diff --git a/Addons/BenchEfficiency/bordeaux_0116.pdf b/Addons/BenchEfficiency/bordeaux_0116.pdf deleted file mode 100644 index c7785df796322f7b6779f10deff6bef7ef3bb436..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/bordeaux_0116.pdf and /dev/null differ diff --git a/Addons/BenchEfficiency/execAllHomogeneous.sh b/Addons/BenchEfficiency/execAllHomogeneous.sh index 483add05b41f306b9bc971e6f943703284e1d028..a4d5899711d3699d8ae5d1d9d223bf67aacf659b 100644 --- a/Addons/BenchEfficiency/execAllHomogeneous.sh +++ b/Addons/BenchEfficiency/execAllHomogeneous.sh @@ -13,14 +13,14 @@ cpu=1 STARPU_NCPUS=$cpu STARPU_NCUDA=0 -logoutput=`./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_SEQ` +logoutput=`./Tests/Release/testBlockedUniformBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_SEQ` if [[ $VERBOSE ]] ; then echo $logoutput fi -$SCALFMM_STARPU_DIR/bin/starpu_fxt_tool -i "/tmp/prof_file_"$USER"_0" +$TUTORIAL_STARPU_DIR/bin/starpu_fxt_tool -i "/tmp/prof_file_"$USER"_0" rec_name="$SCALFMM_RES_DIR/trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_BS_CPU_SEQ-CPU_$cpu.rec" mv trace.rec $rec_name -python $SCALFMM_STARPU_DIR/bin/starpu_trace_state_stats.py -t $rec_name > $rec_name.time +python $TUTORIAL_STARPU_DIR/bin/starpu_trace_state_stats.py -t $rec_name > $rec_name.time for (( cpu=1 ; cpu<=$SCALFMM_MAX_NB_CPU ; cpu++)) ; do @@ -29,13 +29,13 @@ for (( cpu=1 ; cpu<=$SCALFMM_MAX_NB_CPU ; cpu++)) ; do STARPU_NCPUS=$cpu STARPU_NCUDA=0 - logoutput=`./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_PAR` + logoutput=`./Tests/Release/testBlockedUniformBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_PAR` if [[ $VERBOSE ]] ; then echo $logoutput fi - $SCALFMM_STARPU_DIR/bin/starpu_fxt_tool -i "/tmp/prof_file_"$USER"_0" + $TUTORIAL_STARPU_DIR/bin/starpu_fxt_tool -i "/tmp/prof_file_"$USER"_0" rec_name="$SCALFMM_RES_DIR/trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_BS_CPU_PAR-CPU_$cpu.rec" mv trace.rec $rec_name - python $SCALFMM_STARPU_DIR/bin/starpu_trace_state_stats.py -t $rec_name > $rec_name.time + python $TUTORIAL_STARPU_DIR/bin/starpu_trace_state_stats.py -t $rec_name > $rec_name.time done diff --git a/Addons/BenchEfficiency/global-eff.data b/Addons/BenchEfficiency/global-eff.data deleted file mode 100644 index b6c8743f9af5b92d32687ae620f4b810a3bdd682..0000000000000000000000000000000000000000 --- a/Addons/BenchEfficiency/global-eff.data +++ /dev/null @@ -1,25 +0,0 @@ -0 granularity-eff tasks-eff runtime-eff pipeline-eff -1 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 -2 9.588832e-01 9.588832e-01 9.972215e-01 9.999844e-01 -3 9.984195e-01 9.984195e-01 9.992539e-01 9.999840e-01 -4 9.936055e-01 9.936055e-01 9.992505e-01 9.999843e-01 -5 9.859209e-01 9.859209e-01 9.991938e-01 9.999840e-01 -6 9.913540e-01 9.913540e-01 9.992224e-01 9.999848e-01 -7 9.980442e-01 9.980442e-01 9.993216e-01 9.999841e-01 -8 9.932070e-01 9.932070e-01 9.993356e-01 9.999844e-01 -9 9.953908e-01 9.953908e-01 9.993136e-01 9.999852e-01 -10 9.930517e-01 9.930517e-01 9.991280e-01 9.999848e-01 -11 9.937148e-01 9.937148e-01 9.992802e-01 9.999838e-01 -12 9.895039e-01 9.895039e-01 9.992958e-01 9.999842e-01 -13 9.934571e-01 9.934571e-01 9.992770e-01 9.999845e-01 -14 9.939346e-01 9.939346e-01 9.993242e-01 9.999845e-01 -15 9.929928e-01 9.929928e-01 9.993077e-01 9.999849e-01 -16 9.946804e-01 9.946804e-01 9.993051e-01 9.999838e-01 -17 9.959137e-01 9.959137e-01 9.992893e-01 9.999839e-01 -18 9.652375e-01 9.652375e-01 9.961152e-01 9.999832e-01 -19 9.937258e-01 9.937258e-01 9.992987e-01 9.999845e-01 -20 9.949256e-01 9.949256e-01 9.992757e-01 9.999843e-01 -21 9.886613e-01 9.886613e-01 9.992616e-01 9.999838e-01 -22 9.921982e-01 9.921982e-01 9.992499e-01 9.999842e-01 -23 1.001717e+00 1.001717e+00 9.992881e-01 9.999846e-01 -24 9.957642e-01 9.957642e-01 9.992461e-01 9.999836e-01 diff --git a/Addons/BenchEfficiency/global-eff.png b/Addons/BenchEfficiency/global-eff.png deleted file mode 100644 index fc24c14787e6bbc9276edf022a5f81b405a91268..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/global-eff.png and /dev/null differ diff --git a/Addons/BenchEfficiency/mergetimefile.cpp b/Addons/BenchEfficiency/mergetimefile.cpp index 8e781fea5cb538651c7c2fd5e89cd5ede55edaa4..6dcdc96f733833ebb39d516c18224030cfe9c570 100644 --- a/Addons/BenchEfficiency/mergetimefile.cpp +++ b/Addons/BenchEfficiency/mergetimefile.cpp @@ -68,7 +68,7 @@ struct LineData{ } } if(words.size() != 4){ - printf("Error line is no composed of 4 words\n"); + printf("Error line is no composed of 4 words, has %lu for %s\n", words.size(), line); exit(111); } name = ReduceName(words[0].substr(1, words[0].size() - 2)); @@ -186,30 +186,32 @@ int main(int argc, char** argv){ } while((sizeLine = getline((char**)&line, &sizeLine, timeFile)) != -1){ - LineData dt(line); - // Task, Runtime, Other - if(dt.type == "Task"){ - if(dt.name != "execute_on_all_wrapper"){ - timeTasks[idxFile][dt.name] += dt.duration; - allTaskNames.insert(dt.name); - times[idxFile].tt += dt.duration; + if(strncmp(line, "WARNING", 7) != 0){ + LineData dt(line); + // Task, Runtime, Other + if(dt.type == "Task"){ + if(dt.name != "execute_on_all_wrapper"){ + timeTasks[idxFile][dt.name] += dt.duration; + allTaskNames.insert(dt.name); + times[idxFile].tt += dt.duration; + } } - } - else if(dt.type == "Runtime"){ - if(dt.name == "Scheduling" - || dt.name == "FetchingInput" - || dt.name == "PushingOutput"){ - times[idxFile].tr += dt.duration; + else if(dt.type == "Runtime"){ + if(dt.name == "Scheduling" + || dt.name == "FetchingInput" + || dt.name == "PushingOutput"){ + times[idxFile].tr += dt.duration; + } } - } - else if(dt.type == "Other"){ - if(dt.name == "Idle"){ - times[idxFile].ti += dt.duration; + else if(dt.type == "Other"){ + if(dt.name == "Idle"){ + times[idxFile].ti += dt.duration; + } + } + else { + printf("Arg do not know type %s\n", dt.type.c_str()); + //return 3; } - } - else { - printf("Arg do not know type %s\n", dt.type.c_str()); - return 3; } } diff --git a/Addons/BenchEfficiency/par-bs-search.png b/Addons/BenchEfficiency/par-bs-search.png deleted file mode 100644 index 4243937f718415f59047a70a48cb51391dcd223e..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/par-bs-search.png and /dev/null differ diff --git a/Addons/BenchEfficiency/scalfmm.html b/Addons/BenchEfficiency/scalfmm.html deleted file mode 100644 index 3ac064e14379adf390033d3a6632416598dcf5b0..0000000000000000000000000000000000000000 --- a/Addons/BenchEfficiency/scalfmm.html +++ /dev/null @@ -1,594 +0,0 @@ - - - - - scalfmm.html - - - - - - -

ScalFMM with StarPU+CUDA

In this tutorial, we provide the commands to install ScalFMM and the needed tools in order to compute parallel efficiencies.
We first show how to obtain the homogeneous efficencies and then the heterogeneous ones (not done yet).

Installing the libraries

For some installation steps, we provide a “valid-if” test which shows if the previous command has been done correctly or not.
In case of success STEP-OK will be print-out.
In addition, if a library is already installed on the system, it is possible to set the output variables directly and test with the “valid-if” command if it will work.

It is possible to follow these steps only to compile ScalFMM above StarPU and so we marked the installation of execution-trace tools as Optional.
However, we higly recommended to install them and to follow all the steps since they let have the efficiencies.
But if one wants to execute without any overhead, it might need to remove the usage of FXT.

Pre-requiste:

In order to follow this tutorial, it is needed to have the following applications installed:

-

[Remark] Some installations of CUDA does not have libcuda file.
In this case, one needs to create a link : sudo ln /usr/local/cuda-7.5/lib64/libcudart.so /usr/local/cuda-7.5/lib64/libcuda.so

-

[Plafrim-Developers]

-

For those who use this tutorial on Plafrim (or a similar cluster), we provide extra informations.

-

To allocate an heterogeneous node : salloc -N 1 --time=03:00:00 --exclusive -p court_sirocco -CHaswell --gres=gpu:4 -x sirocco06

-

Then, find it using squeue and access it by ssh.

-

We have run this tutorial with the modules : module load compiler/gcc/4.9.2 cuda75/toolkit/7.5.18 intel/mkl/64/11.2/2016.0.0 build/cmake/3.2.1

-

Working directory

The variable SCALFMM_TEST_DIR is used to specify the working directory where all the tools are going to be installed:

export SCALFMM_TEST_DIR=~/scalfmm_test   
-cd $SCALFMM_TEST_DIR
-

In order to be able to stop the tutorial in the middle and restart later, we will register the variables in a file that should be source to restart later:

# function scalfmmRegisterVariable() { echo "export $1=${!1}" >> "$SCALFMM_TEST_DIR/environment.source"; }
-echo "function scalfmmRegisterVariable() { echo \"export \$1=\${!1}\" >> \"$SCALFMM_TEST_DIR/environment.source\"; }" > "$SCALFMM_TEST_DIR/environment.source"
-source "$SCALFMM_TEST_DIR/environment.source"
-

Output variables: scalfmmRegisterVariable SCALFMM_TEST_DIR

Valid-if

if [[ -n $SCALFMM_TEST_DIR ]] && [[ -d $SCALFMM_TEST_DIR ]] ; then
-   echo “STEP-OK”
-fi
-

To restart the tutorial, one needs to re-define the working directory and to source the save file before to resume:

export SCALFMM_TEST_DIR=~/scalfmm_test
-if [[ ! -d $SCALFMM_TEST_DIR ]] ; then
-    mkdir $SCALFMM_TEST_DIR
-else
-    source "$SCALFMM_TEST_DIR/environment.source"
-fi    
-cd $SCALFMM_TEST_DIR
-

Downloading the Packages (in Advance)

If the computational node does not have access to internet, we provide a command to download the needed packages (otherwise the next commands still include just in time download):

cd $SCALFMM_TEST_DIR
-wget https://www.open-mpi.org/software/hwloc/v1.11/downloads/hwloc-1.11.2.tar.gz
-wget http://download.savannah.gnu.org/releases/fkt/fxt-0.2.11.tar.gz # Optional
-wget http://www.fftw.org/fftw-3.3.4.tar.gz
-svn export svn://scm.gforge.inria.fr/svnroot/starpu/trunk starpu
-git clone --depth=1 https://scm.gforge.inria.fr/anonscm/git/scalfmm-public/scalfmm-public.git
-

HWLOC

cd $SCALFMM_TEST_DIR
-if [[ ! -f hwloc-1.11.2.tar.gz ]] ; then
-    wget https://www.open-mpi.org/software/hwloc/v1.11/downloads/hwloc-1.11.2.tar.gz
-fi
-tar xvf hwloc-1.11.2.tar.gz
-cd hwloc-1.11.2/
-export SCALFMM_HWLOC_DIR=$SCALFMM_TEST_DIR/hwlocinstall
-./configure --prefix=$SCALFMM_HWLOC_DIR
-make install
-

Output variables: scalfmmRegisterVariable SCALFMM_HWLOC_DIR

Valid-if:

if [[ -n $SCALFMM_HWLOC_DIR ]] && [[ -d $SCALFMM_HWLOC_DIR/lib/ ]] && [[ -f  $SCALFMM_HWLOC_DIR/lib/libhwloc.so ]]; then
-   echo "STEP-OK"
-fi
-

FXT (Optional)

cd $SCALFMM_TEST_DIR
-if [[ ! -f fxt-0.2.11.tar.gz ]] ; then
-    wget http://download.savannah.gnu.org/releases/fkt/fxt-0.2.11.tar.gz
-fi
-tar xvf fxt-0.2.11.tar.gz
-cd fxt-0.2.11/
-export SCALFMM_FXT_DIR=$SCALFMM_TEST_DIR/fxtinstall
-./configure --prefix=$SCALFMM_FXT_DIR
-make install
-

Output variables: scalfmmRegisterVariable SCALFMM_FXT_DIR

Valid-if:

if [[ -n $SCALFMM_FXT_DIR ]] && [[ -d $SCALFMM_FXT_DIR/lib/ ]] && [[ -f  $SCALFMM_FXT_DIR/lib/libfxt.so ]]; then
-   echo "STEP-OK"
-fi
-

FFTW (If No MKL-FFT)

For those who do not use MKL FFT interface, they have to install FFTW (float/double):

cd $SCALFMM_TEST_DIR
-if [[ ! -f fftw-3.3.4.tar.gz ]] ; then
-    wget http://www.fftw.org/fftw-3.3.4.tar.gz
-fi    
-tar xvf fftw-3.3.4.tar.gz
-cd fftw-3.3.4/
-export SCALFMM_FFTW_DIR=$SCALFMM_TEST_DIR/fftinstall
-./configure --prefix=$SCALFMM_FFTW_DIR
-make install
-./configure --prefix=$SCALFMM_FFTW_DIR --enable-float
-make install
-

Output variables: scalfmmRegisterVariable SCALFMM_FFTW_DIR

Valid-if:

if [[ -n $SCALFMM_FFTW_DIR ]] && [[ -d $SCALFMM_FFTW_DIR/lib/ ]] && [[ -f  $SCALFMM_FFTW_DIR/lib/libfftw3.a ]] && [[ -f  $SCALFMM_FFTW_DIR/lib/libfftw3f.a ]]; then
-   echo "STEP-OK"
-fi
-

StarPU

cd $SCALFMM_TEST_DIR
-if [[ ! -d starpu ]] ; then
-    svn export svn://scm.gforge.inria.fr/svnroot/starpu/trunk starpu
-fi    
-cd starpu/
-export SCALFMM_STARPU_DIR=$SCALFMM_TEST_DIR/starpuinstall
-./autogen.sh
-./configure --prefix=$SCALFMM_STARPU_DIR --with-fxt=$SCALFMM_FXT_DIR --with-hwloc=$SCALFMM_HWLOC_DIR --with-cuda-dir=$CUDA_PATH --disable-opencl
-make install
-
-

Optional In case you do not want to use trace (FXT) please remove the --with-fxt=$SCALFMM_FXT_DIR parameter from the command

-

Output variables: scalfmmRegisterVariable SCALFMM_STARPU_DIR

Valid-if:

if [[ -n $SCALFMM_STARPU_DIR ]] && [[ -d $SCALFMM_STARPU_DIR/lib/ ]] && [[ -f  $SCALFMM_STARPU_DIR/lib/libstarpu.so ]] ; then
-   echo "STEP-OK"
-fi
-

ScalFMM

Configure

Output variables: scalfmmRegisterVariable SCALFMM_BUILD_DIR scalfmmRegisterVariable SCALFMM_SOURCE_DIR

-

[Plafrim-Developers] Should use that one

-
cmake .. -DSCALFMM_BUILD_DEBUG=OFF -DSCALFMM_USE_MPI=OFF \
-               -DSCALFMM_BUILD_TESTS=ON -DSCALFMM_BUILD_UTESTS=OFF \
-               -DSCALFMM_USE_BLAS=ON -DSCALFMM_USE_MKL_AS_BLAS=ON \
-               -DSCALFMM_USE_LOG=ON -DSCALFMM_USE_STARPU=ON \
-               -DSCALFMM_USE_CUDA=ON -DSCALFMM_USE_OPENCL=OFF \
-               -DHWLOC_DIR=$SCALFMM_HWLOC_DIR -DSTARPU_DIR=$SCALFMM_STARPU_DIR \
-               -DSCALFMM_USE_FFT=ON -DSCALFMM_USE_MKL_AS_FFTW=ON
-

Valid-if:

cmake .. ; if [[ "$?" == "0" ]] ; then echo "STEP-OK" ; fi
-

Build

cd $SCALFMM_BUILD_DIR
-make testBlockedUnifCudaBench
-

Valid-if:

ls ./Tests/Release/testBlockedUnifCudaBench ; if [[ "$?" == "0" ]] ; then echo "STEP-OK" ; fi
-

First Execution

In this section we compute a simulation and look at the resulting trace.
ScalFMM binary parameters and descriptions:

Examples:

export STARPU_NCPUS=12
-export STARPU_NCUDA=2
-./Tests/Release/testBlockedUnifCudaBench -nb 30000000 -h 7 -bs 800
-

Last part of the output should be:

    Start FGroupTaskStarPUAlgorithm
-         directPass in 0.0406482s
-             inblock  in 0.000780428s
-             outblock in 0.0398674s
-         bottomPass in 0.00586269s
-         upwardPass in 0.00265723s
-         transferPass in 0.00323571s
-             inblock in  0.000124817s
-             outblock in 0.00298331s
-         downardPass in 0.00257975s
-         transferPass in 0.0652285s
-             inblock in  0.00164774s
-             outblock in 0.0635799s
-         L2P in 0.0115733s
-         Submitting the tasks took 0.139101s
-         Moving data to the host took 0.0578765s
-@EXEC TIME = 14.6321s
-

Convert the fxt file

$SCALFMM_STARPU_DIR/bin/starpu_fxt_tool -i "/tmp/prof_file_"$USER"_0"
-

Then visualize the output with vite (maybe by copying the paje.trace file locally)

vite ./paje.trace
-

Should be like:
Trace

We can convert the color of the trace by (requiere Qt5 library):

$SCALFMM_SOURCE_DIR/Addons/BenchEfficiency/pajecolor paje.trace $SCALFMM_SOURCE_DIR/Addons/BenchEfficiency/paintmodel.fmm.colors
-vite ./paje.trace.painted
-

Should be like:
Trace

python $SCALFMM_STARPU_DIR/bin/starpu_trace_state_stats.py -t trace.rec
-

Should give something like:

"Name","Count","Type","Duration"
-"Initializing",14,"Runtime",7153.096196
-"Overhead",57010,"Runtime",376.473463
-"Idle",14355,"Other",12.815899
-"Scheduling",28441,"Runtime",238.367394
-"Sleeping",610,"Other",13786.513208
-"FetchingInput",14341,"Runtime",13918.805814
-"execute_on_all_wrapper",30,"Task",21.288802
-"Executing",414,"Runtime",26852.864578
-"PushingOutput",14341,"Runtime",284.96123
-"P2P-out",3846,"Task",60378.266619
-"Callback",13559,"Runtime",4.210633
-"P2P",328,"Task",15383.426991
-"M2L-level-5",41,"Task",2354.702554
-"M2L-level-6",328,"Task",18349.915495
-"Deinitializing",14,"Runtime",109.87483
-"M2L-level-4",6,"Task",275.088295
-"P2M",328,"Task",11312.022842
-"M2M-level-5",328,"Task",829.9055
-"M2M-level-4",41,"Task",93.130498
-"M2L-out-level-5",638,"Task",1914.900053
-"M2M-level-3",6,"Task",11.053067
-"M2M-level-2",1,"Task",1.363157
-"M2L-out-level-4",22,"Task",159.580457
-"L2L-level-4",41,"Task",84.554065
-"L2L-level-5",328,"Task",1087.717767
-"M2L-out-level-6",7692,"Task",18322.518045
-"L2P",328,"Task",27146.256793
-"M2L-level-2",1,"Task",2.661235
-"L2L-level-3",6,"Task",11.346978
-"M2L-level-3",1,"Task",47.612555
-"L2L-level-2",1,"Task",1.471873
-

Most of the script are in the addon directories

export SCALFMM_AB=$SCALFMM_SOURCE_DIR/Addons/BenchEfficiency/
-

Output variable: scalfmmRegisterVariable SCALFMM_AB

Homogeneous Efficiencies

Here we compute the efficiencies for a given test case on CPU only.

Go in the build dir and create output dir

cd $SCALFMM_BUILD_DIR
-export SCALFMM_RES_DIR=$SCALFMM_BUILD_DIR/homogeneous
-mkdir $SCALFMM_RES_DIR
-

Output variable: scalfmmRegisterVariable SCALFMM_RES_DIR

Set up the configuration variables:

export SCALFMM_NB=10000000
-export SCALFMM_H=7
-export SCALFMM_MIN_BS=100
-export SCALFMM_MAX_BS=10000
-export SCALFMM_MAX_NB_CPU=24
-

Find best granularity in sequential and in parallel:

export STARPU_NCPUS=1
-export STARPU_NCUDA=0
-export SCALFMM_BS_CPU_SEQ=`$SCALFMM_AB/scalfmmFindBs.sh "./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs" $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmmExtractKey.sh "@BEST BS" `
-if [[ `which gnuplot | wc -l` == "1" ]] ;  then
-    gnuplot -e "filename='seq-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot
-fi
-
-export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU
-export STARPU_NCUDA=0
-export SCALFMM_BS_CPU_PAR=`$SCALFMM_AB/scalfmmFindBs.sh "./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs" $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" `
-if [[ `which gnuplot | wc -l` == "1" ]] ;  then
-    gnuplot -e "filename='par-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot
-fi
-

In our case we get 9710 and 5385.

Output variable: scalfmmRegisterVariable SCALFMM_BS_CPU_SEQ scalfmmRegisterVariable SCALFMM_BS_CPU_PAR

We can look to the work that has been done to find the best granularity:
In sequential
In parallel

Then we compute the efficiency using both granulirities and keep the .rec files:

export SCALFMM_MAX_NB_CPU=24
-export STARPU_NCUDA=0
-source "$SCALFMM_AB/execAllHomogeneous.sh"
-

We should end with all the .rec files and their corresponding time files and ls "$SCALFMM_RES_DIR" should return something like:

trace-nb_10000000-h_7-bs_5385-CPU_10.rec       trace-nb_10000000-h_7-bs_5385-CPU_16.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_22.rec       trace-nb_10000000-h_7-bs_5385-CPU_5.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_10.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_17.rec       trace-nb_10000000-h_7-bs_5385-CPU_22.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_6.rec
-trace-nb_10000000-h_7-bs_5385-CPU_11.rec       trace-nb_10000000-h_7-bs_5385-CPU_17.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_23.rec       trace-nb_10000000-h_7-bs_5385-CPU_6.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_11.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_18.rec       trace-nb_10000000-h_7-bs_5385-CPU_23.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_7.rec
-trace-nb_10000000-h_7-bs_5385-CPU_12.rec       trace-nb_10000000-h_7-bs_5385-CPU_18.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_24.rec       trace-nb_10000000-h_7-bs_5385-CPU_7.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_12.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_19.rec       trace-nb_10000000-h_7-bs_5385-CPU_24.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_8.rec
-trace-nb_10000000-h_7-bs_5385-CPU_13.rec       trace-nb_10000000-h_7-bs_5385-CPU_19.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_2.rec        trace-nb_10000000-h_7-bs_5385-CPU_8.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_13.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_1.rec        trace-nb_10000000-h_7-bs_5385-CPU_2.rec.time   trace-nb_10000000-h_7-bs_5385-CPU_9.rec
-trace-nb_10000000-h_7-bs_5385-CPU_14.rec       trace-nb_10000000-h_7-bs_5385-CPU_1.rec.time   trace-nb_10000000-h_7-bs_5385-CPU_3.rec        trace-nb_10000000-h_7-bs_5385-CPU_9.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_14.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_20.rec       trace-nb_10000000-h_7-bs_5385-CPU_3.rec.time   trace-nb_10000000-h_7-bs_9710-CPU_1.rec
-trace-nb_10000000-h_7-bs_5385-CPU_15.rec       trace-nb_10000000-h_7-bs_5385-CPU_20.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_4.rec        trace-nb_10000000-h_7-bs_9710-CPU_1.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_15.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_21.rec       trace-nb_10000000-h_7-bs_5385-CPU_4.rec.time
-trace-nb_10000000-h_7-bs_5385-CPU_16.rec       trace-nb_10000000-h_7-bs_5385-CPU_21.rec.time  trace-nb_10000000-h_7-bs_5385-CPU_5.rec
-

We then compute the efficiencies from these files

g++ -std=c++11 $SCALFMM_AB/mergetimefile.cpp -o $SCALFMM_AB/mergetimefile.exe
-$SCALFMM_AB/mergetimefile.exe \
-        "$SCALFMM_RES_DIR/trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_BS_CPU_SEQ-CPU_1.rec.time" \
-        "$SCALFMM_RES_DIR/trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_BS_CPU_PAR-CPU_%d.rec.time"\
-         $SCALFMM_MAX_NB_CPU
-

We end-up with the global efficiencies (for the application) but also for the different operators.

Create global-eff.data
-Create task-eff.data
-Create task-gr-eff.dat
-

We can plot each of them

gnuplot -e "filename='global-eff'" $SCALFMM_AB/scalfmmPlotAll.gplot
-gnuplot -e "filename='task-eff'" $SCALFMM_AB/scalfmmPlotAll.gplot
-gnuplot -e "filename='task-gr-eff'" $SCALFMM_AB/scalfmmPlotAll.gplot
-

In our case it gives:
global-eff
task-eff
task-gr-eff

Heterogeneous

NOT FINISHED!!!!

For test case -nb 10000000 (10 million) and -h 6 (height of the tree equal to 6),
we first want to know the best granularity -bs.

This parameter will certainly not be the same for sequential/parallel/heterogenous configurations.

export SCALFMM_NB=10000000
-export SCALFMM_H=7
-export SCALFMM_MIN_BS=100
-export SCALFMM_MAX_BS=3000
-export SCALFMM_MAX_NB_CPU=24
-export SCALFMM_MAX_NB_GPU=4
-
export STARPU_NCPUS=1
-export STARPU_NCUDA=0
-export SCALFMM_BS_CPU_SEQ=`$SCALFMM_AB/scalfmmFindBs.sh -nb $SCALFMM_NB -h $SCALFMM_H $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" `
-if [[ `which gnuplot | wc -l` == "1" ]] ;  then
-    gnuplot -e "filename='seq-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot
-fi
-
-export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU
-export STARPU_NCUDA=0
-export SCALFMM_BS_CPU_PAR=`$SCALFMM_AB/scalfmmFindBs.sh -nb $SCALFMM_NB -h $SCALFMM_H $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" `
-if [[ `which gnuplot | wc -l` == "1" ]] ;  then
-    gnuplot -e "filename='par-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot
-fi
-
-export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU
-export STARPU_NCUDA=$SCALFMM_MAX_NB_GPU
-export SCALFMM_BS_CPU_GPU=`$SCALFMM_AB/scalfmmFindBs.sh -nb $SCALFMM_NB -h $SCALFMM_H $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" `
-if [[ `which gnuplot | wc -l` == "1" ]] ;  then
-    gnuplot -e "filename='cpugpu-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot
-fi
-

Then, we can execute three best configurations, and keep .rec for each of them:

export STARPU_NCPUS=1
-export STARPU_NCUDA=0
-./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_CPU_SEQ
-export SCALFMM_SEQ_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec"
-mv trace.rec $SCALFMM_SEQ_REC
-
-export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU
-export STARPU_NCUDA=0
-./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_PAR
-export SCALFMM_PAR_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec"
-mv trace.rec $SCALFMM_PAR_REC
-
-export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU
-export STARPU_NCUDA=$SCALFMM_MAX_NB_GPU
-./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_GPU
-export SCALFMM_PAR_CPU_GPU_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec"
-mv trace.rec $SCALFMM_PAR_CPU_GPU_REC
-

And we also want the GPU tasks only on GPU

export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU
-export STARPU_NCUDA=$SCALFMM_MAX_NB_GPU
-./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_GPU -p2p-m2l-cuda-only
-export SCALFMM_PAR_GPU_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA-GPUONLY.rec"
-mv trace.rec $SCALFMM_PAR_GPU_REC
-

And we want the sequential version with parallel granularity:

export STARPU_NCPUS=1
-export STARPU_NCUDA=0
-
-./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_PAR
-SCALFMM_SEQ_CPU_BS_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec"
-mv trace.rec $SCALFMM_SEQ_CPU_BS_REC
-
-./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_GPU
-SCALFMM_SEQ_GPU_BS_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec"
-mv trace.rec $SCALFMM_SEQ_GPU_BS_REC
-

From these files, we are able to get the different efficencies.

Post-processing and Plot

From the file:

Getting all the efficency
Solving the linear programming problem

Plotting the results

Automatization

SCALFMM_NB=10000000
-SCALFMM_H=7
-SCALFMM_MIN_BS=100
-SCALFMM_MAX_BS=3000
-SCALFMM_MAX_NB_CPU=24
-SCALFMM_MAX_NB_GPU=4
-
-scalfmm_generate_efficiency -nb $SCALFMM_NB -h $SCALFMM_H -start $SCALFMM_MIN_BS -end $SCALFMM_MAX_BS
-
- - - - diff --git a/Addons/BenchEfficiency/scalfmm.md b/Addons/BenchEfficiency/scalfmm.md deleted file mode 100644 index 0cf00f00e179fba2cfd4d579d4aa97712394876d..0000000000000000000000000000000000000000 --- a/Addons/BenchEfficiency/scalfmm.md +++ /dev/null @@ -1,585 +0,0 @@ -ScalFMM with StarPU+CUDA -======================== - -In this tutorial, we provide the commands to install ScalFMM and the needed tools in order to compute parallel efficiencies. -We first show how to obtain the homogeneous efficencies and then the heterogeneous ones (not done yet). - -## Installing the libraries - -For some installation steps, we provide a "valid-if" test which shows if the previous command has been done correctly or not. -In case of success `STEP-OK` will be print-out. -In addition, if a library is already installed on the system, it is possible to set the output variables directly and test with the "valid-if" command if it will work. - -It is possible to follow these steps only to compile ScalFMM above StarPU and so we marked the installation of execution-trace tools as __Optional__. -However, we higly recommended to install them and to follow all the steps since they let have the efficiencies. -But if one wants to execute without any overhead, it might need to remove the usage of FXT. - -### Pre-requiste: -In order to follow this tutorial, it is needed to have the following applications installed: - -* autoconf (>= 2.69) -* gawk (Awk >= 4.0.1) -* make (>= 3.81) -* cmake (>= 3.2.2) -* gcc/g++ (>= 4.9) and the gcc/g++ names should point to the correct binaries -* BLAS/LAPACK (The configure of ScalFMM is different if the MKL is used or not, but with the MKL it is recommended to set environment variable `MKLROOT`) -* CUDA (>= 7) and `CUDA_PATH` must be set. In our case, `CUDA_PATH=/usr/local/cuda-7.5/` -* __Optional__ Vite (from `sudo apt-get install vite` or see [http://vite.gforge.inria.fr/download.php](http://vite.gforge.inria.fr/download.php)) -* __Optional__ Qt5 library to be able to change the colors of the execution traces in order to visualize the different FMM operators -* gnuplot to generate the figures - -> [Remark] Some installations of CUDA does not have libcuda file. -> In this case, one needs to create a link : `sudo ln /usr/local/cuda-7.5/lib64/libcudart.so /usr/local/cuda-7.5/lib64/libcuda.so` - -> [Plafrim-Developers] -> -> For those who use this tutorial on Plafrim (or a similar cluster), we provide extra informations. -> -> To allocate an heterogeneous node : `salloc -N 1 --time=03:00:00 --exclusive -p court_sirocco -CHaswell --gres=gpu:4 -x sirocco06` -> -> Then, find it using `squeue` and access it by `ssh`. -> -> We have run this tutorial with the modules : `module load compiler/gcc/4.9.2 cuda75/toolkit/7.5.18 intel/mkl/64/11.2/2016.0.0 build/cmake/3.2.1` - -### Working directory - -The variable `SCALFMM_TEST_DIR` is used to specify the working directory where all the tools are going to be installed: -```bash -export SCALFMM_TEST_DIR=~/scalfmm_test -cd $SCALFMM_TEST_DIR -``` - -In order to be able to stop the tutorial in the middle and restart later, we will register the variables in a file that should be source to restart later: -```bash -# function scalfmmRegisterVariable() { echo "export $1=${!1}" >> "$SCALFMM_TEST_DIR/environment.source"; } -echo "function scalfmmRegisterVariable() { echo \"export \$1=\${!1}\" >> \"$SCALFMM_TEST_DIR/environment.source\"; }" > "$SCALFMM_TEST_DIR/environment.source" -source "$SCALFMM_TEST_DIR/environment.source" -``` - -*Output variables:* `scalfmmRegisterVariable SCALFMM_TEST_DIR` - -Valid-if -```bash -if [[ -n $SCALFMM_TEST_DIR ]] && [[ -d $SCALFMM_TEST_DIR ]] ; then - echo “STEP-OK” -fi -``` - -- Restarting the tutorial - -To restart the tutorial, one needs to re-define the working directory and to source the save file before to resume: -```bash -export SCALFMM_TEST_DIR=~/scalfmm_test -if [[ ! -d $SCALFMM_TEST_DIR ]] ; then - mkdir $SCALFMM_TEST_DIR -else - source "$SCALFMM_TEST_DIR/environment.source" -fi -cd $SCALFMM_TEST_DIR -``` - -### Downloading the Packages (in Advance) - -If the computational node does not have access to internet, we provide a command to download the needed packages (otherwise the next commands still include just in time download): -```bash -cd $SCALFMM_TEST_DIR -wget https://www.open-mpi.org/software/hwloc/v1.11/downloads/hwloc-1.11.2.tar.gz -wget http://download.savannah.gnu.org/releases/fkt/fxt-0.2.11.tar.gz # Optional -wget http://www.fftw.org/fftw-3.3.4.tar.gz -svn export svn://scm.gforge.inria.fr/svnroot/starpu/trunk starpu -git clone --depth=1 https://scm.gforge.inria.fr/anonscm/git/scalfmm-public/scalfmm-public.git -``` - -### HWLOC -```bash -cd $SCALFMM_TEST_DIR -if [[ ! -f hwloc-1.11.2.tar.gz ]] ; then - wget https://www.open-mpi.org/software/hwloc/v1.11/downloads/hwloc-1.11.2.tar.gz -fi -tar xvf hwloc-1.11.2.tar.gz -cd hwloc-1.11.2/ -export SCALFMM_HWLOC_DIR=$SCALFMM_TEST_DIR/hwlocinstall -./configure --prefix=$SCALFMM_HWLOC_DIR -make install -``` - -*Output variables:* `scalfmmRegisterVariable SCALFMM_HWLOC_DIR` - -Valid-if: -```bash -if [[ -n $SCALFMM_HWLOC_DIR ]] && [[ -d $SCALFMM_HWLOC_DIR/lib/ ]] && [[ -f $SCALFMM_HWLOC_DIR/lib/libhwloc.so ]]; then - echo "STEP-OK" -fi -``` - -### FXT (__Optional__) -```bash -cd $SCALFMM_TEST_DIR -if [[ ! -f fxt-0.2.11.tar.gz ]] ; then - wget http://download.savannah.gnu.org/releases/fkt/fxt-0.2.11.tar.gz -fi -tar xvf fxt-0.2.11.tar.gz -cd fxt-0.2.11/ -export SCALFMM_FXT_DIR=$SCALFMM_TEST_DIR/fxtinstall -./configure --prefix=$SCALFMM_FXT_DIR -make install -``` - -*Output variables:* `scalfmmRegisterVariable SCALFMM_FXT_DIR` - -Valid-if: -```bash -if [[ -n $SCALFMM_FXT_DIR ]] && [[ -d $SCALFMM_FXT_DIR/lib/ ]] && [[ -f $SCALFMM_FXT_DIR/lib/libfxt.so ]]; then - echo "STEP-OK" -fi -``` - -### FFTW (If No MKL-FFT) -For those who do not use MKL FFT interface, they have to install FFTW (float/double): -```bash -cd $SCALFMM_TEST_DIR -if [[ ! -f fftw-3.3.4.tar.gz ]] ; then - wget http://www.fftw.org/fftw-3.3.4.tar.gz -fi -tar xvf fftw-3.3.4.tar.gz -cd fftw-3.3.4/ -export SCALFMM_FFTW_DIR=$SCALFMM_TEST_DIR/fftinstall -./configure --prefix=$SCALFMM_FFTW_DIR -make install -./configure --prefix=$SCALFMM_FFTW_DIR --enable-float -make install -``` - -*Output variables:* `scalfmmRegisterVariable SCALFMM_FFTW_DIR` - -Valid-if: -```bash -if [[ -n $SCALFMM_FFTW_DIR ]] && [[ -d $SCALFMM_FFTW_DIR/lib/ ]] && [[ -f $SCALFMM_FFTW_DIR/lib/libfftw3.a ]] && [[ -f $SCALFMM_FFTW_DIR/lib/libfftw3f.a ]]; then - echo "STEP-OK" -fi -``` - -### StarPU -```bash -cd $SCALFMM_TEST_DIR -if [[ ! -d starpu ]] ; then - svn export svn://scm.gforge.inria.fr/svnroot/starpu/trunk starpu -fi -cd starpu/ -export SCALFMM_STARPU_DIR=$SCALFMM_TEST_DIR/starpuinstall -./autogen.sh -./configure --prefix=$SCALFMM_STARPU_DIR --with-fxt=$SCALFMM_FXT_DIR --with-hwloc=$SCALFMM_HWLOC_DIR --with-cuda-dir=$CUDA_PATH --disable-opencl -make install -``` -> __Optional__ In case you do not want to use trace (FXT) please remove the `--with-fxt=$SCALFMM_FXT_DIR` parameter from the command - -*Output variables:* `scalfmmRegisterVariable SCALFMM_STARPU_DIR` - -Valid-if: -```bash -if [[ -n $SCALFMM_STARPU_DIR ]] && [[ -d $SCALFMM_STARPU_DIR/lib/ ]] && [[ -f $SCALFMM_STARPU_DIR/lib/libstarpu.so ]] ; then - echo "STEP-OK" -fi -``` - -### ScalFMM - -#### Configure -+ Getting the source from the last commit: -```bash -cd $SCALFMM_TEST_DIR -if [[ ! -d scalfmm-public ]] ; then - git clone --depth=1 https://scm.gforge.inria.fr/anonscm/git/scalfmm-public/scalfmm-public.git -fi -cd scalfmm-public/ -export SCALFMM_SOURCE_DIR=`pwd` -cd Build/ -export SCALFMM_BUILD_DIR=`pwd` -``` - -*Output variables:* `scalfmmRegisterVariable SCALFMM_BUILD_DIR` `scalfmmRegisterVariable SCALFMM_SOURCE_DIR` - -+ Configure (No MKL): -```bash -cmake .. -DSCALFMM_BUILD_DEBUG=OFF -DSCALFMM_USE_MPI=OFF \ - -DSCALFMM_BUILD_TESTS=ON -DSCALFMM_BUILD_UTESTS=OFF \ - -DSCALFMM_USE_BLAS=ON -DSCALFMM_USE_MKL_AS_BLAS=OFF \ - -DSCALFMM_USE_LOG=ON -DSCALFMM_USE_STARPU=ON \ - -DSCALFMM_USE_CUDA=ON -DSCALFMM_USE_OPENCL=OFF \ - -DHWLOC_DIR=$SCALFMM_HWLOC_DIR -DSTARPU_DIR=$SCALFMM_STARPU_DIR \ - -DSCALFMM_USE_FFT=ON -DFFT_DIR=$SCALFMM_FFT_DIR -``` -+ Configure (MKL BLAS/LAPACK and FFTW): -```bash -cmake .. -DSCALFMM_BUILD_DEBUG=OFF -DSCALFMM_USE_MPI=OFF \ - -DSCALFMM_BUILD_TESTS=ON -DSCALFMM_BUILD_UTESTS=OFF \ - -DSCALFMM_USE_BLAS=ON -DSCALFMM_USE_MKL_AS_BLAS=ON \ - -DSCALFMM_USE_LOG=ON -DSCALFMM_USE_STARPU=ON \ - -DSCALFMM_USE_CUDA=ON -DSCALFMM_USE_OPENCL=OFF \ - -DHWLOC_DIR=$SCALFMM_HWLOC_DIR -DSTARPU_DIR=$SCALFMM_STARPU_DIR \ - -DSCALFMM_USE_FFT=ON -DFFT_DIR=$SCALFMM_FFT_DIR -``` -+ Configure (MKL BLAS/LAPACK/FFT and No FFTW): - -> [Plafrim-Developers] Should use that one - -```bash -cmake .. -DSCALFMM_BUILD_DEBUG=OFF -DSCALFMM_USE_MPI=OFF \ - -DSCALFMM_BUILD_TESTS=ON -DSCALFMM_BUILD_UTESTS=OFF \ - -DSCALFMM_USE_BLAS=ON -DSCALFMM_USE_MKL_AS_BLAS=ON \ - -DSCALFMM_USE_LOG=ON -DSCALFMM_USE_STARPU=ON \ - -DSCALFMM_USE_CUDA=ON -DSCALFMM_USE_OPENCL=OFF \ - -DHWLOC_DIR=$SCALFMM_HWLOC_DIR -DSTARPU_DIR=$SCALFMM_STARPU_DIR \ - -DSCALFMM_USE_FFT=ON -DSCALFMM_USE_MKL_AS_FFTW=ON -``` - -Valid-if: -```bash -cmake .. ; if [[ "$?" == "0" ]] ; then echo "STEP-OK" ; fi -``` - -#### Build - -```bash -cd $SCALFMM_BUILD_DIR -make testBlockedUnifCudaBench -``` - -Valid-if: -```bash -ls ./Tests/Release/testBlockedUnifCudaBench ; if [[ "$?" == "0" ]] ; then echo "STEP-OK" ; fi -``` - -#### First Execution - -In this section we compute a simulation and look at the resulting trace. -ScalFMM binary parameters and descriptions: - -* Passing `--help` as parameter provide the possible/valid parameters -* Simulation properties are choosen by : - * `-h` : height of the tree - * `-bs` : granularity/size of the group - * `-nb` : number of particles generated -* Execution properties are choosen by the StarPU environment variables : - * `STARPU_NCPUS` : the number of CPU workers - * `STARPU_NCUDA` : the number of GPU workers (for heterogeneous binary) -* By default the application will not compare the FMM interactions against the direct method (which is N^2) and so it is recommended to avoid the validation for large test cases. But to get the accuracy one must pass the parameter `-validation` -* `-p2p-m2l-cuda-only` : to compute the P2P and the M2L only on GPU (the rest on the CPU) - -Examples: - -```bash -export STARPU_NCPUS=12 -export STARPU_NCUDA=2 -./Tests/Release/testBlockedUnifCudaBench -nb 30000000 -h 7 -bs 800 -``` - -Last part of the output should be: -```bash - Start FGroupTaskStarPUAlgorithm - directPass in 0.0406482s - inblock in 0.000780428s - outblock in 0.0398674s - bottomPass in 0.00586269s - upwardPass in 0.00265723s - transferPass in 0.00323571s - inblock in 0.000124817s - outblock in 0.00298331s - downardPass in 0.00257975s - transferPass in 0.0652285s - inblock in 0.00164774s - outblock in 0.0635799s - L2P in 0.0115733s - Submitting the tasks took 0.139101s - Moving data to the host took 0.0578765s -@EXEC TIME = 14.6321s -``` - -+ Visualize the execution trace (__Optional__) - -Convert the fxt file -```bash -$SCALFMM_STARPU_DIR/bin/starpu_fxt_tool -i "/tmp/prof_file_"$USER"_0" -``` -Then visualize the output with `vite` (maybe by copying the paje.trace file locally) -```bash -vite ./paje.trace -``` - -Should be like: -![Trace](trace-example.png) - -We can convert the color of the trace by (requiere Qt5 library): - -```bash -$SCALFMM_SOURCE_DIR/Addons/BenchEfficiency/pajecolor paje.trace $SCALFMM_SOURCE_DIR/Addons/BenchEfficiency/paintmodel.fmm.colors -vite ./paje.trace.painted -``` - -Should be like: -![Trace](trace-example-colors.png) - -+ Get execution times - -```bash -python $SCALFMM_STARPU_DIR/bin/starpu_trace_state_stats.py -t trace.rec -``` - -Should give something like: -``` -"Name","Count","Type","Duration" -"Initializing",14,"Runtime",7153.096196 -"Overhead",57010,"Runtime",376.473463 -"Idle",14355,"Other",12.815899 -"Scheduling",28441,"Runtime",238.367394 -"Sleeping",610,"Other",13786.513208 -"FetchingInput",14341,"Runtime",13918.805814 -"execute_on_all_wrapper",30,"Task",21.288802 -"Executing",414,"Runtime",26852.864578 -"PushingOutput",14341,"Runtime",284.96123 -"P2P-out",3846,"Task",60378.266619 -"Callback",13559,"Runtime",4.210633 -"P2P",328,"Task",15383.426991 -"M2L-level-5",41,"Task",2354.702554 -"M2L-level-6",328,"Task",18349.915495 -"Deinitializing",14,"Runtime",109.87483 -"M2L-level-4",6,"Task",275.088295 -"P2M",328,"Task",11312.022842 -"M2M-level-5",328,"Task",829.9055 -"M2M-level-4",41,"Task",93.130498 -"M2L-out-level-5",638,"Task",1914.900053 -"M2M-level-3",6,"Task",11.053067 -"M2M-level-2",1,"Task",1.363157 -"M2L-out-level-4",22,"Task",159.580457 -"L2L-level-4",41,"Task",84.554065 -"L2L-level-5",328,"Task",1087.717767 -"M2L-out-level-6",7692,"Task",18322.518045 -"L2P",328,"Task",27146.256793 -"M2L-level-2",1,"Task",2.661235 -"L2L-level-3",6,"Task",11.346978 -"M2L-level-3",1,"Task",47.612555 -"L2L-level-2",1,"Task",1.471873 -``` - -Most of the script are in the addon directories -```bash -export SCALFMM_AB=$SCALFMM_SOURCE_DIR/Addons/BenchEfficiency/ -``` - -*Output variable:* `scalfmmRegisterVariable SCALFMM_AB` - -## Homogeneous Efficiencies - -Here we compute the efficiencies for a given test case on CPU only. - -Go in the build dir and create output dir -```bash -cd $SCALFMM_BUILD_DIR -export SCALFMM_RES_DIR=$SCALFMM_BUILD_DIR/homogeneous -mkdir $SCALFMM_RES_DIR -``` -*Output variable:* `scalfmmRegisterVariable SCALFMM_RES_DIR` - -Set up the configuration variables: -```bash -export SCALFMM_NB=10000000 -export SCALFMM_H=7 -export SCALFMM_MIN_BS=100 -export SCALFMM_MAX_BS=10000 -export SCALFMM_MAX_NB_CPU=24 -``` - -Find best granularity in sequential and in parallel: -```bash -export STARPU_NCPUS=1 -export STARPU_NCUDA=0 -export SCALFMM_BS_CPU_SEQ=`$SCALFMM_AB/scalfmmFindBs.sh "./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs" $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmmExtractKey.sh "@BEST BS" ` -if [[ `which gnuplot | wc -l` == "1" ]] ; then - gnuplot -e "filename='seq-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot -fi - -export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU -export STARPU_NCUDA=0 -export SCALFMM_BS_CPU_PAR=`$SCALFMM_AB/scalfmmFindBs.sh "./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs" $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" ` -if [[ `which gnuplot | wc -l` == "1" ]] ; then - gnuplot -e "filename='par-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot -fi -``` -In our case we get 9710 and 5385. - -*Output variable:* `scalfmmRegisterVariable SCALFMM_BS_CPU_SEQ` `scalfmmRegisterVariable SCALFMM_BS_CPU_PAR` - -We can look to the work that has been done to find the best granularity: -![In sequential](seq-bs-search.png) -![In parallel](par-bs-search.png) - - -Then we compute the efficiency using both granulirities and keep the .rec files: -```bash -export SCALFMM_MAX_NB_CPU=24 -export STARPU_NCUDA=0 -source "$SCALFMM_AB/execAllHomogeneous.sh" -``` - -We should end with all the .rec files and their corresponding time files and `ls "$SCALFMM_RES_DIR"` should return something like: -```bash -trace-nb_10000000-h_7-bs_5385-CPU_10.rec trace-nb_10000000-h_7-bs_5385-CPU_16.rec.time trace-nb_10000000-h_7-bs_5385-CPU_22.rec trace-nb_10000000-h_7-bs_5385-CPU_5.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_10.rec.time trace-nb_10000000-h_7-bs_5385-CPU_17.rec trace-nb_10000000-h_7-bs_5385-CPU_22.rec.time trace-nb_10000000-h_7-bs_5385-CPU_6.rec -trace-nb_10000000-h_7-bs_5385-CPU_11.rec trace-nb_10000000-h_7-bs_5385-CPU_17.rec.time trace-nb_10000000-h_7-bs_5385-CPU_23.rec trace-nb_10000000-h_7-bs_5385-CPU_6.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_11.rec.time trace-nb_10000000-h_7-bs_5385-CPU_18.rec trace-nb_10000000-h_7-bs_5385-CPU_23.rec.time trace-nb_10000000-h_7-bs_5385-CPU_7.rec -trace-nb_10000000-h_7-bs_5385-CPU_12.rec trace-nb_10000000-h_7-bs_5385-CPU_18.rec.time trace-nb_10000000-h_7-bs_5385-CPU_24.rec trace-nb_10000000-h_7-bs_5385-CPU_7.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_12.rec.time trace-nb_10000000-h_7-bs_5385-CPU_19.rec trace-nb_10000000-h_7-bs_5385-CPU_24.rec.time trace-nb_10000000-h_7-bs_5385-CPU_8.rec -trace-nb_10000000-h_7-bs_5385-CPU_13.rec trace-nb_10000000-h_7-bs_5385-CPU_19.rec.time trace-nb_10000000-h_7-bs_5385-CPU_2.rec trace-nb_10000000-h_7-bs_5385-CPU_8.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_13.rec.time trace-nb_10000000-h_7-bs_5385-CPU_1.rec trace-nb_10000000-h_7-bs_5385-CPU_2.rec.time trace-nb_10000000-h_7-bs_5385-CPU_9.rec -trace-nb_10000000-h_7-bs_5385-CPU_14.rec trace-nb_10000000-h_7-bs_5385-CPU_1.rec.time trace-nb_10000000-h_7-bs_5385-CPU_3.rec trace-nb_10000000-h_7-bs_5385-CPU_9.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_14.rec.time trace-nb_10000000-h_7-bs_5385-CPU_20.rec trace-nb_10000000-h_7-bs_5385-CPU_3.rec.time trace-nb_10000000-h_7-bs_9710-CPU_1.rec -trace-nb_10000000-h_7-bs_5385-CPU_15.rec trace-nb_10000000-h_7-bs_5385-CPU_20.rec.time trace-nb_10000000-h_7-bs_5385-CPU_4.rec trace-nb_10000000-h_7-bs_9710-CPU_1.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_15.rec.time trace-nb_10000000-h_7-bs_5385-CPU_21.rec trace-nb_10000000-h_7-bs_5385-CPU_4.rec.time -trace-nb_10000000-h_7-bs_5385-CPU_16.rec trace-nb_10000000-h_7-bs_5385-CPU_21.rec.time trace-nb_10000000-h_7-bs_5385-CPU_5.rec -``` - -We then compute the efficiencies from these files -```bash -g++ -std=c++11 $SCALFMM_AB/mergetimefile.cpp -o $SCALFMM_AB/mergetimefile.exe -$SCALFMM_AB/mergetimefile.exe \ - "$SCALFMM_RES_DIR/trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_BS_CPU_SEQ-CPU_1.rec.time" \ - "$SCALFMM_RES_DIR/trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_BS_CPU_PAR-CPU_%d.rec.time"\ - $SCALFMM_MAX_NB_CPU -``` - -We end-up with the global efficiencies (for the application) but also for the different operators. -```bash -Create global-eff.data -Create task-eff.data -Create task-gr-eff.dat -``` - -We can plot each of them -```bash -gnuplot -e "filename='global-eff'" $SCALFMM_AB/scalfmmPlotAll.gplot -gnuplot -e "filename='task-eff'" $SCALFMM_AB/scalfmmPlotAll.gplot -gnuplot -e "filename='task-gr-eff'" $SCALFMM_AB/scalfmmPlotAll.gplot -``` - -In our case it gives: -![global-eff](global-eff.png) -![task-eff](task-eff.png) -![task-gr-eff](task-gr-eff.png) - - -## Heterogeneous - -__NOT FINISHED!!!!__ - -For test case `-nb 10000000` (10 million) and `-h 6` (height of the tree equal to 6), -we first want to know the best granularity `-bs`. - -This parameter will certainly not be the same for sequential/parallel/heterogenous configurations. - -```bash -export SCALFMM_NB=10000000 -export SCALFMM_H=7 -export SCALFMM_MIN_BS=100 -export SCALFMM_MAX_BS=3000 -export SCALFMM_MAX_NB_CPU=24 -export SCALFMM_MAX_NB_GPU=4 -``` - -```bash -export STARPU_NCPUS=1 -export STARPU_NCUDA=0 -export SCALFMM_BS_CPU_SEQ=`$SCALFMM_AB/scalfmmFindBs.sh -nb $SCALFMM_NB -h $SCALFMM_H $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" ` -if [[ `which gnuplot | wc -l` == "1" ]] ; then - gnuplot -e "filename='seq-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot -fi - -export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU -export STARPU_NCUDA=0 -export SCALFMM_BS_CPU_PAR=`$SCALFMM_AB/scalfmmFindBs.sh -nb $SCALFMM_NB -h $SCALFMM_H $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" ` -if [[ `which gnuplot | wc -l` == "1" ]] ; then - gnuplot -e "filename='par-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot -fi - -export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU -export STARPU_NCUDA=$SCALFMM_MAX_NB_GPU -export SCALFMM_BS_CPU_GPU=`$SCALFMM_AB/scalfmmFindBs.sh -nb $SCALFMM_NB -h $SCALFMM_H $SCALFMM_MIN_BS $SCALFMM_MAX_BS | $SCALFMM_AB/scalfmm_extract_key "@BEST BS" ` -if [[ `which gnuplot | wc -l` == "1" ]] ; then - gnuplot -e "filename='cpugpu-bs-search'" $SCALFMM_AB/scalfmmFindBs.gplot -fi -``` - -Then, we can execute three best configurations, and keep .rec for each of them: -```bash -export STARPU_NCPUS=1 -export STARPU_NCUDA=0 -./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_CPU_SEQ -export SCALFMM_SEQ_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec" -mv trace.rec $SCALFMM_SEQ_REC - -export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU -export STARPU_NCUDA=0 -./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_PAR -export SCALFMM_PAR_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec" -mv trace.rec $SCALFMM_PAR_REC - -export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU -export STARPU_NCUDA=$SCALFMM_MAX_NB_GPU -./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_GPU -export SCALFMM_PAR_CPU_GPU_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec" -mv trace.rec $SCALFMM_PAR_CPU_GPU_REC -``` - -And we also want the GPU tasks only on GPU -```bash -export STARPU_NCPUS=$SCALFMM_MAX_NB_CPU -export STARPU_NCUDA=$SCALFMM_MAX_NB_GPU -./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_GPU -p2p-m2l-cuda-only -export SCALFMM_PAR_GPU_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA-GPUONLY.rec" -mv trace.rec $SCALFMM_PAR_GPU_REC -``` - -And we want the sequential version with parallel granularity: -```bash -export STARPU_NCPUS=1 -export STARPU_NCUDA=0 - -./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_PAR -SCALFMM_SEQ_CPU_BS_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec" -mv trace.rec $SCALFMM_SEQ_CPU_BS_REC - -./Tests/Release/testBlockedUnifCudaBench -nb $SCALFMM_NB -h $SCALFMM_H -bs $SCALFMM_BS_CPU_GPU -SCALFMM_SEQ_GPU_BS_REC="trace-nb_$SCALFMM_NB-h_$SCALFMM_H-bs_$SCALFMM_CPU_SEQ-CPU_$STARPU_NCPUS-GPU_$STARPU_NCUDA.rec" -mv trace.rec $SCALFMM_SEQ_GPU_BS_REC -``` - -From these files, we are able to get the different efficencies. - -## Post-processing and Plot - -From the file: - -+ `$SCALFMM_SEQ_REC` : the resulting file from the sequential execution with best sequential granularity -+ `$SCALFMM_PAR_REC` : the resulting file from a parallel execution (no GPU) with best parallel granularity -+ `$SCALFMM_PAR_CPU_GPU_REC` : the resulting file from a parallel execution (hybrid) with best parallel-hybrid granularity -+ `$SCALFMM_PAR_GPU_REC` : the resulting file with all possible tasks on GPU with best parallel-hybrid granularity -+ `$SCALFMM_SEQ_CPU_BS_REC` : the resulting file from sequential execution with best parallel granularity -+ `$SCALFMM_SEQ_GPU_BS_REC` : the resulting file from sequential execution with best parallel-hybrid granularity - -Getting all the efficency -Solving the linear programming problem - -Plotting the results - - -## Automatization - -```bash -SCALFMM_NB=10000000 -SCALFMM_H=7 -SCALFMM_MIN_BS=100 -SCALFMM_MAX_BS=3000 -SCALFMM_MAX_NB_CPU=24 -SCALFMM_MAX_NB_GPU=4 - -scalfmm_generate_efficiency -nb $SCALFMM_NB -h $SCALFMM_H -start $SCALFMM_MIN_BS -end $SCALFMM_MAX_BS -``` \ No newline at end of file diff --git a/Addons/BenchEfficiency/scalfmmExtractKey.sh b/Addons/BenchEfficiency/scalfmmExtractKey.sh index a1909bcb4db4a77e7238db47dba78721c8045043..dbdc7f0e20309561a11cf009161fc305bbb18765 100644 --- a/Addons/BenchEfficiency/scalfmmExtractKey.sh +++ b/Addons/BenchEfficiency/scalfmmExtractKey.sh @@ -6,5 +6,5 @@ if [[ $# -ne 1 ]] ; then fi input=$(cat) -res=`echo "$input" | grep "$3" | cut -d'=' -f2 | cut -d's' -f1` +res=`echo "$input" | grep "$1" | cut -d'=' -f2 | cut -d' ' -f2` echo $res diff --git a/Addons/BenchEfficiency/seq-bs-search.png b/Addons/BenchEfficiency/seq-bs-search.png deleted file mode 100644 index 3bc1ece1cf46f09a17f2b95f59040589fdd91bd9..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/seq-bs-search.png and /dev/null differ diff --git a/Addons/BenchEfficiency/task-eff.data b/Addons/BenchEfficiency/task-eff.data deleted file mode 100644 index d921d6a94df131fea43c5d9e12cdb61f290322a2..0000000000000000000000000000000000000000 --- a/Addons/BenchEfficiency/task-eff.data +++ /dev/null @@ -1,25 +0,0 @@ -0 L2L M2M P2M L2P M2L-out M2L P2P-out P2P -1 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 -2 9.565659e-01 9.665736e-01 1.031103e+00 1.004286e+00 9.715094e-01 9.208541e-01 9.697996e-01 9.763831e-01 -3 9.263068e-01 1.024516e+00 1.029574e+00 9.889095e-01 9.937418e-01 9.954310e-01 1.001689e+00 1.000994e+00 -4 1.005226e+00 1.006333e+00 1.033745e+00 1.010624e+00 9.534195e-01 9.864280e-01 9.895790e-01 9.995851e-01 -5 8.615300e-01 9.844517e-01 9.938413e-01 1.009990e+00 9.569465e-01 9.791331e-01 9.887700e-01 9.975625e-01 -6 8.535893e-01 9.410083e-01 1.014109e+00 1.018876e+00 9.739749e-01 9.860534e-01 9.782539e-01 9.964238e-01 -7 1.046813e+00 9.975072e-01 1.037954e+00 1.003486e+00 9.786087e-01 9.933857e-01 1.004895e+00 9.965736e-01 -8 9.995985e-01 1.013025e+00 9.895591e-01 1.013030e+00 9.652670e-01 9.907845e-01 1.000561e+00 9.971405e-01 -9 1.039365e+00 1.013929e+00 1.047827e+00 9.852421e-01 9.711139e-01 9.898517e-01 9.980679e-01 9.993222e-01 -10 9.181035e-01 9.952685e-01 1.031850e+00 1.012496e+00 9.670203e-01 9.852214e-01 9.859215e-01 9.985014e-01 -11 8.717502e-01 9.889525e-01 1.028373e+00 1.011922e+00 9.699808e-01 9.888136e-01 9.826419e-01 9.981512e-01 -12 9.452144e-01 1.040015e+00 1.013514e+00 9.762884e-01 9.389195e-01 9.915452e-01 9.996240e-01 9.998256e-01 -13 1.022490e+00 1.021529e+00 1.014210e+00 9.896566e-01 9.668669e-01 9.898209e-01 1.011145e+00 9.991000e-01 -14 9.383201e-01 9.923898e-01 1.030084e+00 1.009296e+00 9.748870e-01 9.858361e-01 1.005721e+00 9.971995e-01 -15 9.387378e-01 9.986737e-01 1.032522e+00 9.967096e-01 9.675984e-01 9.877332e-01 1.003181e+00 9.974178e-01 -16 9.377196e-01 9.853747e-01 1.043778e+00 1.003874e+00 9.786853e-01 9.873092e-01 1.003464e+00 9.958178e-01 -17 9.293735e-01 1.034251e+00 1.038271e+00 1.003177e+00 9.700248e-01 9.915540e-01 9.899480e-01 9.984129e-01 -18 9.081814e-01 9.992797e-01 1.018655e+00 9.982681e-01 9.627375e-01 9.752319e-01 9.739917e-01 9.297086e-01 -19 9.471672e-01 9.763513e-01 1.026148e+00 1.013503e+00 9.656781e-01 9.868543e-01 9.891711e-01 9.992051e-01 -20 9.376034e-01 1.008523e+00 1.015422e+00 9.988900e-01 9.763451e-01 9.917410e-01 1.016855e+00 9.974959e-01 -21 9.649789e-01 9.941223e-01 1.023371e+00 9.720318e-01 9.427889e-01 9.864717e-01 1.011408e+00 1.001528e+00 -22 8.085859e-01 1.003002e+00 1.024132e+00 1.015483e+00 9.586926e-01 9.888563e-01 9.829068e-01 9.982469e-01 -23 9.843031e-01 1.009513e+00 1.041257e+00 1.012564e+00 1.009160e+00 9.949415e-01 9.970272e-01 9.964763e-01 -24 9.408696e-01 9.847445e-01 1.030481e+00 9.726508e-01 9.691133e-01 9.975819e-01 1.022271e+00 1.000680e+00 diff --git a/Addons/BenchEfficiency/task-eff.png b/Addons/BenchEfficiency/task-eff.png deleted file mode 100644 index d8e15fae86dc95d544ca3ca3f1fe85b624b5b32a..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/task-eff.png and /dev/null differ diff --git a/Addons/BenchEfficiency/task-gr-eff.data b/Addons/BenchEfficiency/task-gr-eff.data deleted file mode 100644 index d921d6a94df131fea43c5d9e12cdb61f290322a2..0000000000000000000000000000000000000000 --- a/Addons/BenchEfficiency/task-gr-eff.data +++ /dev/null @@ -1,25 +0,0 @@ -0 L2L M2M P2M L2P M2L-out M2L P2P-out P2P -1 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 -2 9.565659e-01 9.665736e-01 1.031103e+00 1.004286e+00 9.715094e-01 9.208541e-01 9.697996e-01 9.763831e-01 -3 9.263068e-01 1.024516e+00 1.029574e+00 9.889095e-01 9.937418e-01 9.954310e-01 1.001689e+00 1.000994e+00 -4 1.005226e+00 1.006333e+00 1.033745e+00 1.010624e+00 9.534195e-01 9.864280e-01 9.895790e-01 9.995851e-01 -5 8.615300e-01 9.844517e-01 9.938413e-01 1.009990e+00 9.569465e-01 9.791331e-01 9.887700e-01 9.975625e-01 -6 8.535893e-01 9.410083e-01 1.014109e+00 1.018876e+00 9.739749e-01 9.860534e-01 9.782539e-01 9.964238e-01 -7 1.046813e+00 9.975072e-01 1.037954e+00 1.003486e+00 9.786087e-01 9.933857e-01 1.004895e+00 9.965736e-01 -8 9.995985e-01 1.013025e+00 9.895591e-01 1.013030e+00 9.652670e-01 9.907845e-01 1.000561e+00 9.971405e-01 -9 1.039365e+00 1.013929e+00 1.047827e+00 9.852421e-01 9.711139e-01 9.898517e-01 9.980679e-01 9.993222e-01 -10 9.181035e-01 9.952685e-01 1.031850e+00 1.012496e+00 9.670203e-01 9.852214e-01 9.859215e-01 9.985014e-01 -11 8.717502e-01 9.889525e-01 1.028373e+00 1.011922e+00 9.699808e-01 9.888136e-01 9.826419e-01 9.981512e-01 -12 9.452144e-01 1.040015e+00 1.013514e+00 9.762884e-01 9.389195e-01 9.915452e-01 9.996240e-01 9.998256e-01 -13 1.022490e+00 1.021529e+00 1.014210e+00 9.896566e-01 9.668669e-01 9.898209e-01 1.011145e+00 9.991000e-01 -14 9.383201e-01 9.923898e-01 1.030084e+00 1.009296e+00 9.748870e-01 9.858361e-01 1.005721e+00 9.971995e-01 -15 9.387378e-01 9.986737e-01 1.032522e+00 9.967096e-01 9.675984e-01 9.877332e-01 1.003181e+00 9.974178e-01 -16 9.377196e-01 9.853747e-01 1.043778e+00 1.003874e+00 9.786853e-01 9.873092e-01 1.003464e+00 9.958178e-01 -17 9.293735e-01 1.034251e+00 1.038271e+00 1.003177e+00 9.700248e-01 9.915540e-01 9.899480e-01 9.984129e-01 -18 9.081814e-01 9.992797e-01 1.018655e+00 9.982681e-01 9.627375e-01 9.752319e-01 9.739917e-01 9.297086e-01 -19 9.471672e-01 9.763513e-01 1.026148e+00 1.013503e+00 9.656781e-01 9.868543e-01 9.891711e-01 9.992051e-01 -20 9.376034e-01 1.008523e+00 1.015422e+00 9.988900e-01 9.763451e-01 9.917410e-01 1.016855e+00 9.974959e-01 -21 9.649789e-01 9.941223e-01 1.023371e+00 9.720318e-01 9.427889e-01 9.864717e-01 1.011408e+00 1.001528e+00 -22 8.085859e-01 1.003002e+00 1.024132e+00 1.015483e+00 9.586926e-01 9.888563e-01 9.829068e-01 9.982469e-01 -23 9.843031e-01 1.009513e+00 1.041257e+00 1.012564e+00 1.009160e+00 9.949415e-01 9.970272e-01 9.964763e-01 -24 9.408696e-01 9.847445e-01 1.030481e+00 9.726508e-01 9.691133e-01 9.975819e-01 1.022271e+00 1.000680e+00 diff --git a/Addons/BenchEfficiency/task-gr-eff.png b/Addons/BenchEfficiency/task-gr-eff.png deleted file mode 100644 index c748b76826f08ea7f7f09769eba322f0dce0cf3e..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/task-gr-eff.png and /dev/null differ diff --git a/Addons/BenchEfficiency/trace-example-colors.png b/Addons/BenchEfficiency/trace-example-colors.png deleted file mode 100644 index dcefa9fb53660927f1509d64f89254ee03e60dec..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/trace-example-colors.png and /dev/null differ diff --git a/Addons/BenchEfficiency/trace-example.png b/Addons/BenchEfficiency/trace-example.png deleted file mode 100644 index 5e466b94ed15a4d0905484425a75de9d390f45d7..0000000000000000000000000000000000000000 Binary files a/Addons/BenchEfficiency/trace-example.png and /dev/null differ diff --git a/Addons/CKernelApi/Src/FUserKernelEngine.hpp b/Addons/CKernelApi/Src/FUserKernelEngine.hpp index aa70d9241e791a89676bb7c038bbf4212a4db337..a4fb90b9164d67205c035fede02f1c4868edf28b 100644 --- a/Addons/CKernelApi/Src/FUserKernelEngine.hpp +++ b/Addons/CKernelApi/Src/FUserKernelEngine.hpp @@ -125,10 +125,14 @@ public: virtual void M2M(CellClass* const FRestrict cell, const CellClass*const FRestrict *const FRestrict children, const int level) { if(kernel.m2m_full){ std::vector userCellArray; - for(int i=0 ;i<8 ; ++i){ - userCellArray.push_back(children[i]->getContainer()); - kernel.m2m_full(level, cell->getContainer(), userCellArray.data(), userData); + for(int idx=0 ;idx<8 ; ++idx){ + if( children[idx] ){ + userCellArray.push_back(children[idx]->getContainer()); + }else{ + userCellArray.push_back(nullptr); + } } + kernel.m2m_full(level, cell->getContainer(), userCellArray.data(), userData); }else{ if(kernel.m2m){ for(int idx = 0 ; idx < 8 ; ++idx){ @@ -167,7 +171,11 @@ public: if(kernel.l2l_full){ std::vector userCellArray; for(int i=0 ;i<8 ; ++i){ - userCellArray.push_back(children[i]->getContainer()); + if(children[i]){ + userCellArray.push_back(children[i]->getContainer()); + }else{ + userCellArray.push_back(nullptr); + } kernel.l2l_full(level, cell->getContainer(), userCellArray.data(), userData); } }else{ diff --git a/CMakeLists.txt b/CMakeLists.txt index ecba3000c7fafc93b3927d9d19135ce5268bb6b9..5a771b490d74dbcb44b33cc751d48686e2bd3384 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,9 +328,10 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ # SYMBOL_NAMESPACE "PM_" # SYMBOLS init testPPM:init) message(STATUS "CMAKE_CXX_COMPILER_ID STREQUAL ${CMAKE_CXX_COMPILER_ID}") - - option( SCALFMM_USE_MKL_AS_BLAS "Set to ON to use MKL CBLAS" OFF ) - + + option( SCALFMM_USE_MKL_AS_BLAS "Set to ON to use MKL BLAS/LAPACK" OFF ) + option( SCALFMM_USE_ESSL_AS_BLAS "Set to ON to use ESSL BLAS/LAPACK" OFF ) + if( SCALFMM_USE_MKL_AS_BLAS ) set(BLA_VENDOR "Intel10_64lp_seq") find_package(BLASEXT QUIET) # not REQUIRED @@ -338,6 +339,16 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ if (BLAS_LIBRARIES) set(BLASLAPACK_LIBRARIES ${BLAS_LIBRARIES}) endif() + elseif(SCALFMM_USE_ESSL_AS_BLAS) + set(BLA_VENDOR "IBMESSL") + find_package(BLASEXT QUIET) # not REQUIRED + find_package(LAPACKEXT QUIET) # not REQUIRED + if (LAPACK_LIBRARIES) + set(BLASLAPACK_LIBRARIES "${LAPACK_LIBRARIES}") + endif() + if (BLAS_LIBRARIES) + list(APPEND BLASLAPACK_LIBRARIES ${BLAS_LIBRARIES}) + endif() elseif(SCALFMM_USE_EXTERNAL_BLAS) message(STATUS "BLAS SET BY EXTERNAL PROGRAM = ${BLAS_LIBRARIES}") list(APPEND BLASLAPACK_LIBRARIES "${BLAS_LIBRARIES}") @@ -352,7 +363,7 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ list(APPEND BLASLAPACK_LIBRARIES "${BLAS_LIBRARIES}") endif() endif() - + if(BLAS_FOUND) set(SCALFMM_LIBRARIES "${SCALFMM_LIBRARIES};${BLASLAPACK_LIBRARIES}") if(BLAS_LIBRARY_DIRS) @@ -363,6 +374,7 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ # the RPATH to be used when installing list(APPEND CMAKE_INSTALL_RPATH "${LAPACK_LIBRARY_DIRS}") endif() + message (STATUS "check BLAS Fortran mangling") # check blas and lapack symbols naming set(CMAKE_REQUIRED_LIBRARIES "${BLAS_LIBRARIES}") check_function_exists(dgemv_ DGEMV_ADD_) @@ -374,19 +386,19 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ message (STATUS "BLAS dgemv_ symbol found, SCALFMM_BLAS_ADD_ is ON") else (DGEMV_ADD_) set (SCALFMM_BLAS_ADD_ OFF) - check_function_exists(DGEMV DGEMV_UPCASE) - if (DGEMV_UPCASE) - set (SCALFMM_BLAS_UPCASE ON) - message (STATUS "BLAS DGEMV symbol found, SCALFMM_BLAS_UPCASE is ON") - else (DGEMV_UPCASE) - # set (SCALFMM_BLAS_UPCASE OFF) + check_function_exists(DGEMV DGEMV_UPCASE) + if (DGEMV_UPCASE) + set (SCALFMM_BLAS_UPCASE ON) + message (STATUS "BLAS DGEMV symbol found, SCALFMM_BLAS_UPCASE is ON") + else (DGEMV_UPCASE) + # set (SCALFMM_BLAS_UPCASE OFF) check_function_exists(dgemv DGEMV_NOCHANGE) if (DGEMV_NOCHANGE) set (SCALFMM_BLAS_NOCHANGE ON) message (STATUS "BLAS dgemv symbol found, SCALFMM_BLAS_NOCHANGE is ON") - # else (DGEMV_NOCHANGE) - # set (SCALFMM_BLAS_NOCHANGE OFF) - endif (DGEMV_NOCHANGE) + # else (DGEMV_NOCHANGE) + # set (SCALFMM_BLAS_NOCHANGE OFF) + endif (DGEMV_NOCHANGE) endif (DGEMV_UPCASE) endif (DGEMV_ADD_) if ( (NOT DGEMV_ADD_) AND (NOT DGEMV_UPCASE) AND (NOT DGEMV_NOCHANGE) ) @@ -403,88 +415,59 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ # # FFT option # - CMAKE_DEPENDENT_OPTION(SCALFMM_USE_MKL_AS_FFTW "Set to ON to use MKL FFTW" ON "SCALFMM_USE_FFT;SCALFMM_USE_MKL_AS_BLAS" OFF ) + CMAKE_DEPENDENT_OPTION(SCALFMM_USE_MKL_AS_FFTW "Set to ON to use MKL FFTW" ON "SCALFMM_USE_FFT;SCALFMM_USE_MKL_AS_BLAS" OFF ) + CMAKE_DEPENDENT_OPTION(SCALFMM_USE_ESSL_AS_FFTW "Set to ON to use ESSL FFTW" ON "SCALFMM_USE_FFT;SCALFMM_USE_ESSL_AS_BLAS" OFF ) if( SCALFMM_USE_FFT ) message(STATUS "SCALFMM USE FFT Configure:") + # The package find_package(FFTW) can be used with the following COMPONENTS: + # MKL, ESSL, THREADS|OMP and/or SIMPLE|LONG|QUAD + # Default will find the real double precision fftw library version without THREADS|OMP if( SCALFMM_USE_MKL_AS_FFTW ) + message(STATUS " SCALFMM USE FFT from MKL") + find_package(FFTW COMPONENTS MKL) + elseif (SCALFMM_USE_ESSL_AS_FFTW) + message(STATUS " SCALFMM USE FFT from ESSL ") + find_package(FFTW COMPONENTS ESSL) + add_definitions(-DSCALFMM_USE_ESSL_AS_FFTW) + else() + message(STATUS " SCALFMM USE FFTW") + find_package(FFTW COMPONENTS SIMPLE) + endif() - message(STATUS " SCALFMM USE MKL ") - - if( SCALFMM_USE_MKL_AS_BLAS ) - - unset(FFT_LIBRARIES CACHE) - message(STATUS " SCALFMM USE MKL already defined") - set(FFT_INCLUDES "$ENV{MKLROOT}/include/fftw" CACHE STRING "Set your MKL flags") - if (BLAS_FOUND) - set(FFTW_FOUND ON) - endif() - - else(SCALFMM_USE_MKL_AS_BLAS) - - # The package can be used with the following COMPONENTS: - # MKL, THREADS|OMP and/or SIMPLE|DOUBLE|LONG|QUAD - # Default is DOUBLE and without THREADS|OMP - find_package(FFTW COMPONENTS MKL) # not REQUIRED - if (FFTW_LIBRARY_DIRS_DEP) - set(FFT_LIBRARIES "-L${FFTW_LIBRARY_DIRS_DEP};" CACHE STRING "Set your MKL flags") - endif() - if (FFTW_LIBRARIES_DEP) - foreach (fft_lib ${FFTW_LIBRARIES_DEP}) - set(FFT_LIBRARIES "${FFT_LIBRARIES};${fft_lib};") - endforeach() - endif() - set(FFT_INCLUDES "${FFTW_INCLUDE_DIRS_DEP}" ) - if (FFT_LIBRARIES) - set(SCALFMM_LIBRARIES "${SCALFMM_LIBRARIES};${FFT_LIBRARIES}") - endif() - - endif(SCALFMM_USE_MKL_AS_BLAS) - - else(SCALFMM_USE_MKL_AS_FFTW) - - message(STATUS " SCALFMM USE FFTW ") - # The package can be used with the following COMPONENTS: - # MKL, THREADS|OMP and/or SIMPLE|DOUBLE|LONG|QUAD - # Default is DOUBLE and without THREADS|OMP - find_package(FFTW COMPONENTS SIMPLE) # not REQUIRED - if (FFTW_LIBRARY_DIRS_DEP) - set(FFT_LIBRARIES "-L${FFTW_LIBRARY_DIRS_DEP};" CACHE STRING "Set your FFTW path") - endif() - if (FFTW_LIBRARIES_DEP) - foreach (fft_lib ${FFTW_LIBRARIES_DEP}) - set(FFT_LIBRARIES "${FFT_LIBRARIES};${fft_lib};") - endforeach() - endif() - set(FFT_INCLUDES "${FFTW_INCLUDE_DIRS_DEP}" ) - if (FFT_LIBRARIES) - set(SCALFMM_LIBRARIES "${SCALFMM_LIBRARIES};${FFT_LIBRARIES}") - endif() - if(FFTW_LIBRARY_DIRS) - # the RPATH to be used when installing - list(APPEND CMAKE_INSTALL_RPATH "${FFTW_LIBRARY_DIRS}") - endif() + if (FFTW_LIBRARY_DIRS_DEP) + set(FFT_LIBRARIES "-L${FFTW_LIBRARY_DIRS_DEP};" CACHE STRING "Set your MKL flags") + endif() + if (FFTW_LIBRARIES_DEP) + foreach (fft_lib ${FFTW_LIBRARIES_DEP}) + set(FFT_LIBRARIES "${FFT_LIBRARIES};${fft_lib};") + endforeach() + endif() - endif(SCALFMM_USE_MKL_AS_FFTW) + set(FFT_INCLUDES "${FFTW_INCLUDE_DIRS_DEP}" ) + if (FFT_LIBRARIES) + set(SCALFMM_LIBRARIES "${SCALFMM_LIBRARIES};${FFT_LIBRARIES}") + endif() + if(FFTW_LIBRARY_DIRS) + # the RPATH to be used when installing + list(APPEND CMAKE_INSTALL_RPATH "${FFTW_LIBRARY_DIRS}") + endif() if (FFT_INCLUDES) set(SCALFMM_INCLUDES "${SCALFMM_INCLUDES}; ${FFT_INCLUDES}") endif() - if(FFTW_FOUND) - message(STATUS " SCALFMM_LIBRARIES = ${SCALFMM_LIBRARIES}") - message(STATUS " SCALFMM_INCLUDES = ${SCALFMM_INCLUDES}") - else() + if(NOT FFTW_FOUND) message(WARNING "FFTW has not been found, SCALFMM will continue to compile but some applications will be disabled.") message(WARNING "If you have FFTW set FFTW_LIBDIR, FFTW_INCDIR or FFTW_DIR (CMake variables using -D or environment variables).") set(SCALFMM_USE_FFT OFF) endif() + endif(SCALFMM_USE_FFT) list(APPEND FUSE_LIST "FFT") - message(STATUS " SCALFMM_LIBRARIES = ${SCALFMM_LIBRARIES}") - message(STATUS " SCALFMM_INCLUDES = ${SCALFMM_INCLUDES}") - message(STATUS "SCALFMM_USE_FFT = ${SCALFMM_USE_FFT}") + list(REMOVE_DUPLICATES SCALFMM_INCLUDES) + list(REMOVE_DUPLICATES SCALFMM_LIBRARIES) # # C++ 2011 @@ -788,7 +771,7 @@ if (MORSE_DISTRIB_DIR OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/morse/ set(SCALFMM_COMPILE_LIBS "") foreach(lib_var ${SCALFMM_LIBRARIES}) string(STRIP ${lib_var} lib_var) - LIST(APPEND SCALFMM_COMPILE_LIBS ${lib_var}) + LIST(APPEND SCALFMM_COMPILE_LIBS ${lib_var}) endforeach() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Src/ScalFmmConfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/Src/ScalFmmConfig.h ) diff --git a/CMakeModules/morse/find/FindBLAS.cmake b/CMakeModules/morse/find/FindBLAS.cmake index 073e2c1134ebf2b26e798996e24d616785d20ef2..40e8ae2c53c583aaf31affdde69cde9268141513 100644 --- a/CMakeModules/morse/find/FindBLAS.cmake +++ b/CMakeModules/morse/find/FindBLAS.cmake @@ -44,7 +44,7 @@ ### List of vendors (BLA_VENDOR) valid in this module ########## List of vendors (BLA_VENDOR) valid in this module ## Open (for OpenBlas), Eigen (for EigenBlas), Goto, ATLAS PhiPACK, -##  CXML, DXML, SunPerf, SCSL, SGIMATH, IBMESSL, +##  CXML, DXML, SunPerf, SCSL, SGIMATH, IBMESSL, IBMESSLMT ## Intel10_32 (intel mkl v10 32 bit), Intel10_64lp (intel mkl v10 64 bit,lp thread model, lp64 model), ## Intel10_64lp_seq (intel mkl v10 64 bit,sequential code, lp64 model), ## Intel( older versions of mkl 32 and 64 bit), @@ -330,11 +330,9 @@ macro(Check_Fortran_Libraries LIBRARIES _prefix _name _flags _list _thread) if(_libraries_work) set(${LIBRARIES} ${${LIBRARIES}} ${_thread}) else(_libraries_work) - set(${LIBRARIES} FALSE) + set(${LIBRARIES} FALSE) endif(_libraries_work) -# message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}") - endmacro(Check_Fortran_Libraries) @@ -707,6 +705,14 @@ if (BLA_VENDOR MATCHES "Intel*" OR BLA_VENDOR STREQUAL "All") endif (_LANGUAGES_ MATCHES C OR _LANGUAGES_ MATCHES CXX) + if(NOT BLAS_FIND_QUIETLY) + if(${_LIBRARIES}) + message(STATUS "Looking for MKL BLAS: found") + else() + message(STATUS "Looking for MKL BLAS: not found") + endif() + endif() + endif (BLA_VENDOR MATCHES "Intel*" OR BLA_VENDOR STREQUAL "All") @@ -722,6 +728,13 @@ if (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All") "goto2" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Goto BLAS: found") + else() + message(STATUS "Looking for Goto BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All") @@ -740,6 +753,13 @@ if (BLA_VENDOR STREQUAL "Open" OR BLA_VENDOR STREQUAL "All") "openblas" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Open BLAS: found") + else() + message(STATUS "Looking for Open BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "Open" OR BLA_VENDOR STREQUAL "All") @@ -758,6 +778,13 @@ if (BLA_VENDOR STREQUAL "Eigen" OR BLA_VENDOR STREQUAL "All") "eigen_blas" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Eigen BLAS: found") + else() + message(STATUS "Looking for Eigen BLAS: not found") + endif() + endif() endif() if(NOT BLAS_LIBRARIES) @@ -770,6 +797,13 @@ if (BLA_VENDOR STREQUAL "Eigen" OR BLA_VENDOR STREQUAL "All") "eigen_blas_static" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Eigen BLAS: found") + else() + message(STATUS "Looking for Eigen BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "Eigen" OR BLA_VENDOR STREQUAL "All") @@ -787,6 +821,13 @@ if (BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All") "f77blas;atlas" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Atlas BLAS: found") + else() + message(STATUS "Looking for Atlas BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All") @@ -804,6 +845,13 @@ if (BLA_VENDOR STREQUAL "PhiPACK" OR BLA_VENDOR STREQUAL "All") "sgemm;dgemm;blas" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for PhiPACK BLAS: found") + else() + message(STATUS "Looking for PhiPACK BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "PhiPACK" OR BLA_VENDOR STREQUAL "All") @@ -821,6 +869,13 @@ if (BLA_VENDOR STREQUAL "CXML" OR BLA_VENDOR STREQUAL "All") "cxml" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for CXML BLAS: found") + else() + message(STATUS "Looking for CXML BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "CXML" OR BLA_VENDOR STREQUAL "All") @@ -838,6 +893,13 @@ if (BLA_VENDOR STREQUAL "DXML" OR BLA_VENDOR STREQUAL "All") "dxml" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for DXML BLAS: found") + else() + message(STATUS "Looking for DXML BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "DXML" OR BLA_VENDOR STREQUAL "All") @@ -858,6 +920,13 @@ if (BLA_VENDOR STREQUAL "SunPerf" OR BLA_VENDOR STREQUAL "All") if(BLAS_LIBRARIES) set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf") endif() + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for SunPerf BLAS: found") + else() + message(STATUS "Looking for SunPerf BLAS: not found") + endif() + endif() endif() endif () @@ -875,6 +944,13 @@ if (BLA_VENDOR STREQUAL "SCSL" OR BLA_VENDOR STREQUAL "All") "scsl" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for SCSL BLAS: found") + else() + message(STATUS "Looking for SCSL BLAS: not found") + endif() + endif() endif() endif () @@ -892,12 +968,19 @@ if (BLA_VENDOR STREQUAL "SGIMATH" OR BLA_VENDOR STREQUAL "All") "complib.sgimath" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for SGIMATH BLAS: found") + else() + message(STATUS "Looking for SGIMATH BLAS: not found") + endif() + endif() endif() endif () -# BLAS in IBM ESSL library? (requires generic BLAS lib, too) +# BLAS in IBM ESSL library (requires generic BLAS lib, too) if (BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) @@ -906,9 +989,39 @@ if (BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All") BLAS sgemm "" - "essl" + "essl;xlfmath;xlf90_r;blas" + "" + ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for IBM ESSL BLAS: found") + else() + message(STATUS "Looking for IBM ESSL BLAS: not found") + endif() + endif() + endif() + +endif () + +# BLAS in IBM ESSL_MT library (requires generic BLAS lib, too) +if (BLA_VENDOR STREQUAL "IBMESSLMT" OR BLA_VENDOR STREQUAL "All") + + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "esslsmp;xlsmp;xlfmath;xlf90_r;blas" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for IBM ESSL MT BLAS: found") + else() + message(STATUS "Looking for IBM ESSL MT BLAS: not found") + endif() + endif() endif() endif () @@ -1035,6 +1148,13 @@ if (BLA_VENDOR MATCHES "ACML.*" OR BLA_VENDOR STREQUAL "All") "acml;acml_mv" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for ACML BLAS: found") + else() + message(STATUS "Looking for ACML BLAS: not found") + endif() + endif() endif() if(NOT BLAS_LIBRARIES) @@ -1046,6 +1166,13 @@ if (BLA_VENDOR MATCHES "ACML.*" OR BLA_VENDOR STREQUAL "All") "acml_mp;acml_mv" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for ACML BLAS: found") + else() + message(STATUS "Looking for ACML BLAS: not found") + endif() + endif() endif() if(NOT BLAS_LIBRARIES) @@ -1057,6 +1184,13 @@ if (BLA_VENDOR MATCHES "ACML.*" OR BLA_VENDOR STREQUAL "All") "acml;acml_mv;CALBLAS" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for ACML BLAS: found") + else() + message(STATUS "Looking for ACML BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR MATCHES "ACML.*" OR BLA_VENDOR STREQUAL "All") # ACML @@ -1074,6 +1208,13 @@ if (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All") "Accelerate" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Apple BLAS: found") + else() + message(STATUS "Looking for Apple BLAS: not found") + endif() + endif() endif() endif (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All") @@ -1090,8 +1231,16 @@ if (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All") "vecLib" "" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for NAS BLAS: found") + else() + message(STATUS "Looking for NAS BLAS: not found") + endif() + endif() endif () + endif (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All") @@ -1110,6 +1259,13 @@ if (BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All") "${SEARCH_LIB}" "${LGFORTRAN}" ) + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_LIBRARIES) + message(STATUS "Looking for Generic BLAS: found") + else() + message(STATUS "Looking for Generic BLAS: not found") + endif() + endif() endif() endforeach () diff --git a/CMakeModules/morse/find/FindBLASEXT.cmake b/CMakeModules/morse/find/FindBLASEXT.cmake index 86330f4224b9d706f35760cc03d810cf222b6cba..a24687ac0b7f94cf664345cb44dc6f531f0a47a5 100644 --- a/CMakeModules/morse/find/FindBLASEXT.cmake +++ b/CMakeModules/morse/find/FindBLASEXT.cmake @@ -43,13 +43,25 @@ # add a cache variable to let the user specify the BLAS vendor set(BLA_VENDOR "" CACHE STRING "list of possible BLAS vendor: - Open, Eigen, Goto, ATLAS PhiPACK, CXML, DXML, SunPerf, SCSL, SGIMATH, IBMESSL, + Open, Eigen, Goto, ATLAS PhiPACK, CXML, DXML, SunPerf, SCSL, SGIMATH, IBMESSL, IBMESSLMT, Intel10_32 (intel mkl v10 32 bit), Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model), Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model), Intel( older versions of mkl 32 and 64 bit), ACML, ACML_MP, ACML_GPU, Apple, NAS, Generic") +if(NOT BLASEXT_FIND_QUIETLY) + message(STATUS "In FindBLASEXT") + message(STATUS "If you want to force the use of one specific library, " + "please specify the BLAS vendor by setting -DBLA_VENDOR=blas_vendor_name" + "at cmake configure.") + message(STATUS "List of possible BLAS vendor: Goto, ATLAS PhiPACK, CXML, " + "DXML, SunPerf, SCSL, SGIMATH, IBMESSL, IBMESSLMT, Intel10_32 (intel mkl v10 32 bit)," + "Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model)," + "Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model)," + "Intel( older versions of mkl 32 and 64 bit)," + "ACML, ACML_MP, ACML_GPU, Apple, NAS, Generic") +endif() if (NOT BLAS_FOUND) # First try to detect two cases: @@ -75,34 +87,24 @@ if(BLA_VENDOR STREQUAL "All" AND endif() if(NOT BLASEXT_FIND_QUIETLY) message(STATUS "A BLAS library has been found (${BLAS_LIBRARIES}) but we" - "have also potentially detected some BLAS libraries from the MKL." - "We try to use this one.") - message(STATUS "If you want to force the use of one specific library, " - "please specify the BLAS vendor by setting -DBLA_VENDOR=blas_vendor_name" - "at cmake configure.") - message(STATUS "List of possible BLAS vendor: Goto, ATLAS PhiPACK, CXML, " - "DXML, SunPerf, SCSL, SGIMATH, IBMESSL, Intel10_32 (intel mkl v10 32 bit)," - "Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model)," - "Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model)," - "Intel( older versions of mkl 32 and 64 bit)," - "ACML, ACML_MP, ACML_GPU, Apple, NAS, Generic") + "have also potentially detected some multithreaded BLAS libraries from the MKL." + "We try to find both libraries lists (Sequential/Multithreaded).") endif() set(BLAS_FOUND "") elseif(BLA_VENDOR STREQUAL "All" AND BLAS_acml_LIBRARY) set(BLA_VENDOR "ACML") if(NOT BLASEXT_FIND_QUIETLY) message(STATUS "A BLAS library has been found (${BLAS_LIBRARIES}) but we" - "have also potentially detected some BLAS libraries from the ACML." - "We try to use this one.") - message(STATUS "If you want to force the use of one specific library, " - "please specify the BLAS vendor by setting -DBLA_VENDOR=blas_vendor_name" - "at cmake configure.") - message(STATUS "List of possible BLAS vendor: Goto, ATLAS PhiPACK, CXML, " - "DXML, SunPerf, SCSL, SGIMATH, IBMESSL, Intel10_32 (intel mkl v10 32 bit)," - "Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model)," - "Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model)," - "Intel( older versions of mkl 32 and 64 bit)," - "ACML, ACML_MP, ACML_GPU, Apple, NAS, Generic") + "have also potentially detected some multithreaded BLAS libraries from the ACML." + "We try to find both libraries lists (Sequential/Multithreaded).") + endif() + set(BLAS_FOUND "") +elseif(BLA_VENDOR STREQUAL "All" AND BLAS_essl_LIBRARY) + set(BLA_VENDOR "IBMESSL") + if(NOT BLASEXT_FIND_QUIETLY) + message(STATUS "A BLAS library has been found (${BLAS_LIBRARIES}) but we" + "have also potentially detected some multithreaded BLAS libraries from the ESSL." + "We try to find both libraries lists (Sequential/Multithreaded).") endif() set(BLAS_FOUND "") endif() @@ -238,6 +240,35 @@ elseif(BLA_VENDOR MATCHES "ACML*") set(BLAS_PAR_LIBRARIES "${BLAS_PAR_LIBRARIES-NOTFOUND}") endif() +# IBMESSL case +elseif(BLA_VENDOR MATCHES "IBMESSL*") + + ## look for the sequential version + set(BLA_VENDOR "IBMESSL") + if(BLASEXT_FIND_REQUIRED) + find_package(BLAS REQUIRED) + else() + find_package(BLAS) + endif() + if(BLAS_FOUND) + set(BLAS_SEQ_LIBRARIES "${BLAS_LIBRARIES}") + else() + set(BLAS_SEQ_LIBRARIES "${BLAS_SEQ_LIBRARIES-NOTFOUND}") + endif() + + ## look for the multithreaded version + set(BLA_VENDOR "IBMESSLMT") + if(BLASEXT_FIND_REQUIRED) + find_package(BLAS REQUIRED) + else(BLAS_FOUND) + find_package(BLAS) + endif() + if(BLAS_FOUND) + set(BLAS_PAR_LIBRARIES "${BLAS_LIBRARIES}") + else() + set(BLAS_PAR_LIBRARIES "${BLAS_PAR_LIBRARIES-NOTFOUND}") + endif() + else() if(BLAS_FOUND) @@ -254,7 +285,6 @@ endif() if(BLAS_SEQ_LIBRARIES) set(BLAS_LIBRARIES "${BLAS_SEQ_LIBRARIES}") endif() -# message("DEBUG BLAS: ${BLAS_SEQ_LIBRARIES} ${BLAS_LIBRARIES}") # extract libs paths # remark: because it is not given by find_package(BLAS) @@ -275,15 +305,6 @@ if (BLAS_LIBRARY_DIRS) list(REMOVE_DUPLICATES BLAS_LIBRARY_DIRS) endif () - -# message(STATUS "BLAS_FOUND: ${BLAS_FOUND}") -# message(STATUS "BLA_VENDOR: ${BLA_VENDOR}") -# message(STATUS "BLAS_LIBRARIES: ${BLAS_LIBRARIES}") -# message(STATUS "BLAS_SEQ_LIBRARIES: ${BLAS_SEQ_LIBRARIES}") -# message(STATUS "BLAS_PAR_LIBRARIES: ${BLAS_PAR_LIBRARIES}") -# message(STATUS "BLAS_INCLUDE_DIRS: ${BLAS_INCLUDE_DIRS}") -# message(STATUS "BLAS_LIBRARY_DIRS: ${BLAS_LIBRARY_DIRS}") - # check that BLAS has been found # --------------------------------- include(FindPackageHandleStandardArgs) @@ -324,8 +345,24 @@ elseif(BLA_VENDOR MATCHES "ACML*") endif() find_package_handle_standard_args(BLAS DEFAULT_MSG BLAS_SEQ_LIBRARIES - BLAS_LIBRARY_DIRS - BLAS_INCLUDE_DIRS) + BLAS_LIBRARY_DIRS) + if(BLAS_PAR_LIBRARIES) + if(NOT BLASEXT_FIND_QUIETLY) + message(STATUS "BLAS parallel libraries stored in BLAS_PAR_LIBRARIES") + endif() + find_package_handle_standard_args(BLAS DEFAULT_MSG + BLAS_PAR_LIBRARIES) + endif() +elseif(BLA_VENDOR MATCHES "IBMESSL*") + if(NOT BLASEXT_FIND_QUIETLY) + message(STATUS "BLAS found is ESSL:" + "we manage two lists of libs," + " one sequential and one parallel if found (see BLAS_SEQ_LIBRARIES and BLAS_PAR_LIBRARIES)") + message(STATUS "BLAS sequential libraries stored in BLAS_SEQ_LIBRARIES") + endif() + find_package_handle_standard_args(BLAS DEFAULT_MSG + BLAS_SEQ_LIBRARIES + BLAS_LIBRARY_DIRS) if(BLAS_PAR_LIBRARIES) if(NOT BLASEXT_FIND_QUIETLY) message(STATUS "BLAS parallel libraries stored in BLAS_PAR_LIBRARIES") diff --git a/CMakeModules/morse/find/FindFFTW.cmake b/CMakeModules/morse/find/FindFFTW.cmake index f259c58feb78c7f1a576456b5e68f90d807d379e..c9163a369f0ba55a5d6e68c64741c4d7a045b399 100644 --- a/CMakeModules/morse/find/FindFFTW.cmake +++ b/CMakeModules/morse/find/FindFFTW.cmake @@ -9,6 +9,8 @@ ### # # - Find FFTW Version 3 include dirs and libraries +# Default configuration will find the real double precision fftw library version +# without THREADS|OMP. # Use this module by invoking find_package with the form: # find_package(FFTW # [REQUIRED] # Fail with error if fftw is not found @@ -16,10 +18,10 @@ # # COMPONENTS can be some of the following: # - MKL: to detect the FFTW from Intel MKL +# - ESSL: to detect the FFTW from IBM ESSL # - THREADS: to detect the Threads version of FFTW # - OMP: to detect the OpenMP version of FFTW # - SIMPLE: to detect the FFTW simple precision fftw3f -# - DOUBLE: to detect the FFTW double precision fftw3 (default) # - LONG: to detect the FFTW long double precision fftw3l # - QUAD: to detect the FFTW quadruple precision fftw3q # @@ -50,7 +52,7 @@ # Copyright 2012-2013 Emmanuel Agullo # Copyright 2012-2013 Mathieu Faverge # Copyright 2012 Cedric Castagnede -# Copyright 2013 Florent Pruvost +# Copyright 2013-2016 Florent Pruvost # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file MORSE-Copyright.txt for details. @@ -72,10 +74,10 @@ endif() # Set the version to find set(FFTW_LOOK_FOR_MKL OFF) +set(FFTW_LOOK_FOR_ESSL OFF) set(FFTW_LOOK_FOR_THREADS OFF) set(FFTW_LOOK_FOR_OMP OFF) set(FFTW_LOOK_FOR_FFTW_SIMPLE OFF) -set(FFTW_LOOK_FOR_FFTW_DOUBLE ON) set(FFTW_LOOK_FOR_FFTW_LONG OFF) set(FFTW_LOOK_FOR_FFTW_QUAD OFF) @@ -92,28 +94,18 @@ if( FFTW_FIND_COMPONENTS ) if (${component} STREQUAL "SIMPLE") # means we look for FFTW simple precision (fftw3f) set(FFTW_LOOK_FOR_FFTW_SIMPLE ON) - set(FFTW_LOOK_FOR_FFTW_DOUBLE OFF) - set(FFTW_LOOK_FOR_FFTW_LONG OFF) - set(FFTW_LOOK_FOR_FFTW_QUAD OFF) - endif() - if (${component} STREQUAL "DOUBLE") - # means we look for FFTW double precision (fftw3) - set(FFTW_LOOK_FOR_FFTW_SIMPLE OFF) - set(FFTW_LOOK_FOR_FFTW_DOUBLE ON) set(FFTW_LOOK_FOR_FFTW_LONG OFF) set(FFTW_LOOK_FOR_FFTW_QUAD OFF) endif() if (${component} STREQUAL "LONG") # means we look for FFTW long double precision (fftw3l) set(FFTW_LOOK_FOR_FFTW_SIMPLE OFF) - set(FFTW_LOOK_FOR_FFTW_DOUBLE OFF) set(FFTW_LOOK_FOR_FFTW_LONG ON) set(FFTW_LOOK_FOR_FFTW_QUAD OFF) endif() if (${component} STREQUAL "QUAD") # means we look for FFTW quad precision (fftw3q) set(FFTW_LOOK_FOR_FFTW_SIMPLE OFF) - set(FFTW_LOOK_FOR_FFTW_DOUBLE OFF) set(FFTW_LOOK_FOR_FFTW_LONG OFF) set(FFTW_LOOK_FOR_FFTW_QUAD ON) endif() @@ -121,18 +113,47 @@ if( FFTW_FIND_COMPONENTS ) # means we look for the Intel MKL version of FFTW set(FFTW_LOOK_FOR_MKL ON) if (FFTW_LOOK_FOR_FFTW_LONG) - message(WARNING "Looking for FFTW -- long precision functions do not exist in MKL FFTW") - set(FFTW_LOOK_FOR_FFTW_LONG OFF) + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "Looking for FFTW -- long precision functions do not exist in MKL FFTW") + endif() + set(FFTW_LOOK_FOR_FFTW_LONG OFF) + endif() + if (FFTW_LOOK_FOR_FFTW_QUAD) + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "Looking for FFTW -- quadruple functions do not exist in MKL FFTW") + endif() + set(FFTW_LOOK_FOR_FFTW_QUAD OFF) + endif() + endif() + if (${component} STREQUAL "ESSL") + # means we look for the Intel MKL version of FFTW + set(FFTW_LOOK_FOR_ESSL ON) + if (FFTW_LOOK_FOR_FFTW_LONG) + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "Looking for FFTW -- long precision functions do not exist in FFTW_ESSL") + endif() + set(FFTW_LOOK_FOR_FFTW_LONG OFF) endif() if (FFTW_LOOK_FOR_FFTW_QUAD) - message(WARNING "Looking for FFTW -- quadruple functions do not exist in MKL FFTW") - set(FFTW_LOOK_FOR_FFTW_QUAD OFF) + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "Looking for FFTW -- quadruple functions do not exist in FFTW_ESSL") + endif() + set(FFTW_LOOK_FOR_FFTW_QUAD OFF) + endif() + if (FFTW_LOOK_FOR_OMP) + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "Looking for FFTW -- FFTW_ESSL does not use OpenMP") + endif() + set(FFTW_LOOK_FOR_OMP OFF) endif() endif() endforeach() endif() if (FFTW_LOOK_FOR_THREADS) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "FFTW looks for threads") + endif() if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_THREADS) find_package(Threads REQUIRED) else() @@ -140,23 +161,51 @@ if (FFTW_LOOK_FOR_THREADS) endif() endif() +if (FFTW_LOOK_FOR_OMP) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "FFTW looks for openmp") + endif() + if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_OMP) + find_package(OpenMP REQUIRED) + else() + find_package(OpenMP) + endif() +endif() + if (FFTW_LOOK_FOR_MKL) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "FFTW looks for threads and Intel MKL") + endif() + if (FFTW_LOOK_FOR_THREADS) + set(BLA_VENDOR "Intel10_64lp") + else() + set(BLA_VENDOR "Intel10_64lp_seq") + endif() if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_MKL) find_package(Threads REQUIRED) + find_package(BLASEXT REQUIRED) else() find_package(Threads) + find_package(BLASEXT) endif() endif() -if (FFTW_LOOK_FOR_OMP) - if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_OMP) - find_package(OpenMP REQUIRED) +if (FFTW_LOOK_FOR_ESSL) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "FFTW looks for IBM ESSL") + endif() + if (FFTW_LOOK_FOR_THREADS) + set(BLA_VENDOR "IBMESSLMT") else() - find_package(OpenMP) + set(BLA_VENDOR "IBMESSL") + endif() + if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_ESSL) + find_package(BLASEXT REQUIRED) + else() + find_package(BLASEXT) endif() endif() - set(ENV_FFTW_DIR "$ENV{FFTW_DIR}") set(ENV_FFTW_INCDIR "$ENV{FFTW_INCDIR}") set(ENV_FFTW_LIBDIR "$ENV{FFTW_LIBDIR}") @@ -165,61 +214,153 @@ if ( FFTW_DIR OR ( FFTW_INCDIR AND FFTW_LIBDIR) OR ENV_FFTW_DIR OR (ENV_FFTW_INC set(FFTW_GIVEN_BY_USER "TRUE") endif() + # Optionally use pkg-config to detect include/library dirs (if pkg-config is available) # ------------------------------------------------------------------------------------- -include(FindPkgConfig) -find_package(PkgConfig QUIET) -if( PKG_CONFIG_EXECUTABLE AND NOT FFTW_GIVEN_BY_USER ) - - if(FFTW_LOOK_FOR_FFTW_SIMPLE) - pkg_search_module(FFTW3F fftw3f) - pkg_search_module(FFTW3 fftw3) - elseif(FFTW_LOOK_FOR_FFTW_LONG) - pkg_search_module(FFTW3L fftw3l) - pkg_search_module(FFTW3 fftw3) - elseif(FFTW_LOOK_FOR_FFTW_QUAD) - pkg_search_module(FFTW3Q fftw3q) - pkg_search_module(FFTW3 fftw3) - else() - pkg_search_module(FFTW3 fftw3) - endif() - - if (NOT FFTW_FIND_QUIETLY) - if (FFTW_FOUND AND FFTW_LIBRARIES) - message(STATUS "Looking for FFTW - found using PkgConfig") - #if(NOT FFTW_INCLUDE_DIRS) - # message("${Magenta}FFTW_INCLUDE_DIRS is empty using PkgConfig." - # "Perhaps the path to hwloc headers is already present in your" - # "C(PLUS)_INCLUDE_PATH environment variable.${ColourReset}") - #endif() +if (NOT FFTW_LOOK_FOR_MKL AND NOT FFTW_LOOK_FOR_ESSL) + include(FindPkgConfig) + find_package(PkgConfig QUIET) + if( PKG_CONFIG_EXECUTABLE AND NOT FFTW_GIVEN_BY_USER ) + + set(FFTW_INCLUDE_DIRS) + set(FFTW_LIBRARY_DIRS) + set(FFTW_LIBRARIES) + + if(FFTW_LOOK_FOR_FFTW_SIMPLE) + pkg_search_module(FFTW3F fftw3f) + pkg_search_module(FFTW3 fftw3) + if (FFTW3F_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3F - found using PkgConfig") + endif() + if (FFTW3F_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${FFTW3F_LIBRARIES}") + endif() + if(FFTW3F_INCLUDE_DIRS) + list(APPEND FFTW_INCLUDE_DIRS "${FFTW3F_INCLUDE_DIRS}") + else() + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "FFTW3F_INCLUDE_DIRS is empty using PkgConfig." + "Perhaps the path to fftw3f headers is already present in your" + "CPATH/C(PLUS)_INCLUDE_PATH environment variables.") + endif() + endif() + if(FFTW3F_LIBRARY_DIRS) + list(APPEND FFTW_LIBRARY_DIRS "${FFTW3F_LIBRARY_DIRS}") + endif() + else(FFTW3F_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3F - not found using PkgConfig." + "Perhaps you should add the directory containing fftw3f.pc to" + "the PKG_CONFIG_PATH environment variable.") + endif() + endif(FFTW3F_FOUND) + elseif(FFTW_LOOK_FOR_FFTW_LONG) + pkg_search_module(FFTW3L fftw3l) + pkg_search_module(FFTW3 fftw3) + if (FFTW3L_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3L - found using PkgConfig") + endif() + if (FFTW3L_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${FFTW3L_LIBRARIES}") + endif() + if(FFTW3L_INCLUDE_DIRS) + list(APPEND FFTW_INCLUDE_DIRS "${FFTW3L_INCLUDE_DIRS}") + else() + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "FFTW3L_INCLUDE_DIRS is empty using PkgConfig." + "Perhaps the path to fftw3l headers is already present in your" + "CPATH/C(PLUS)_INCLUDE_PATH environment variables.") + endif() + endif() + if(FFTW3L_LIBRARY_DIRS) + list(APPEND FFTW_LIBRARY_DIRS "${FFTW3L_LIBRARY_DIRS}") + endif() + else(FFTW3L_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3L - not found using PkgConfig." + "Perhaps you should add the directory containing fftw3l.pc to" + "the PKG_CONFIG_PATH environment variable.") + endif() + endif(FFTW3L_FOUND) + elseif(FFTW_LOOK_FOR_FFTW_QUAD) + pkg_search_module(FFTW3Q fftw3q) + pkg_search_module(FFTW3 fftw3) + if (FFTW3Q_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3Q - found using PkgConfig") + endif() + if (FFTW3Q_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${FFTW3Q_LIBRARIES}") + endif() + if(FFTW3Q_INCLUDE_DIRS) + list(APPEND FFTW_INCLUDE_DIRS "${FFTW3Q_INCLUDE_DIRS}") + else() + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "FFTW3Q_INCLUDE_DIRS is empty using PkgConfig." + "Perhaps the path to fftw3q headers is already present in your" + "CPATH/C(PLUS)_INCLUDE_PATH environment variables.") + endif() + endif() + if(FFTW3Q_LIBRARY_DIRS) + list(APPEND FFTW_LIBRARY_DIRS "${FFTW3Q_LIBRARY_DIRS}") + endif() + else(FFTW3Q_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3Q - not found using PkgConfig." + "Perhaps you should add the directory containing fftw3q.pc to" + "the PKG_CONFIG_PATH environment variable.") + endif() + endif(FFTW3Q_FOUND) else() - message("${Magenta}Looking for FFTW - not found using PkgConfig." - "Perhaps you should add the directory containing fftw3.pc to" - "the PKG_CONFIG_PATH environment variable.${ColourReset}") + pkg_search_module(FFTW3 fftw3) endif() - endif() + if (FFTW3_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3 - found using PkgConfig") + endif() + if (FFTW3_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${FFTW3_LIBRARIES}") + endif() + if(FFTW3_INCLUDE_DIRS) + list(APPEND FFTW_INCLUDE_DIRS "${FFTW3_INCLUDE_DIRS}") + else() + if (NOT FFTW_FIND_QUIETLY) + message(WARNING "FFTW3_INCLUDE_DIRS is empty using PkgConfig." + "Perhaps the path to fftw3 headers is already present in your" + "CPATH/C(PLUS)_INCLUDE_PATH environment variables.") + endif() + endif() + if(FFTW3_LIBRARY_DIRS) + list(APPEND FFTW_LIBRARY_DIRS "${FFTW3_LIBRARY_DIRS}") + endif() + else(FFTW3_FOUND) + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW3 - not found using PkgConfig." + "Perhaps you should add the directory containing fftw3.pc to" + "the PKG_CONFIG_PATH environment variable.") + endif() + endif(FFTW3_FOUND) - set(FFTW_INCLUDE_DIRS_DEP "${FFTW_INCLUDE_DIRS}") - set(FFTW_LIBRARY_DIRS_DEP "${FFTW_LIBRARY_DIRS}") - set(FFTW_LIBRARIES_DEP) - if( FFTW3Q_LIBRARIES ) - list(APPEND FFTW_LIBRARIES_DEP "${FFTW3Q_LIBRARIES}") - endif() - if( FFTW3L_LIBRARIES ) - list(APPEND FFTW_LIBRARIES_DEP "${FFTW3L_LIBRARIES}") - endif() - if( FFTW3F_LIBRARIES ) - list(APPEND FFTW_LIBRARIES_DEP "${FFTW3F_LIBRARIES}") - endif() -if( FFTW3_LIBRARIES ) - list(APPEND FFTW_LIBRARIES_DEP "${FFTW3_LIBRARIES}") -endif() - set(FFTW_WORKS TRUE) + set(FFTW_INCLUDE_DIRS_DEP "${FFTW_INCLUDE_DIRS}") + set(FFTW_LIBRARY_DIRS_DEP "${FFTW_LIBRARY_DIRS}") + set(FFTW_LIBRARIES_DEP "${FFTW_LIBRARIES}" ) -endif( PKG_CONFIG_EXECUTABLE AND NOT FFTW_GIVEN_BY_USER ) + if (FFTW_LIBRARIES) + set(FFTW_WORKS TRUE) + endif() + endif( PKG_CONFIG_EXECUTABLE AND NOT FFTW_GIVEN_BY_USER ) -if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR (FFTW_GIVEN_BY_USER) ) +endif(NOT FFTW_LOOK_FOR_MKL AND NOT FFTW_LOOK_FOR_ESSL) + +if( (NOT PKG_CONFIG_EXECUTABLE) OR + (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR + FFTW_GIVEN_BY_USER OR + FFTW_LOOK_FOR_MKL OR + FFTW_LOOK_FOR_ESSL + ) # Looking for include # ------------------- @@ -262,39 +403,45 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR # set paths where to look for set(PATH_TO_LOOK_FOR "${_inc_env}") + if (FFTW_LOOK_FOR_ESSL) + set(FFTW3_HEADER_TO_FIND "fftw3_essl.h") + else() + set(FFTW3_HEADER_TO_FIND "fftw3.h") + endif() + # Try to find the fftw header in the given paths # ------------------------------------------------- # call cmake macro to find the header path if(FFTW_INCDIR) - set(FFTW_fftw3.h_DIRS "FFTW_fftw3.h_DIRS-NOTFOUND") - find_path(FFTW_fftw3.h_DIRS - NAMES fftw3.h + set(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS "FFTW_${FFTW3_HEADER_TO_FIND}_DIRS-NOTFOUND") + find_path(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS + NAMES ${FFTW3_HEADER_TO_FIND} HINTS ${FFTW_INCDIR}) else() if(FFTW_DIR) - set(FFTW_fftw3.h_DIRS "FFTW_fftw3.h_DIRS-NOTFOUND") - find_path(FFTW_fftw3.h_DIRS - NAMES fftw3.h + set(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS "FFTW_${FFTW3_HEADER_TO_FIND}_DIRS-NOTFOUND") + find_path(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS + NAMES ${FFTW3_HEADER_TO_FIND} HINTS ${FFTW_DIR} PATH_SUFFIXES "include" "include/fftw") else() - set(FFTW_fftw3.h_DIRS "FFTW_fftw3.h_DIRS-NOTFOUND") - find_path(FFTW_fftw3.h_DIRS - NAMES fftw3.h + set(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS "FFTW_${FFTW3_HEADER_TO_FIND}_DIRS-NOTFOUND") + find_path(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS + NAMES ${FFTW3_HEADER_TO_FIND} HINTS ${PATH_TO_LOOK_FOR} PATH_SUFFIXES "fftw") endif() endif() - mark_as_advanced(FFTW_fftw3.h_DIRS) + mark_as_advanced(FFTW_${FFTW3_HEADER_TO_FIND}_DIRS) # Add path to cmake variable # ------------------------------------ - if (FFTW_fftw3.h_DIRS) - set(FFTW_INCLUDE_DIRS "${FFTW_fftw3.h_DIRS}") + if (FFTW_${FFTW3_HEADER_TO_FIND}_DIRS) + set(FFTW_INCLUDE_DIRS "${FFTW_${FFTW3_HEADER_TO_FIND}_DIRS}") else () set(FFTW_INCLUDE_DIRS "FFTW_INCLUDE_DIRS-NOTFOUND") if(NOT FFTW_FIND_QUIETLY) - message(STATUS "Looking for FFTW -- fftw3.h not found") + message(STATUS "Looking for FFTW -- ${FFTW3_HEADER_TO_FIND} not found") endif() endif () @@ -350,52 +497,21 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR if(FFTW_LOOK_FOR_FFTW_SIMPLE) set(FFTW_PREC "f") set(FFTW_PREC_TESTFUNC "s") - elseif(FFTW_LOOK_FOR_FFTW_DOUBLE) - set(FFTW_PREC "") - set(FFTW_PREC_TESTFUNC "d") elseif(FFTW_LOOK_FOR_FFTW_LONG) set(FFTW_PREC "l") set(FFTW_PREC_TESTFUNC "l") elseif(FFTW_LOOK_FOR_FFTW_QUAD) set(FFTW_PREC "q") set(FFTW_PREC_TESTFUNC "q") + else() + set(FFTW_PREC "") + set(FFTW_PREC_TESTFUNC "d") endif() - if (FFTW_LOOK_FOR_MKL) - - set(FFTW_libs_to_find "mkl_intel_lp64;mkl_sequential;mkl_core") - - # Try to find the MKL fftw lib in the given paths - # ----------------------------------------------- - - # call cmake macro to find the lib path - if(FFTW_LIBDIR) - foreach(fftw_lib ${FFTW_libs_to_find}) - set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") - find_library(FFTW_${fftw_lib}_LIBRARY - NAMES ${fftw_lib} - HINTS ${FFTW_LIBDIR}) - endforeach() - else() - if(FFTW_DIR) - foreach(fftw_lib ${FFTW_libs_to_find}) - set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") - find_library(FFTW_${fftw_lib}_LIBRARY - NAMES ${fftw_lib} - HINTS ${FFTW_DIR} - PATH_SUFFIXES lib lib32 lib64) - endforeach() - else() - foreach(fftw_lib ${FFTW_libs_to_find}) - set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") - find_library(FFTW_${fftw_lib}_LIBRARY - NAMES ${fftw_lib} - HINTS ${PATH_TO_LOOK_FOR}) - endforeach() - endif() - endif() + set(FFTW_LIBRARIES "") + set(FFTW_LIBRARY_DIRS "") - else(FFTW_LOOK_FOR_MKL) + if(NOT FFTW_LOOK_FOR_MKL) if (FFTW_LOOK_FOR_THREADS) set(FFTW_libs_to_find "fftw3${FFTW_PREC}_threads;fftw3${FFTW_PREC};fftw3") @@ -404,6 +520,15 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR else() set(FFTW_libs_to_find "fftw3${FFTW_PREC};fftw3") endif() + if (FFTW_LOOK_FOR_FFTW_QUAD) + if (NOT FFTW_LOOK_FOR_MKL AND NOT FFTW_LOOK_FOR_ESSL) + list(APPEND FFTW_libs_to_find "quadmath") + endif() + endif() + + if (FFTW_LOOK_FOR_ESSL) + set(FFTW_libs_to_find "fftw3_essl") + endif() # Try to find the fftw lib in the given paths # ---------------------------------------------- @@ -411,56 +536,147 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR # call cmake macro to find the lib path if(FFTW_LIBDIR) foreach(fftw_lib ${FFTW_libs_to_find}) - set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") - find_library(FFTW_${fftw_lib}_LIBRARY - NAMES ${fftw_lib} - HINTS ${FFTW_LIBDIR}) + set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") + find_library(FFTW_${fftw_lib}_LIBRARY + NAMES ${fftw_lib} + HINTS ${FFTW_LIBDIR}) endforeach() else() if(FFTW_DIR) - foreach(fftw_lib ${FFTW_libs_to_find}) - set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") - find_library(FFTW_${fftw_lib}_LIBRARY - NAMES ${fftw_lib} - HINTS ${FFTW_DIR} - PATH_SUFFIXES lib lib32 lib64) - endforeach() + foreach(fftw_lib ${FFTW_libs_to_find}) + set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") + find_library(FFTW_${fftw_lib}_LIBRARY + NAMES ${fftw_lib} + HINTS ${FFTW_DIR} + PATH_SUFFIXES lib lib32 lib64) + endforeach() else() - foreach(fftw_lib ${FFTW_libs_to_find}) - set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") - find_library(FFTW_${fftw_lib}_LIBRARY - NAMES ${fftw_lib} - HINTS ${PATH_TO_LOOK_FOR}) - endforeach() + foreach(fftw_lib ${FFTW_libs_to_find}) + set(FFTW_${fftw_lib}_LIBRARY "FFTW_${fftw_lib}_LIBRARY-NOTFOUND") + find_library(FFTW_${fftw_lib}_LIBRARY + NAMES ${fftw_lib} + HINTS ${PATH_TO_LOOK_FOR}) + endforeach() endif() endif() - endif(FFTW_LOOK_FOR_MKL) + # If found, add path to cmake variable + # ------------------------------------ + foreach(fftw_lib ${FFTW_libs_to_find}) + + if (FFTW_${fftw_lib}_LIBRARY) + get_filename_component(${fftw_lib}_lib_path "${FFTW_${fftw_lib}_LIBRARY}" PATH) + # set cmake variables + list(APPEND FFTW_LIBRARIES "${FFTW_${fftw_lib}_LIBRARY}") + list(APPEND FFTW_LIBRARY_DIRS "${${fftw_lib}_lib_path}") + else () + list(APPEND FFTW_LIBRARIES "${FFTW_${fftw_lib}_LIBRARY}") + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Looking for FFTW -- lib ${fftw_lib} not found") + endif() + endif () + mark_as_advanced(FFTW_${fftw_lib}_LIBRARY) - # If found, add path to cmake variable - # ------------------------------------ - set(FFTW_LIBRARIES "") - set(FFTW_LIBRARY_DIRS "") - foreach(fftw_lib ${FFTW_libs_to_find}) - - if (FFTW_${fftw_lib}_LIBRARY) - get_filename_component(${fftw_lib}_lib_path "${FFTW_${fftw_lib}_LIBRARY}" PATH) - # set cmake variables - list(APPEND FFTW_LIBRARIES "${FFTW_${fftw_lib}_LIBRARY}") - list(APPEND FFTW_LIBRARY_DIRS "${${fftw_lib}_lib_path}") - else () - list(APPEND FFTW_LIBRARIES "${FFTW_${fftw_lib}_LIBRARY}") + endforeach() + + # check if one lib is NOTFOUND + foreach(lib ${FFTW_LIBRARIES}) + if (NOT lib) + set(FFTW_LIBRARIES "FFTW_LIBRARIES-NOTFOUND") + endif() + endforeach() + + endif(NOT FFTW_LOOK_FOR_MKL) + + if (FFTW_LOOK_FOR_MKL OR FFTW_LOOK_FOR_ESSL) + + # FFTW relies on blas libs + if (FFTW_LOOK_FOR_THREADS) + if (FFTW_LOOK_FOR_MKL) + if (BLAS_PAR_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${BLAS_PAR_LIBRARIES}") + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Multithreaded FFTW has been found: ${FFTW_LIBRARIES}") + endif() + else() + if (NOT FFTW_FIND_QUIETLY) + if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_MKL) + message(FATAL_ERROR "FFTW is required but not found.") + else() + message(STATUS "Multithreaded FFTW not found.") + endif() + endif() + endif(BLAS_PAR_LIBRARIES) + elseif (FFTW_LOOK_FOR_ESSL) + if (FFTW_LIBRARIES AND BLAS_PAR_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${BLAS_PAR_LIBRARIES}") + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "Multithreaded FFTW has been found: ${FFTW_LIBRARIES}") + endif() + else() + if (NOT FFTW_FIND_QUIETLY) + if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_MKL) + message(FATAL_ERROR "FFTW is required but not found.") + else() + message(STATUS "Multithreaded FFTW not found.") + endif() + endif() + endif(FFTW_LIBRARIES AND BLAS_PAR_LIBRARIES) + endif() + else(FFTW_LOOK_FOR_THREADS) + if (FFTW_LOOK_FOR_MKL) + if (BLAS_SEQ_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${BLAS_SEQ_LIBRARIES}") + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "FFTW has been found: ${FFTW_LIBRARIES}") + endif() + else() + if (NOT FFTW_FIND_QUIETLY) + if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_MKL) + message(FATAL_ERROR "FFTW is required but not found.") + else() + message(STATUS "FFTW not found.") + endif() + endif() + endif(BLAS_SEQ_LIBRARIES) + elseif (FFTW_LOOK_FOR_ESSL) + if (FFTW_LIBRARIES AND BLAS_SEQ_LIBRARIES) + list(APPEND FFTW_LIBRARIES "${BLAS_SEQ_LIBRARIES}") + if (NOT FFTW_FIND_QUIETLY) + message(STATUS "FFTW has been found: ${FFTW_LIBRARIES}") + endif() + else() + if (NOT FFTW_FIND_QUIETLY) + if (FFTW_FIND_REQUIRED AND FFTW_FIND_REQUIRED_MKL) + message(FATAL_ERROR "FFTW is required but not found.") + else() + message(STATUS "FFTW not found.") + endif() + endif() + endif(FFTW_LIBRARIES AND BLAS_SEQ_LIBRARIES) + endif() + endif(FFTW_LOOK_FOR_THREADS) + + if (BLAS_LIBRARY_DIRS) + list(APPEND FFTW_LIBRARY_DIRS "${BLAS_LIBRARY_DIRS}") + else() if (NOT FFTW_FIND_QUIETLY) - message(STATUS "Looking for FFTW -- lib ${fftw_lib} not found") + message(WARNING "FFTW_LIBRARY_DIRS may not be complete because BLAS_LIBRARY_DIRS is empty.") endif() - endif () - mark_as_advanced(FFTW_${fftw_lib}_LIBRARY) + endif() - endforeach() + endif(FFTW_LOOK_FOR_MKL OR FFTW_LOOK_FOR_ESSL) list(REMOVE_DUPLICATES FFTW_INCLUDE_DIRS) list(REMOVE_DUPLICATES FFTW_LIBRARY_DIRS) + # check if one lib is NOTFOUND + foreach(lib ${FFTW_LIBRARIES}) + if (NOT lib) + set(FFTW_LIBRARIES "FFTW_LIBRARIES-NOTFOUND") + endif() + endforeach() + # check a function to validate the find if(FFTW_LIBRARIES) @@ -484,21 +700,21 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR endif() # OMP if(FFTW_LOOK_FOR_OMP) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - # either gomp ... - #set(REQUIRED_FLAGS "-fopenmp") - #list(APPEND REQUIRED_LIBS "-lgomp") - # or iomp5 - list(APPEND REQUIRED_LIBS "-liomp5") - elseif (CMAKE_C_COMPILER_ID STREQUAL "Intel") - list(APPEND REQUIRED_LIBS "-liomp5") - endif() + set(REQUIRED_FLAGS "-fopenmp") + #if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + # # either gomp ... + # list(APPEND REQUIRED_LIBS "-lgomp") + # # or iomp5 + # list(APPEND REQUIRED_LIBS "-liomp5") + #elseif (CMAKE_C_COMPILER_ID STREQUAL "Intel") + # list(APPEND REQUIRED_LIBS "-liomp5") + #endif() endif() # MKL if(FFTW_LOOK_FOR_MKL) list(APPEND REQUIRED_LIBS "${CMAKE_THREAD_LIBS_INIT}") if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") - list(APPEND REQUIRED_LDFLAGS "-Wl,--no-as-needed") + list(APPEND REQUIRED_LDFLAGS "-Wl,--no-as-needed") endif() endif() # m @@ -521,7 +737,11 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR # test link unset(FFTW_WORKS CACHE) include(CheckFunctionExists) - check_function_exists(${FFTW_PREC_TESTFUNC}fftw_execute_ FFTW_WORKS) + if (FFTW_LOOK_FOR_ESSL) + check_function_exists(${FFTW_PREC_TESTFUNC}fftw_execute FFTW_WORKS) + else() + check_function_exists(${FFTW_PREC_TESTFUNC}fftw_execute_ FFTW_WORKS) + endif() mark_as_advanced(FFTW_WORKS) if(FFTW_WORKS) @@ -550,7 +770,12 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR set(CMAKE_REQUIRED_LIBRARIES) endif(FFTW_LIBRARIES) -endif( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR (FFTW_GIVEN_BY_USER) ) +endif( (NOT PKG_CONFIG_EXECUTABLE) OR + (PKG_CONFIG_EXECUTABLE AND NOT FFTW_FOUND) OR + FFTW_GIVEN_BY_USER OR + FFTW_LOOK_FOR_MKL OR + FFTW_LOOK_FOR_ESSL + ) if (FFTW_LIBRARIES) list(GET FFTW_LIBRARIES 0 first_lib) diff --git a/CMakeModules/morse/find/FindLAPACK.cmake b/CMakeModules/morse/find/FindLAPACK.cmake index 668453dab6eb413fe24cf3a1ea90ee4b37dae8fd..c9da7bd9dc8630af8f5ddc5bfb4dc393fd089bf5 100644 --- a/CMakeModules/morse/find/FindLAPACK.cmake +++ b/CMakeModules/morse/find/FindLAPACK.cmake @@ -41,7 +41,7 @@ # environment variable # Note that if BLAS_DIR is set, it will also look for lapack in it ### List of vendors (BLA_VENDOR) valid in this module -## Intel(mkl), ACML,Apple, NAS, Generic +## Intel(mkl), ACML, Apple, NAS, Generic #============================================================================= # Copyright 2007-2009 Kitware, Inc. @@ -347,6 +347,7 @@ endif() #intel lapack if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") + if (_LANGUAGES_ MATCHES C OR _LANGUAGES_ MATCHES CXX) if(LAPACK_FIND_QUIETLY OR NOT LAPACK_FIND_REQUIRED) find_PACKAGE(Threads) @@ -391,7 +392,7 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") if (NOT ${_LIBRARIES}) check_lapack_libraries( ${_LIBRARIES} - BLAS + LAPACK ${LAPACK_mkl_SEARCH_SYMBOL} "${additional_flags}" "" @@ -407,7 +408,7 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") if (NOT ${_LIBRARIES}) check_lapack_libraries( ${_LIBRARIES} - BLAS + LAPACK ${LAPACK_mkl_SEARCH_SYMBOL} "${additional_flags}" "${IT}" @@ -419,6 +420,13 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") endif() endif () endforeach () + if(NOT LAPACK_FIND_QUIETLY) + if(${_LIBRARIES}) + message(STATUS "Looking for MKL LAPACK: found") + else() + message(STATUS "Looking for MKL LAPACK: not found") + endif() + endif() endif () endif() @@ -434,16 +442,73 @@ if (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All") "${BLAS_LIBRARIES}" "" ) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for Goto LAPACK: found") + else() + message(STATUS "Looking for Goto LAPACK: not found") + endif() + endif() endif(NOT LAPACK_LIBRARIES) endif (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All") +# LAPACK in IBM ESSL library (requires generic lapack lib, too) +if (BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All") + if(NOT LAPACK_LIBRARIES) + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheevd + "" + "essl;lapack" + "${BLAS_LIBRARIES}" + "" + ) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for IBM ESSL LAPACK: found") + else() + message(STATUS "Looking for IBM ESSL LAPACK: not found") + endif() + endif() + endif() +endif () + +# LAPACK in IBM ESSL_MT library (requires generic lapack lib, too) +if (BLA_VENDOR STREQUAL "IBMESSLMT" OR BLA_VENDOR STREQUAL "All") + if(NOT LAPACK_LIBRARIES) + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheevd + "" + "esslsmp;lapack" + "${BLAS_PAR_LIBRARIES}" + "" + ) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for IBM ESSL MT LAPACK: found") + else() + message(STATUS "Looking for IBM ESSL MT LAPACK: not found") + endif() + endif() + endif() +endif () #acml lapack - if (BLA_VENDOR MATCHES "ACML.*" OR BLA_VENDOR STREQUAL "All") +if (BLA_VENDOR MATCHES "ACML.*" OR BLA_VENDOR STREQUAL "All") if (BLAS_LIBRARIES MATCHES ".+acml.+") set (LAPACK_LIBRARIES ${BLAS_LIBRARIES}) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for ACML LAPACK: found") + else() + message(STATUS "Looking for ACML LAPACK: not found") + endif() + endif() endif () - endif () +endif () # Apple LAPACK library? if (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All") @@ -457,8 +522,16 @@ if (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All") "${BLAS_LIBRARIES}" "" ) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for Apple Accelerate LAPACK: found") + else() + message(STATUS "Looking for Apple Accelerate LAPACK: not found") + endif() + endif() endif(NOT LAPACK_LIBRARIES) endif (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All") + if (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All") if ( NOT LAPACK_LIBRARIES ) check_lapack_libraries( @@ -470,8 +543,16 @@ if (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All") "${BLAS_LIBRARIES}" "" ) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for NAS LAPACK: found") + else() + message(STATUS "Looking for NAS LAPACK: not found") + endif() + endif() endif ( NOT LAPACK_LIBRARIES ) endif (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All") + # Generic LAPACK library? if (BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "ATLAS" OR @@ -486,6 +567,13 @@ if (BLA_VENDOR STREQUAL "Generic" OR "${BLAS_LIBRARIES};${LM}" "" ) + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_LIBRARIES) + message(STATUS "Looking for Generic LAPACK: found") + else() + message(STATUS "Looking for Generic LAPACK: not found") + endif() + endif() endif ( NOT LAPACK_LIBRARIES ) endif () else(BLAS_FOUND) diff --git a/CMakeModules/morse/find/FindLAPACKEXT.cmake b/CMakeModules/morse/find/FindLAPACKEXT.cmake index 420b898d9f10b9c2f8588ca2ea700f639c4e14cf..b3a397d2075107b69ddbd241b02f3d5a85ab54b5 100644 --- a/CMakeModules/morse/find/FindLAPACKEXT.cmake +++ b/CMakeModules/morse/find/FindLAPACKEXT.cmake @@ -13,10 +13,8 @@ # This module allows to find LAPACK libraries by calling the official FindLAPACK module # and handles the creation of different library lists whether the user wishes to link # with a sequential LAPACK or a multihreaded (LAPACK_SEQ_LIBRARIES and LAPACK_PAR_LIBRARIES). -# LAPACK is detected with a FindLAPACK call then if the LAPACK vendor is in the following list, -# Intel mkl, Goto, Openlapack, ACML, IBMESSL -# then the module tries find the corresponding multithreaded libraries -# LAPACK_LIBRARIES does not exists anymore. +# LAPACK is detected with a FindLAPACK call and if the BLAS vendor is in the following list, +# Intel mkl, ACML then the module tries find the corresponding multithreaded libraries # # The following variables have been added to manage links with sequential or multithreaded # versions: @@ -54,6 +52,7 @@ if (NOT BLAS_FOUND) endif() endif () +message(STATUS "In FindLAPACKEXT") if(BLA_VENDOR MATCHES "Intel*") @@ -145,6 +144,42 @@ if(BLA_VENDOR MATCHES "Intel*") endif() endif() +elseif(BLA_VENDOR MATCHES "IBMESSL*") + + ## look for the sequential version + set(BLA_VENDOR "IBMESSL") + + if(LAPACKEXT_FIND_REQUIRED) + find_package(LAPACK REQUIRED) + else() + find_package(LAPACK) + endif() + + if (LAPACK_FOUND) + if(LAPACK_LIBRARIES) + set(LAPACK_SEQ_LIBRARIES "${LAPACK_LIBRARIES}") + else() + set(LAPACK_SEQ_LIBRARIES "${LAPACK_SEQ_LIBRARIES-NOTFOUND}") + endif() + endif() + + ## look for the multithreaded version + set(BLA_VENDOR "IBMESSLMT") + + if(LAPACKEXT_FIND_REQUIRED) + find_package(LAPACK REQUIRED) + else() + find_package(LAPACK) + endif() + + if (LAPACK_FOUND) + if(LAPACK_LIBRARIES) + set(LAPACK_PAR_LIBRARIES "${LAPACK_LIBRARIES}") + else() + set(LAPACK_PAR_LIBRARIES "${LAPACK_PAR_LIBRARIES-NOTFOUND}") + endif() + endif() + elseif(BLA_VENDOR MATCHES "ACML*") ### @@ -228,14 +263,6 @@ if (LAPACK_LIBRARY_DIRS) endif () -# message(STATUS "LAPACK_FOUND: ${LAPACK_FOUND}") -# message(STATUS "LAPACK_VENDOR: ${LAPACK_VENDOR}") -# message(STATUS "LAPACK_LIBRARIES: ${LAPACK_LIBRARIES}") -# message(STATUS "LAPACK_SEQ_LIBRARIES: ${LAPACK_SEQ_LIBRARIES}") -# message(STATUS "LAPACK_PAR_LIBRARIES: ${LAPACK_PAR_LIBRARIES}") -# message(STATUS "LAPACK_INCLUDE_DIRS: ${LAPACK_INCLUDE_DIRS}") -# message(STATUS "LAPACK_LIBRARY_DIRS: ${LAPACK_LIBRARY_DIRS}") - # check that LAPACK has been found # --------------------------------- include(FindPackageHandleStandardArgs) @@ -283,8 +310,27 @@ elseif(BLA_VENDOR MATCHES "ACML*") endif() find_package_handle_standard_args(LAPACK DEFAULT_MSG LAPACK_SEQ_LIBRARIES - LAPACK_LIBRARY_DIRS - LAPACK_INCLUDE_DIRS) + LAPACK_LIBRARY_DIRS) + if(LAPACK_PAR_LIBRARIES) + if(NOT LAPACKEXT_FIND_QUIETLY) + message(STATUS "LAPACK parallel libraries stored in" + "LAPACK_PAR_LIBRARIES") + endif() + find_package_handle_standard_args(LAPACK DEFAULT_MSG + LAPACK_PAR_LIBRARIES) + endif() +elseif(BLA_VENDOR MATCHES "IBMESSL*") + if(NOT LAPACKEXT_FIND_QUIETLY) + message(STATUS "LAPACK found is IBMESSL:" + "we manage two lists of libs," + " one sequential and one parallel (see" + "LAPACK_SEQ_LIBRARIES and LAPACK_PAR_LIBRARIES)") + message(STATUS "LAPACK sequential libraries stored in" + "LAPACK_SEQ_LIBRARIES") + endif() + find_package_handle_standard_args(LAPACK DEFAULT_MSG + LAPACK_SEQ_LIBRARIES + LAPACK_LIBRARY_DIRS) if(LAPACK_PAR_LIBRARIES) if(NOT LAPACKEXT_FIND_QUIETLY) message(STATUS "LAPACK parallel libraries stored in" diff --git a/CMakeModules/morse/find/FindSTARPU.cmake b/CMakeModules/morse/find/FindSTARPU.cmake index a64c187d06d157223aa17c5a37147c5ab423ad3d..a2b1ed209b7444fc4c10f31d248cd2d78972795e 100644 --- a/CMakeModules/morse/find/FindSTARPU.cmake +++ b/CMakeModules/morse/find/FindSTARPU.cmake @@ -465,14 +465,23 @@ if( (NOT PKG_CONFIG_EXECUTABLE) OR (PKG_CONFIG_EXECUTABLE AND NOT STARPU_FOUND) find_path(STARPU_${starpu_hdr}_INCLUDE_DIRS NAMES ${starpu_hdr} HINTS ${STARPU_DIR} - PATH_SUFFIXES "include/starpu/${STARPU_VERSION_STRING}") + PATH_SUFFIXES "include" + "include/starpu/1.0" + "include/starpu/1.1" + "include/starpu/1.2" + "include/starpu/1.3") endforeach() else() foreach(starpu_hdr ${STARPU_hdrs_to_find}) set(STARPU_${starpu_hdr}_INCLUDE_DIRS "STARPU_${starpu_hdr}_INCLUDE_DIRS-NOTFOUND") find_path(STARPU_${starpu_hdr}_INCLUDE_DIRS NAMES ${starpu_hdr} - HINTS ${_inc_env}) + HINTS ${_inc_env} + PATH_SUFFIXES + "starpu/1.0" + "starpu/1.1" + "starpu/1.2" + "starpu/1.3") endforeach() endif() endif() diff --git a/Examples/changeFmaFormat.cpp b/Examples/changeFmaFormat.cpp index 7e2c76350e7eeadb44e3b6ac0325be2c563cfecd..45932744e733e6d5090c0bd19c549872cf1868eb 100644 --- a/Examples/changeFmaFormat.cpp +++ b/Examples/changeFmaFormat.cpp @@ -87,7 +87,7 @@ int main(int argc, char ** argv){ // Generate file for visualization purpose // if(FParameters::existParameter(argc, argv, FParameterDefinitions::OutputVisuFile.options)){ - std::string outfilename(FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "output.vtp")); + std::string outfilename(FParameters::getStr(argc,argv,FParameterDefinitions::OutputVisuFile.options, "output.vtp")); driverExportData(outfilename, particles , NbPoints,loader.getNbRecordPerline() ); } // diff --git a/Examples/fuseDistributions.cpp b/Examples/fuseDistributions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5a6535cc3aa4e249836e23ace2db64b856aed39 --- /dev/null +++ b/Examples/fuseDistributions.cpp @@ -0,0 +1,287 @@ +/** + * \file + * \brief Fuses FMA files to create a new distribution + * + * \author Quentin Khan + * \copyright ScalFmm 2016 INRIA + * \copyright [CeCILL-C licence](http://www.cecill.info) + * + * + */ + +#include +#include +#include +#include +#include + + +#include "Files/FFmaGenericLoader.hpp" + + +void usage(const std::string& progname) { + std::size_t start = progname.find_last_of('/'); + std::string name = progname.substr(start+1); + std::cout << + "usage: " << name << + " --file [[-s scale] [-c cx:cy:cz] [-g gx:gy:gz]] filename" + " -fout output_file" + " [--extra-length length]" + "\n" + "\n" + "Fuses multiple particle distributions into a bigger one." + "\n" + "\n" + "Options:\n" + " -fout output_file\n" + " The output file name, must hase .bfma or .fma extension\n" + "\n" + " --file [opts] filename [opts]\n" + " Add a .fma or .bfma distibution file. Multiple files may be specified by\n" + " adding more --file options. 'opts' is a combination of:\n" + " -s scale\n" + " Scale the distribution by 'scale' factor.\n" + " -c cx:cy:cz\n" + " Center the distribution at given coordinates. cx, cy and cz are\n" + " floating point numbers.\n" + " -g gx:gy:gz\n" + " Duplicate the distribution inside a grid of gx by gy by gz dimensions.\n" + " gx, gy and gz are integers. The grid center is governed by the -c \n" + " option.\n" + " -r rx:ry:rz\n" + " Rotate the distribution around its x, y and z axes. The rotation \n" + " center is the distribution center. rx, ry and rz are in radians.\n" + "\n" + " --extra-length length\n" + " Length to be added to the final box width.\n" + "\n" + " --help\n" + " Print this message." + "\n" + ; +} + + +using FReal = double; + +struct Particle { + FPoint pos; + FReal val; +}; + +/// Distribution options +struct distribution { + /// Distribution filename + std::string filename = ""; + /// Distribution offset from center + FPoint offset = {0,0,0}; + /// Distribution rotation around its center + FPoint rot = {0,0,0}; + /// Distribution scale factor + FReal scale = 1; +}; + + + +struct parameters { + std::string output_filename; + std::vector distributions; + FReal extra_length; +}; + +std::vector subparse_file(const std::vector& args, std::size_t& i) { + std::stringstream sstr; + // Grid layout + unsigned int gx = 1, gy = 1, gz = 1; + // Final distributions, one per grid part + std::vector distributions; + // Distributions options + distribution dist; + + while(i < args.size() && args[i] != "--file") { + sstr.clear(); + if(false) { + } else if(args[i] == "-s") { + ++i; + sstr.str(args.at(i)); + sstr >> dist.scale; + } else if (args[i] == "-c") { + ++i; + char c; // Used to discard the ':' from argument format + sstr.str(args.at(i)); + sstr >> dist.offset[0] >> c >> dist.offset[1] >> c >> dist.offset[2]; + } else if(args[i] == "-g") { + ++i; + char c; // Used to discard the ':' from argument format + sstr.str(args.at(i)); + sstr >> gx >> c >> gy >> c >> gz; + } else if(args[i] == "-r") { + ++i; + char c; // Used to discard the ':' from argument format + sstr.str(args.at(i)); + sstr >> dist.rot[0] >> c >> dist.rot[1] >> c >> dist.rot[2]; + } else { + if(dist.filename != "") { + --i; + break; + } + dist.filename = args[i]; + } + ++i; + } + + if(gx > 1 || gy > 1 || gz > 1) { + + // Compute offset of lowest left grid offset + FFmaGenericLoader loader(dist.filename); + FReal box_width = loader.getBoxWidth() * dist.scale; + dist.offset[0] -= (gx-1) * box_width / 2; + dist.offset[1] -= (gy-1) * box_width / 2; + dist.offset[2] -= (gz-1) * box_width / 2; + + // Create one distribution for each part of the grid layout + for(unsigned int x = 0; x < gx; ++x) { + for(unsigned int y = 0; y < gy; ++y) { + for(unsigned int z = 0; z < gz; ++z) { + distribution tmp_dist = dist; + tmp_dist.offset[0] += x * box_width; + tmp_dist.offset[1] += y * box_width; + tmp_dist.offset[2] += z * box_width; + distributions.push_back(tmp_dist); + } + } + } + } else { + distributions.push_back(dist); + } + + return distributions; +} + + +parameters parse(const std::vector& args) { + parameters params; + std::stringstream sstr; + for(std::size_t i = 1; i < args.size(); ++i) { + if(args[i] == "--help") { + usage(args[0]); + exit(0); + } else if(args[i] == "--file") { + ++i; + auto ds = subparse_file(args, i); + params.distributions.insert(params.distributions.end(), + ds.begin(), ds.end()); + } else if(args[i] == "--extra-length") { + ++i; + sstr.str(args.at(i)); + sstr >> params.extra_length; + } else if(args[i] == "-fout") { + ++i; + params.output_filename = args.at(i); + } else { + std::cerr << "Unknown or misplaced parameters: " << args[i] << '\n'; + } + } + return params; +} + + +void rotate(Particle& p, const distribution& dist) { + // Rotate around x axis + if(dist.rot[0] > 1e-5 || dist.rot[0] < -1e-5) { + FReal alpha = dist.rot[0]; + p.pos[1] = p.pos[1] * cos(alpha) - p.pos[2] * sin(alpha); + p.pos[2] = p.pos[1] * sin(alpha) + p.pos[2] * cos(alpha); + } + // Rotate around y axis + if(dist.rot[1] > 1e-5 || dist.rot[1] < -1e-5) { + FReal alpha = dist.rot[1]; + p.pos[0] = p.pos[0] * cos(alpha) + p.pos[2] * sin(alpha); + p.pos[2] = -p.pos[0] * sin(alpha) + p.pos[2] * cos(alpha); + } + // Rotate around z axis + if(dist.rot[2] > 1e-5 || dist.rot[2] < -1e-5) { + FReal alpha = dist.rot[1]; + p.pos[0] = p.pos[0] * cos(alpha) - p.pos[1] * sin(alpha); + p.pos[1] = p.pos[0] * sin(alpha) + p.pos[1] * cos(alpha); + } +} + + + + + + +int main(int argc, char** argv) { + auto params = parse({argv,argv+argc}); + + // Fail early if output file raises an error + FFmaGenericWriter writer(params.output_filename); + + // Fuse particle distributions + std::vector particles; + FReal axis_max = 0; + + for(distribution& dist : params.distributions) { + // Load particles into array + FFmaGenericLoader loader(dist.filename); + const std::size_t count = loader.getParticleCount(); + // Particle array: x1, y1, z1, val1, x2, y2... + particles.reserve(particles.size() + count); + + FPoint center = loader.getBoxCenter(); + + // Temp particle + Particle p; + for(std::size_t i = 0; i < count; ++i) { + loader.fillParticle(&p.pos, &p.val); + // Move distribution center to origin + p.pos -= center; + // Scale distribution + p.pos *= dist.scale; + // Rotate distribution + rotate(p, dist); + // Move to new position + p.pos += dist.offset; + // Add particle to list + particles.push_back(p); + + // Save particle x,y,z min/max to compute final box + axis_max = std::max(std::abs(p.pos[0]), axis_max); + axis_max = std::max(std::abs(p.pos[1]), axis_max); + axis_max = std::max(std::abs(p.pos[2]), axis_max); + } + } + + + // Write final distribution + FPoint center(0,0,0); + // Compute final box width + FReal box_width = 2 * (axis_max + params.extra_length); + + // Write header + writer.writeHeader(center, box_width, particles.size(), 8, 4); + + // Write all particles + + // Buffer avoids duplicating particle vector + std::vector buffer; + buffer.reserve(4*1024); // Avoid reallocations, size is a multiple of 4 + + auto cur = particles.begin(); + auto sentinel = particles.end(); + + // Fill and write buffer until we're done + while(cur != sentinel) { + buffer.clear(); + while(buffer.size() != buffer.capacity() && cur != sentinel) { + buffer.push_back(cur->pos[0]); + buffer.push_back(cur->pos[1]); + buffer.push_back(cur->pos[2]); + buffer.push_back(cur->val); + ++cur; + } + writer.writeArrayOfReal(buffer.data(), 4, buffer.size()/4); + } + +} diff --git a/Src/Adaptive/new/FBox.hpp b/Src/Adaptive/new/FBox.hpp deleted file mode 100644 index 71146022a20948830a662126280805527f079d37..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FBox.hpp +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef SCALFMM_BOX_HPP_ -#define SCALFMM_BOX_HPP_ - -#include - -#include "FZCurve.hpp" - -/* Implements a N dimensions box - * - * \author Quentin Khan - * - * The box is described by two opposite corners : the maximum and - * the minimum one. All the class transformations maintain this - * predicate. - * - * \tparam Real Floating number representation. - * \tparam Dim Space dimension count. - * \tparam SpaceFillingCurve A templatize implementation of a space filling curve - * - */ -template class SpaceFillingCurve = FZCurve> -class FBox { -public: - /// Position type - using position_t = _Position; - /// Floating number representation - using Real = typename position_t::Real; - /// Space dimension - constexpr static const std::size_t Dim = position_t::Dim; - /// Space filling curve type - using space_filling_curve_t = SpaceFillingCurve; - -private: - position_t _c1; ///< Minimum corner - position_t _c2; ///< Maximum corner - position_t _center; ///< Center - - /** Rearranges the corners to ensure the maximum-minimum predicate */ - void rearrange_corners () { - for(std::size_t i = 0; i < Dim; ++i){ - if(_c1[i] > _c2[i]) { - std::swap(_c1[i], _c2[i]); - } - } - _center = (_c1 + _c2) / 2; - } -public: - /// Accessor for the minimum corner - const position_t& c1 = _c1; - /// Accessor for the maximum corner - const position_t& c2 = _c2; - - /** Builds an empty box at the origin */ - FBox() = default; - /** Copies an existing box */ - FBox(const FBox& other) : _c1(other._c1), _c2(other._c2), _center(other._center) {} - - /** Copies an other box */ - FBox& operator=(const FBox& other) { - this->_c1 = other._c1; - this->_c2 = other._c2; - this->_center = other._center; - return *this; - } - - /** Builds a cube from the lower corner and its side length - * - * \param min_corner The lowest corner - * \param side_length The cube's side length - **/ - FBox(const position_t& min_corner, Real side_length) : - _c1(min_corner), - _c2(min_corner) - { - if(side_length < 0) { - side_length = - side_length; - } - - for(auto&& d : _c2) { - d += side_length; - } - - _center = (_c1 + _c2) / 2; - } - - /** Builds a box from two corners - * - * The maximum and minimum corners are deduced from the given corners. - * - * \param corner_1 The first corner. - * \param corner_2 The second corner. - */ - FBox(const position_t& corner_1, const position_t& corner_2) : _c1(corner_1), _c2(corner_2) { - rearrange_corners(); - } - - /** Changes the box corners - * - * The maximum and minimum corners are deduced from the given corners. - * - * \param corner_1 The first corner. - * \param corner_2 The second corner. - */ - void set(const position_t& corner_1, const position_t& corner_2) { - _c1 = corner_1; - _c2 = corner_2; - - rearrange_corners(); - } - - /** Checks whether a position is within the box bounds - * - * \param p The position to check. - */ - bool contains(const position_t& p) const { - for(std::size_t i = 0; i < Dim; i++) { - if(p[i] < _c1[i] || p[i] > _c2[i]) { - return false; - } - } - return true; - } - - /** Checks whether an object's position is within the box bounds - * - * The object must implement a `position_t position() const;` method. - * - * \tparam T The object type. - * \param obj The object which position to check. - */ - template - bool contains(const T& obj) const { - return contains(obj.position()); - } - - - /** Accessor for the box center */ - const position_t& center() const { - return _center; - } - - /** Accessor for the box corners - * - * The corners are numbered using a space filling curve. - * - * \param idx The corner index. - * \return The idx'th corner. - */ - position_t corner(std::size_t idx) const { - position_t c; - std::size_t i = 0; - for(bool choice : space_filling_curve_t::position(idx)) { - c[i] = choice ? _c2[i] : _c1[i]; - ++i; - } - return c; - } - - /** Setter for the corners - * - * Moves a corner to a new position and modifies the relevant other - * ones. The corners are numbered using a space filling curve. - * - * \param idx The moved corner index. - * \param pos The new corner position. - */ - void corner(std::size_t idx, const position_t& pos) { - std::size_t i = 0; - for(bool choice : space_filling_curve_t::position(idx)) { - if(choice) { - _c2[i] = pos[i]; - } else { - _c1[i] = pos[i]; - } - ++i; - } - rearrange_corners(); - } - - /** Sums the corners of two boxes */ - FBox operator+(const FBox& other) const { - return FBox(_c1 + other._c1, _c2 + other._c2); - } - - /** Tests two boxes equality */ - bool operator==(const FBox& other) const { - return c1 == other.c1 && c2 == other.c2; - } - /** Tests two boxes inequality */ - bool operator!=(const FBox& other) const { - return ! this->operator==(other); - } - - friend std::ostream& operator<<(std::ostream& os, const FBox& box) { - return os << "[" << box.c1 << "," << box.c2 << "]"; - } -}; - -#endif diff --git a/Src/Adaptive/new/FInOrderNodeIterator.hpp b/Src/Adaptive/new/FInOrderNodeIterator.hpp deleted file mode 100644 index 2d3614296d93a05a42a870b89f15472ea5163535..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FInOrderNodeIterator.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef _SCALFMM_IN_ORDER_NODE_ITERATOR_HPP_ -#define _SCALFMM_IN_ORDER_NODE_ITERATOR_HPP_ - -#include "FNodeIterator.hpp" - -namespace scalfmm { - namespace tests { - struct test_InOrderNodeIterator; - } -} - -template -class FInOrderNodeIterator : public FNodeIterator, Node> { - - using base_t = FNodeIterator, Node>; - using Direction = typename base_t::Direction; - - friend scalfmm::tests::test_InOrderNodeIterator; - friend base_t; - -public: - - using base_t::base_t; - using base_t::operator++; - using base_t::operator--; - - FInOrderNodeIterator& operator++() { - return move_iterator(); - } - - FInOrderNodeIterator& operator--() { - return move_iterator(); - } - - -private: - - /** Indicates the index of the middle child */ - template - typename base_t::index_t mid_idx() const { - if(dir == Direction::forwards) { // Compile time optimisation will remove unused branch - return (base_t::child_count/2)-1; - } else { - return (base_t::child_count/2); - } - } - - /** Moves the cursor to the first node - * - * Resets the iterator to a valid state. - */ - template - FInOrderNodeIterator& move_to_boundary() { - - base_t::template goto_root(); - - while(! this->_cur->is_leaf()) { - base_t::template move_down(); - } - return *this; - } - - template - FInOrderNodeIterator& leaf_next() { - // Leave current leaf - if(!this->_cur_state.empty()) { - base_t::move_up(); - } - // If we visited half the parent's children, stay on the parent - if (!this->_cur_state.empty() && mid_idx() == this->_cur_state.back()) { - return *this; - } - // If we visited all the children of the node, we move up - while(!this->_cur_state.empty() && base_t::template at_last_child()) { - base_t::move_up(); - } - // Moving too far up means we got to the end of the tree - if(this->_cur_state.empty()) { - base_t::template set_end(); - return *this; - } - // Once we moved up enough, we move down to the next leaf - while(! this->_cur->is_leaf()) { - base_t::template move_down(); - } - - return *this; - } - - template - FInOrderNodeIterator& node_next() { - // If we are on an internal node, we move down to the children - if(dir == Direction::forwards) { // Compile time optimisation will remove unused branch - this->_cur_state.back() = static_cast(mid_idx()+1); - } else { - this->_cur_state.back() = static_cast(mid_idx()-1); - } - this->_cur = this->_cur->getChild((std::size_t)this->_cur_state.back()); - this->_cur_state.push_back(base_t::template first_idx()); - - while(! this->_cur->is_leaf()) { - base_t::template move_down(); - } - return *this; - } - - - template - FInOrderNodeIterator& move_iterator() { - // If before the beginning, move to the first node - if(base_t::template is_other_end()) { - return move_to_boundary(); - } - // Don't move if already past the end - if(base_t::template is_end()) { - return *this; - } - if(this->_cur->is_leaf()) { - return leaf_next(); - } else { - return node_next(); - } - } -}; - -#endif diff --git a/Src/Adaptive/new/FNode.hpp b/Src/Adaptive/new/FNode.hpp deleted file mode 100644 index 0d4673da2d848a373f28223898dc5d5d6f2f068a..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FNode.hpp +++ /dev/null @@ -1,622 +0,0 @@ -#ifndef SCALFMM_NODE_HPP_ -#define SCALFMM_NODE_HPP_ - -#include -#include -#include -#include -#include -#include -#include - -#include "FBox.hpp" -#include "Utils/FPoint.hpp" -#include "Utils/FConstFuncs.hpp" - -namespace scalfmm { - namespace tests { - struct test_Node; - struct test_NodeIterator; - struct test_InOrderNodeIterator; - struct test_PreOrderNodeIterator; - struct test_PostOrderNodeIterator; - } -} - -struct NodeEmptyData {}; - -/** \brief Tree node implementation - * - */ -template -class FNode { -public: - /// Tree type this class belongs to - using tree_t = _Tree; - /// Type used to represent real numbers - using Real = typename tree_t::Real; - /// Space dimension count - constexpr static const std::size_t Dim = _Tree::Dim; - /// Child count if the node is not a leaf - constexpr static std::size_t child_count = Fpow(2,Dim); - - /// Node position type - using position_t = FPoint; - /// Node bounding box type - using box_t = FBox; - /// Interaction lists type - using interaction_list_t = std::unordered_set; - /// Children array type - using child_node_array_t = std::array; - /// Particle container type - using particle_container_t = _ParticleContainer; - /// Particle type - using particle_t = typename particle_container_t::value_type; - /// Node data structure - using data_t = NodeData; - - -private: - - friend struct scalfmm::tests::test_Node; - friend struct scalfmm::tests::test_NodeIterator; - friend struct scalfmm::tests::test_InOrderNodeIterator; - friend struct scalfmm::tests::test_PreOrderNodeIterator; - friend struct scalfmm::tests::test_PostOrderNodeIterator; - friend tree_t; - - /// Children array, filled with nullptr is Node is a leaf - child_node_array_t _children{{}}; - /// Node parent, nullptr if the node is a root - FNode* _parent = nullptr; - /// Node spatial bounding box - box_t _box; - /// Node depth in its tree - std::size_t _depth = 0; - /// Node index in parent child array - std::size_t _m_idx = 0; - /// Particle container - std::unique_ptr _p_container{new particle_container_t}; - /// Node data - data_t _data = data_t(); - - /// Tree the Node belongs to - tree_t* _tree; - - /// Indicates whether node is a leaf - bool _is_leaf = true; - -public: - /// Near-field leaves interaction list - interaction_list_t U; - /// Mid-field node interaction list - interaction_list_t V; - /// Near-field node interaction list - interaction_list_t W; - /// Mid-field leaf interaction list - interaction_list_t X; - - /** Constructor called from parent - * - * \param parent The parent node - * \param child_index The index of this node in the parent children array - */ - FNode(FNode& parent, const std::size_t& child_index) : - _parent(&parent), - _box (parent.getBox().center(), parent.getBox().corner(child_index) ), - _depth (parent.getDepth()+1), - _m_idx((parent.getIndex() << Dim) + child_index), - _tree (parent._tree ) - { - if (child_index >= child_count) { - throw std::invalid_argument(std::string("Wrong child index in node contructor: got ") - + std::to_string(child_index) - + std::string(", expected at most ") - + std::to_string(Dim) - + "."); - } - } - - /** Root constructor called from tree */ - FNode(tree_t* tree) : - _box(tree->box()), - _tree(tree) - { - tree->leaves().insert(this); - } - - /** Default constructor */ - FNode() = delete; - - /** Copy constructor */ - FNode(const FNode& other) = delete; - - /** Copy operator */ - FNode& operator=(const FNode& other) = delete; - - /** Move constructor */ - FNode(FNode&& other) = delete; - - /** Move operator */ - FNode& operator=(FNode&& other) = delete; - - /** Destructor */ - ~FNode() { - for(auto&& child : _children) { - delete child; - } - } - - - /// Data accessor - data_t& getData() noexcept { - return _data; - } - /// Data const accessor - const data_t& getData() const noexcept { - return _data; - } - - /// Children container accessor - child_node_array_t& getChildren() noexcept { - return _children; - } - /// Children const container accessor - const child_node_array_t& getChildren() const noexcept { - return _children; - } - - /** Child container accessor - * - * \param index Child index - */ - FNode* getChild(const std::size_t& index) noexcept { - return getChildren()[index]; - } - /** Child container const accessor - * - * \param index Child index - */ - const FNode* getChild(const std::size_t& index) const noexcept { - return getChildren()[index]; - } - - /// Parent accessor - FNode* getParent() noexcept { - return _parent; - } - /// Parent const accessor - const FNode* getParent() const noexcept { - return _parent; - } - - /// Depth accessor - const std::size_t& getDepth() const noexcept { - return _depth; - } - - /// Morton index accessor - const std::size_t& getIndex() const noexcept { - return _m_idx; - } - - /// Tree accessor - tree_t& getTree() noexcept { - return *_tree; - } - /// Tree const accessor - const tree_t& getTree() const noexcept { - return *_tree; - } - - /// Box const accessor - const box_t& getBox() const noexcept { - return _box; - } - - /// Particle container accessor - particle_container_t* getParticleContainer() noexcept { - return _p_container.get(); - } - /// Particle container accessor - const particle_container_t* getParticleContainer() const noexcept { - return _p_container.get(); - } - - /// Particle count for the container - std::size_t getParticleCount() const noexcept { - if(getParticleContainer()) { - return getParticleContainer()->size(); - } - return 0; - } - - /** Returns true if this node and the 'other' node are adjacent - * - * The nodes are assumed to belong to the same tree. - * - * To check whether nodes are adjacent, on each axis, the distance between - * the nodes' center is compared to the sum of their half diameter. For at - * least one of the axes, the two must be equal. For the others, the - * distance must be less than or equal to the sum. This ensures that a node - * is not adjacent to one of its descendants. - * - * \param other The node to test adjacency with. - * - * \return true if this FNode and the 'other' FNode are adjacent. - */ - bool is_adjacent(const FNode& other) const noexcept { - // Sum of the half side lengh of the two nodes boxes. - // Boxes are cubes, we only need one side. - Real centers_distance = getBox().center()[0] - getBox().c1[0] - + other.getBox().center()[0] - other.getBox().c1[0]; - // Used to check that the other box isn't overlapping with this box - bool one_axis_is_at_exact_distance = false; - - position_t my_center = getBox().center(); - position_t other_center = other.getBox().center(); - - for(std::size_t i = 0; i < Dim; ++i) { - Real distance = fabs(my_center[i] - other_center[i]); - if( Ffeq(distance, centers_distance) ) { - one_axis_is_at_exact_distance = true; - } else if(distance > centers_distance) { - return false; - } - } - - return one_axis_is_at_exact_distance; - } - - /** Tests whether this node and the 'other' node are adjacent - * - * \return true if the nodes are adjacent. - */ - bool is_adjacent(const FNode* other) const noexcept { - if(nullptr == other) { - return false; - } else if (this == other){ - return true; - } - - return is_adjacent(*other); - } - - /** Tests whether this node is a leaf - * - * \return true if this node is a leaf. - */ - bool is_leaf() const noexcept { - return _is_leaf; - } - - /** Inserts a particle in the tree rooted at node - * - * Pushes a particle in the node particle container if it is a leaf. If it - * isn't, the particle is forwarded to the relevant child. - * - * \note The `push_back` method of #particle_container_t is used to insert in a leaf - */ - void insert(const particle_t& p) { - if(! is_leaf()) { - std::size_t child_index = box_t::space_filling_curve_t::index(p.position(), getBox().center()); - getChild(child_index)->insert(p); - } else { - getParticleContainer()->push_back(p); - if(getParticleContainer()->size() > getTree().leaf_max_particle_count()) { - split(); - } - } - } - - /** Inserts a particle in the tree rooted at node - * - * Emplaces a particle in the node particle container if it is a leaf. If it - * isn't, the particle is forwarded to the relevant child. - * - * \note The `emplace_back` method of #particle_container_t is used to insert in a leaf - */ - template - void insert(const position_t& position, Args&&... args) { - if(! is_leaf()) { - std::size_t child_index = box_t::space_filling_curve_t::index(position, getBox().center()); - getChild(child_index)->insert(position, std::forward(args)...); - } else { - getParticleContainer()->emplace_back(position, std::forward(args)...); - } - } - - - /** Extracts a particle from a leaf - * - * If the nodes is not a leaf, does nothing. - */ - particle_t extract(const std::size_t& idx) { - particle_t p = *(getParticleContainer()->begin() + idx); - if(getParticleContainer()) { - getParticleContainer()->erase(getParticleContainer()->begin() + idx); - } - return p; - } - - /** Splits or fuses nodes after tree modifications - * - * Iterates over all the sub-tree particles and splits the leafs that - * hold too many particles or fuses those that hold too few. - * - * This may be necessary when the tree parameters have been changed - * (leaf max particle count modified) or when particles have moved and - * been reinserted in the tree to be in the right boxes. - */ - void reshape() { - if(is_leaf()) { - if(getParticleCount() > getTree().leaf_max_particle_count()) { - split(); - } - } else { - std::size_t p_count = 0; - for(auto child : getChildren()) { - child->reshape(); - p_count += child->getParticleCount(); - } - - if(p_count <= getTree().leaf_max_particle_count()) { - fuse(); - } - } - } - - /** Applies a function to the node and it descendants in order */ - void for_each_in_order(std::function lambda) { - std::size_t idx = 0; - if(! is_leaf()) { - for(; idx < getChildren().size()/2; ++idx) { - getChildren()[idx]->for_each_in_order(lambda); - } - } - lambda(this); - if(! is_leaf()) { - for(; idx < getChildren().size(); ++idx) { - getChildren()[idx]->for_each_in_order(lambda); - } - } - } - - /** Applies a function to the node and it descendants post order (children first) */ - void for_each_post_order(std::function lambda) { - if(! is_leaf()) { - for(std::size_t idx = 0; idx < getChildren().size(); ++idx) { - getChildren()[idx]->for_each_post_order(lambda); - } - } - lambda(this); - } - - /** Applies a function to the node and it descendants pre order (parent first) */ - void for_each_pre_order(std::function lambda) { - lambda(this); - if(! is_leaf()) { - for(std::size_t idx = 0; idx < getChildren().size(); ++idx) { - getChildren()[idx]->for_each_pre_order(lambda); - } - } - } - - /** Equality test operator */ - bool operator==(const FNode& other) const { - return other.getParent() == getParent() - && other.getDepth() == getDepth() - && other.getIndex() == getIndex(); - } - -private: - /** Tree setter */ - void setTree(tree_t* t) { - _tree = t; - if(! is_leaf()) { - for(FNode*& child : getChildren()) { - child->setTree(t); - } - } - } - - - /** Creates or allocates the particle container */ - void create_particle_container() { - _p_container.reset(new particle_container_t); - } - - /** Deletes the particle container to save space when it is not needed */ - void delete_particle_container() { - _p_container.reset(nullptr); - } - - /** Allocates this node's children */ - void create_children() { - std::size_t idx = 0; - - getTree().leaves().erase(this); - for(FNode*& child : getChildren()) { - child = new FNode(*this, idx); - getTree().leaves().insert(child); - ++idx; - } - _is_leaf = false; - } - - /* Deletes this node's children */ - void delete_children() { - for(FNode*& child : getChildren()) { - getTree().leaves().erase(child); - delete child; - child = nullptr; - } - getTree().leaves().insert(this); - _is_leaf = true; - } - - /** Adds children to a leaf node - * - * Adds children to a leaf node and redistributes its particles among - * the newly created leaves. - */ - void split() { - if(getDepth()+1 > getTree().max_height()) { - // TODO: log that there were too many particles - return; - } - - create_children(); - - // Update interaction lists - this->U.erase(this); - for(FNode* child : getChildren()) { - // Children are adjacent to each other - child->U.insert(getChildren().begin(), getChildren().end()); - // Find where to put U list items in child - for(FNode* u_item : this->U) { - if(child->is_adjacent(u_item)) { - // Adjacent to child - child->U.insert(u_item); - u_item->U.insert(child); - } else if(u_item->getDepth() < child->getDepth()) { - // Adjacent to parent (this) but not to child - child->X.insert(u_item); - u_item->W.insert(child); - } else { // u_item->getDepth() >= child->getDepth() - // Find ancestor of u_item that is adjacent to child - while(u_item->getDepth() > child->getDepth()) { - if(child->is_adjacent(u_item->getParent())) { - // Parent is adjacent -> W list - child->W.insert(u_item); - u_item->X.insert(child); - break; - } else { - u_item = u_item->getParent(); - } - } - if(u_item->getDepth() == child->getDepth()) { - // No adjacent ancestor -> add a neighbour - child->V.insert(u_item); - u_item->V.insert(child); - } - } - } - - // Find where to put W list items in child - for(FNode* w_item : this->W) { - // Find first ancestor of w_item that is adjacent to child - // not needed, done in U list treatment, only check parent - if(child->getDepth() < w_item->getDepth()) { - if(child->is_adjacent(w_item->getParent())) { - child->W.insert(w_item); - w_item->X.insert(child); - } - } else if(child->getDepth() == w_item->getDepth()) { - // No adjacent ancestor -> add a neighbour - child->V.insert(w_item); - w_item->V.insert(child); - } - } - } - // Remove this from other lists - for(FNode* w_item : this->W) { - w_item->X.erase(this); - } - for(FNode* u_item : this->U) { - u_item->U.erase(this); - } - // Clear leaf-only lists - this->U.clear(); - this->W.clear(); - - move_particles_to_children(); - } - - void move_particles_to_children() { - for(auto&& p : *getParticleContainer()) { - insert(p); - } - delete_particle_container(); - } - - - /** Fuses the children nodes until this node becomes a leaf */ - void fuse() { - if(is_leaf()) { - return; // In a leaf, there's nothing to do - } - - for(FNode* child : getChildren()) { - child->fuse(); // Fuse children into leaves - } - - create_particle_container(); - _is_leaf = true; - - // Remove children from U lists - for(FNode* child_1 : getChildren()) { - for(FNode* child_2 : getChildren()) { - child_1->U.erase(child_2); - } - } - // Use the children interaction lists to update this one - for(FNode* child : getChildren()) { - // Child U list items get into this U list - for(FNode* u_item : child->U) { - // Remove child from u_item U list - u_item->U.erase(child); - // Add this and u_item in each other's U lists - this->U.insert(u_item); - u_item->U.insert(this); - } - child->U.clear(); - - // Child X list items get into the this U list - for(FNode* x_item : child->X) { - // Remove child from x_item W list - x_item->W.erase(child); - // Add this and x_item in each other's U lists - this->U.insert(x_item); - x_item->U.insert(this); - } - - // Child W items get into this W list - for(FNode* w_item : child->W) { - // Remove child from w_item X list - w_item->X.erase(child); - // Add this and w_item in each other's W and X lists - // when w_item is not adjacent to this - if(! is_adjacent(w_item)) { - this->W.insert(w_item); - w_item->X.insert(this); - } - } - - // Child V list items get into this W list - for(FNode* v_item : child->V) { - // Remove child from the v_item V list - v_item->V.erase(child); - // Add this and v_item in each other's W and X lists - // when v_item is not adjacent to this - if(! is_adjacent(v_item)) { - this->W.insert(v_item); - v_item->X.insert(this); - } - } - - for(auto&& p : *(child->getParticleContainer())) { - insert(p); - } - } - // This belongs to its own U list - this->U.insert(this); - // Clear the children after everything is updated - delete_children(); - - } - -}; - - -#endif diff --git a/Src/Adaptive/new/FNodeIterator.hpp b/Src/Adaptive/new/FNodeIterator.hpp deleted file mode 100644 index d5034e8a849ef35d6b46697f8727e375df8e1e7c..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FNodeIterator.hpp +++ /dev/null @@ -1,258 +0,0 @@ -#ifndef _SCALFMM_NODE_ITERATOR_HPP_ -#define _SCALFMM_NODE_ITERATOR_HPP_ - -#include - -#include "Utils/FConstFuncs.hpp" - -namespace scalfmm { - namespace tests { - struct test_NodeIterator; - } -} - -template -class FNodeIterator { -public: - - friend struct scalfmm::tests::test_NodeIterator; - - using node_t = Node; - - // Iterator types - using value_type = node_t; - using difference_type = std::ptrdiff_t; - using pointer = node_t*; - using reference = node_t&; - using iterator_category = std::bidirectional_iterator_tag; - - constexpr static std::size_t child_count = node_t::child_count; - enum class IteratorPosition {begin, end, reverse_end}; - -protected: - enum class Direction {forwards, backwards}; - using state_container = std::vector; - using index_t = typename state_container::value_type; - - - /// Root node for the graph walk - /** \warning This may not be the first node of the walk. */ - node_t* _root = nullptr; - /// Current node for the graph walk - node_t* _cur = nullptr; - /** Current state in the walk - * Contains the indexes of the next children to visit per level - * in the currently visited tree branch. - */ - state_container _cur_state; - /// Special past_the_end iterator status - bool _is_end = false; - /// Special past_the_reverse_end iterator status - bool _is_rend = false; - -public: - /// Main constructor - /** - * \param root The graph root node before walking accross it. - * - * \warning This constructor must be completed by the derived class. - * It does not set #_cur nor #_cur_state to the right value. */ - FNodeIterator(node_t* root, IteratorPosition p = IteratorPosition::begin) : - _root(root), - _is_end(p == IteratorPosition::end), - _is_rend(p == IteratorPosition::reverse_end) - { - if(!_is_end && ! _is_rend) { - static_cast(this)->template move_to_boundary(); - } - } - - /// Default constructor - /** Such a constructed iterator is not in a valid state. */ - FNodeIterator() = default; - /// Copy constructor - FNodeIterator(const FNodeIterator& other) = default; - /// Copy assignment - FNodeIterator& operator=(const FNodeIterator& other) = default; - /// Move constructor - FNodeIterator(FNodeIterator&& other) = default; - /// Move assignment - FNodeIterator& operator=(FNodeIterator&& other) = default; - - /// Destructor - ~FNodeIterator() = default; - - /// Swap operation - void swap(FNodeIterator&& other) noexcept { - #define _MY_SWAP_(a) {auto tmp = a; a = other.a; other.a = tmp;} - _MY_SWAP_(_root); - _MY_SWAP_(_cur); - _MY_SWAP_(_is_end); - _MY_SWAP_(_is_rend); - _cur_state.swap(other._cur_state); - #undef _MY_SWAP_ - } - - - /// Dereference operator - node_t& operator*() { - return *_cur; - } - /// Dereference const operator - const node_t& operator*() const { - return *_cur; - } - - /// Pointer dereference operator - node_t* operator->() { - return _cur; - } - /// Pointer const dereference operator - const node_t* operator->() const { - return _cur; - } - - /// Prefix increment - //virtual FNodeIterator& operator++() = 0; - - /// Postfix increment - Derived operator++(int) { - Derived it(static_cast(*this)); - ++static_cast(*this); - return it; - } - - /// Prefix decrement - //virtual FNodeIterator& operator--() = 0; - - /// Postfix decrement - Derived operator--(int) { - Derived it(static_cast(*this)); - --static_cast(*this); - return it; - } - - /// Equality operator - friend bool operator==(const FNodeIterator& lhs, const FNodeIterator& rhs) { - #define _TEST_EQ(name) (lhs.name == rhs.name) - return - _TEST_EQ(_root) && - _TEST_EQ(_cur) && - _TEST_EQ(_is_end) && - _TEST_EQ(_is_rend); - #undef _TEST_EQ - } - - /// Inequality operator - friend bool operator!=(const FNodeIterator& lhs, const FNodeIterator& rhs) { - return ! (lhs == rhs); - } - - friend Derived operator+=(Derived lhs, difference_type n) { - if(n < 0) { - for(; n != 0; ++n, --lhs); - } - if(n > 0) { - for(; n != 0; --n, ++lhs); - } - return lhs; - } - - friend Derived operator-=(const Derived& lhs, difference_type n) { - return operator+=(lhs, -n); - } - - friend Derived operator+(const Derived& lhs, difference_type n) { - return lhs += n; - } - - friend Derived operator-(const Derived& lhs, difference_type n) { - return operator+=(lhs, -n); - } - -protected: - - // Methods used in all subclasses - - template - void goto_root() { - this->_is_rend = false; - this->_is_end = false; - this->_cur = this->_root; - this->_cur_state.clear(); - this->_cur_state.push_back(first_idx()); - } - - /** Returns the end flag corresponding to the direction */ - template - bool is_end() { - return dir == Direction::forwards ? this->_is_end : this->_is_rend; - } - - /** Returns the end flag corresponding to the oposite direction */ - template - bool is_other_end() { - return dir == Direction::forwards ? this->_is_rend : this->_is_end; - } - - /** Sets the end flag according to the direction */ - template - void set_end() { - if(dir == Direction::forwards) { - this->_is_end = true; - } else { - this->_is_rend = true; - } - } - - /** Returns the first index to insert in #_cur_state */ - template - index_t first_idx() const { - return dir == Direction::forwards ? -1 : (index_t)Node::child_count; - } - - - /** Indicates whether the last child of a node has been visited */ - template - bool at_last_child() const { - if(dir == Direction::forwards) { // Compile time optimisation will remove unused branch - return Node::child_count-1 == this->_cur_state.back(); - } else { - return 0 == this->_cur_state.back(); - } - } - - /** Moves the cursor to its parent - * - * \warning Undefined behaviour when the cursor points to a leaf. - */ - void move_up() { - this->_cur_state.pop_back(); - this->_cur = this->_cur->getParent(); - } - - /** Moves the cursor to the next child to visit - * - * \warning Undefined behaviour when the cursor points to a leaf. - */ - template - void move_down() { - if(dir == Direction::forwards) { // Compile time optimisation will remove unused branch - ++(this->_cur_state.back()); - } else { - --(this->_cur_state.back()); - } - this->_cur = this->_cur->getChild((std::size_t) this->_cur_state.back()); - this->_cur_state.push_back(first_idx()); - } - - - -}; - -template -void swap(FNodeIterator& it1, FNodeIterator& it2) { - it1.swap(it2); -} - -#endif diff --git a/Src/Adaptive/new/FNodeIteratorBox.hpp b/Src/Adaptive/new/FNodeIteratorBox.hpp deleted file mode 100644 index 82b9f15096494c5dbac368ae61804e71eef86ee2..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FNodeIteratorBox.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _SCALFMM_NODE_ITERATOR_BOX_ -#define _SCALFMM_NODE_ITERATOR_BOX_ - -#include - -template class NodeIterator> -class FNodeIteratorBox { - using node_t = Node; -public: - - using value_type = node_t; - using reference = node_t&; - using const_reference = const node_t&; - using iterator = NodeIterator; - using const_iterator = NodeIterator; - using difference_type = typename iterator::difference_type; - using size_type = std::size_t; - - - node_t* _root = nullptr; - - FNodeIteratorBox(node_t* root) : _root(root) { } - - iterator begin() { - return iterator(_root); - } - - iterator end() { - return iterator(_root, iterator::IteratorPosition::end); - } - - const_iterator begin() const { - return const_iterator(_root); - } - - const_iterator end() const { - return const_iterator(_root, iterator::IteratorPosition::end); - } - - const_iterator cbegin() const { - return this->begin(); - } - - const_iterator cend() const { - return this->cend(); - } - -}; - -#endif diff --git a/Src/Adaptive/new/FPrePostOrderNodeIterator.hpp b/Src/Adaptive/new/FPrePostOrderNodeIterator.hpp deleted file mode 100644 index eea7b009178462372a5b48852ac5bb9b7dd99cc2..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FPrePostOrderNodeIterator.hpp +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef _SCALFMM____ORDER_NODE_ITERATOR_HPP_ -#define _SCALFMM____ORDER_NODE_ITERATOR_HPP_ - -#include "FNodeIterator.hpp" - -namespace scalfmm { - namespace tests { - struct test_PostOrderNodeIterator; - struct test_PreOrderNodeIterator; - } -} - -namespace scalfmm_adaptive_iterator_impl { - - enum class NodeIteratorOrder {preorder, postorder}; - - template - class __OrderNodeIterator : public FNodeIterator<__OrderNodeIterator, Node> { - - friend scalfmm::tests::test_PostOrderNodeIterator; - friend scalfmm::tests::test_PreOrderNodeIterator; - - using base_t = FNodeIterator<__OrderNodeIterator, Node>; - using Direction = typename base_t::Direction; - - public: - - friend base_t; - using base_t::base_t; - using base_t::operator++; - using base_t::operator--; - - __OrderNodeIterator& operator++() { - if(it_type == NodeIteratorOrder::preorder) { - return move_iterator_prefix(); - } else { - return move_iterator_postfix(); - } - } - - __OrderNodeIterator& operator--() { - if(it_type == NodeIteratorOrder::preorder) { - return move_iterator_postfix(); - } else { - return move_iterator_prefix(); - } - } - - - protected: - - - /** Moves the cursor to the first node - * - * Resets the iterator to a valid state. - */ - template - __OrderNodeIterator& move_to_boundary() { - - base_t::template goto_root(); - - if( (it_type == NodeIteratorOrder::preorder - && dir == Direction::backwards) - || (it_type == NodeIteratorOrder::postorder - && dir == Direction::forwards) ) - { - while(! this->_cur->is_leaf()) { - base_t::template move_down(); - } - } - return *this; - } - - - ////////////// POSTORDER TRAVERSAL ///////////////// - template - __OrderNodeIterator& move_iterator_postfix() { - if(base_t::template is_other_end()) { - return move_to_boundary(); - } - if(base_t::template is_end()) { - return *this; - } - return next_postfix(); - } - - template - __OrderNodeIterator& next_postfix() { - // Leave current leaf - if(!this->_cur_state.empty()) { - base_t::move_up(); - } - // If we visited all the children of the node, we move up - if(!this->_cur_state.empty() && base_t::template at_last_child()) { - if(dir == Direction::backwards) { - --(this->_cur_state.back()); - } else { - ++(this->_cur_state.back()); - } - return *this; - } - // Moving too far up means we got to the end of the tree - if(this->_cur_state.empty()) { - base_t::template set_end(); - return *this; - } - // Once we moved up enough, we move down to the next node - while(! this->_cur->is_leaf()) { - base_t::template move_down(); - } - return *this; - } - - ////////////// PREORDER TRAVERSAL ////////////////// - template - __OrderNodeIterator& move_iterator_prefix() { - if(base_t::template is_other_end()) { - return move_to_boundary(); - } - if(base_t::template is_end()) { - return *this; - } - if(this->_cur->is_leaf()) { - return leaf_next_prefix(); - } else { - return node_next_prefix(); - } - } - - template - __OrderNodeIterator& leaf_next_prefix() { - // Leave current leaf - if(!this->_cur_state.empty()) { - base_t::move_up(); - } - // If we visited all the children of the node, we move up - while(!this->_cur_state.empty() && base_t::template at_last_child()) { - base_t::move_up(); - } - // Moving too far up means we got to the end of the tree - if(this->_cur_state.empty()) { - base_t::template set_end(); - return *this; - } - // Once we moved up enough, we move down to the next node - base_t::template move_down(); - return *this; - } - - template - __OrderNodeIterator& node_next_prefix() { - base_t::template move_down(); - return *this; - } - - - //////////////////////////////////////////////////////////// - }; - -} -template -using FPreOrderNodeIterator = scalfmm_adaptive_iterator_impl:: - __OrderNodeIterator; -template -using FPostOrderNodeIterator = scalfmm_adaptive_iterator_impl:: - __OrderNodeIterator; - - -#endif diff --git a/Src/Adaptive/new/FTree.hpp b/Src/Adaptive/new/FTree.hpp deleted file mode 100644 index 82a5e27968cff2be72ea35f623d61c38cfb19b3f..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FTree.hpp +++ /dev/null @@ -1,210 +0,0 @@ -#ifndef SCALFMM_TREE_HPP_ -#define SCALFMM_TREE_HPP_ - -#include - -#include "FBox.hpp" -#include "FNode.hpp" -#include "FNodeIteratorBox.hpp" -#include "FInOrderNodeIterator.hpp" -#include "FPrePostOrderNodeIterator.hpp" - -/** \brief Adaptive FMM tree - * - * \author Quentin Khan - * - * Implements the adaptive tree to be used with an adaptive FMM algorithm. - * - * \tparam _ParticleContainer The class use to store particles. Expected to - * expose a value_type type definition that exposes the particle type. - * \tparam _NodeData The cell data class that is used by the FMM kernel. - */ -template< - class _ParticleContainer, - class _NodeData > -class FTree { -public: - /// Internal node structure - using node_t = FNode ; - /// Particle container type - using particle_container_t = typename _ParticleContainer::value_type; - /// Particle type - using particle_t = typename _ParticleContainer::value_type; - /// Floating point numbers type - using Real = typename particle_t::Real; - /// Space dimension count - constexpr static std::size_t Dim = particle_t::Dim; - /// Particle position type - using position_t = typename particle_t::position_t; - /// Box type use to slice space - using box_t = FBox; - /// List type to store leaves - using leaf_list_t = std::unordered_set; - /// In order tree traversal mock container type - using in_order_walk_t = FNodeIteratorBox; - /// Pre-order tree traversal mock container type - using pre_order_walk_t = FNodeIteratorBox; - /// Post-order tree traversal mock container type - using post_order_walk_t = FNodeIteratorBox; - -private: - /// Tree maximum heigh - std::size_t _max_height = 50; - /// Maximum particle per leaf density - std::size_t _leaf_max_particle_count = 50; - /// Tree space bounding box - box_t _box; - /// Tree root node - node_t* _root = nullptr; - /// Tree leaf list - leaf_list_t _leaves; - - -public: - /** \brief Swaps two trees */ - void swap(FTree& tree) { - using std::swap; - swap(_max_height, tree._max_height); - swap(_box, tree._box); - swap(_root, tree._root); - swap(_leaves, tree._leaves); - swap(_leaf_max_particle_count, tree._leaf_max_particle_count); - - if(tree.root() && root()) { - tree.root()->setTree(&(root()->getTree())); - } - if(root()) { - root()->setTree(this); - } - } - - /** \brief Builds a tree - * - * \param box Tree bounding box - * - */ - FTree(box_t box_) : _box(box_) { - _root = new node_t(this); - } - - FTree(FTree&) = delete; - - /** \brief Move constructor */ - FTree(FTree&& tree) { - swap(tree); - } - - FTree& operator=(FTree&) = delete; - - /** \brief Move assignment */ - FTree& operator=(FTree&& tree) { - swap(tree); - } - - /** \brief Destructor */ - ~FTree() { - delete _root; - } - - /** \brief Maximum height accessor - * \return Tree maximum height - */ - std::size_t max_height() const { - return _max_height; - } - - /** \brief Maximum height setter - * \param height New maximum height - */ - void max_height(const std::size_t& height) { - _max_height = height; - } - - /** \brief Maximum leaf particle density accessor - * \return Tree maximum leaf particle density - */ - std::size_t leaf_max_particle_count() const { - return _leaf_max_particle_count; - } - /** \brief Maximum leaf particle density accessor - * \param count New maximum density - */ - void leaf_max_particle_count(std::size_t count) { - _leaf_max_particle_count = count; - } - - /** \brief Tree root accessor - * \return Root pointer - */ - node_t* root() { - return _root; - } - - /** \brief Tree root const accessor - * \return Root pointer - */ - const node_t* root() const { - return _root; - } - - /** \brief Bounding box accessor - * \return Tree bounding box - */ - const box_t& box() const { - return _box; - } - - /** \brief Leaf list accessor - * \return Tree leaf list - */ - leaf_list_t& leaves() { - return _leaves; - } - - /** \brief Leaf list const accessor - * \return Tree leaf list - */ - const leaf_list_t& leaves() const { - return _leaves; - } - - /** \brief In order walk accessor */ - in_order_walk_t in_order_walk() { - return in_order_walk_t(root()); - } - - /** \brief Pre-order walk accessor */ - pre_order_walk_t pre_order_walk() { - return pre_order_walk_t(root()); - } - - /** \brief Post-order walk accessor */ - post_order_walk_t post_order_walk() { - return post_order_walk_t(root()); - } - - /** \brief Proxy call for FNode#insert applied to #root*/ - void insert(const particle_t& p) { - root()->insert(p); - } - - - /** \brief Proxy call for FNode#extract appliced to #root*/ - void extract(const particle_t& p) { - root()->extract(p); - } - - /** \brief Updates the underlying graph after moving some particles - * - * After an FMM run, particles may have moved out of their leaf's bounding - * box. This extracts the particles from the leaf and inserts them again at - * the right place. - * - */ - void reshape() { - root()->reshape(); - } - -}; - -#endif diff --git a/Src/Adaptive/new/FZCurve.hpp b/Src/Adaptive/new/FZCurve.hpp deleted file mode 100644 index 06ab7e89bf59e81709805d4b77340b21ffb467ac..0000000000000000000000000000000000000000 --- a/Src/Adaptive/new/FZCurve.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef SCALFMM_SPACE_CURVE_HPP_ -#define SCALFMM_SPACE_CURVE_HPP_ - -#include "Utils/FPoint.hpp" - -/** Provides the corner traversal order of an N dimension hypercube - * - * The positions returned are array of booleans. Each boolean tells where - * to place the element in the binary grid. - * - * For instance, in 2D: - * - * - * __0__ __1__ - * | | | - * 0| | X | pos(X) = [true, false] - * |_____|_____| - * | | | - * 1| | Y | pos(Y) = [true, true ] - * |_____|_____| - * - * - * \tparam Dim The hypercube dimension. - */ -template -class FZCurve { -public: - /// Space dimension count - constexpr static const std::size_t Dim = _Dim; - /// Position type used - using position_t = FPoint; - /// Position count in the grid - constexpr static std::size_t pos_count = Fpow(2,Dim); - -private: - /// Array of positions type - using position_array_t = std::array; - /// Array to cache the positions corresponding to indexes - static const position_array_t _positions; - - /** Creates an array of positions to initialize #_positions */ - static position_array_t create_array() noexcept { - position_array_t positions; - for(std::size_t i = 0; i < pos_count; ++i) { - for(std::size_t j = Dim-1, k = i; k != 0; --j, k >>=1) { - positions[i][j] = k % 2; - } - } - return positions; - } - -public: - /** The position corresponding to an index - * - * \param idx The index of the point in the space filling curve - * \return The position corresponding to the space filling curve index - */ - static position_t position(std::size_t idx) noexcept { - return _positions[idx]; - } - - /** Index in the space filling curve of a boolean position - * - * \param p The position - * \return The space filling curve index corresponding to the position - */ - static std::size_t index(const position_t& p) noexcept { - std::size_t idx = 0; - for(auto i : p) { - idx <<= 1; - idx += i; - } - return idx; - } - - /** Index in the space filling curve of a real position relative to the center of the hypercube - * - * \param p The position - * \param center The center of the hypercube - * \return The space filling curve index corresponding to the position - */ - template - static std::size_t index(const FPoint& p, const FPoint& center) noexcept { - std::size_t idx = 0; - for(std::size_t i = 0; i < Dim; ++i) { - idx <<= 1; - idx += p[i] > center[i]; - } - return idx; - } - -}; - -// Initialization of static variable -template -const typename FZCurve<_Dim>::position_array_t FZCurve<_Dim>::_positions(FZCurve<_Dim>::create_array()); - -#endif diff --git a/Src/BalanceTree/FChebSymCostKernel.hpp b/Src/BalanceTree/FChebSymCostKernel.hpp index 18d3b6622e7433deba52304550b1d598bb7c1a07..e6d930d650406befa5b87b35f371e01c4b364371 100644 --- a/Src/BalanceTree/FChebSymCostKernel.hpp +++ b/Src/BalanceTree/FChebSymCostKernel.hpp @@ -316,7 +316,7 @@ public: flopsP2P += tmpCost; CellClass* cell = _tree->getCell( - LeafCellCoordinate.getMortonIndex(_treeHeight - 1), + LeafCellCoordinate.getMortonIndex(), _treeHeight - 1); cell->addNearCost(tmpCost); @@ -344,7 +344,7 @@ public: flopsP2P += tmpCost; CellClass* cell = _tree->getCell( - LeafCellCoordinate.getMortonIndex(_treeHeight - 1), + LeafCellCoordinate.getMortonIndex(), _treeHeight - 1); cell->addNearCost(tmpCost); diff --git a/Src/BalanceTree/FDumbCostKernel.hpp b/Src/BalanceTree/FDumbCostKernel.hpp index 5a0231e14593b38ea11b2201e8961943c29b36b9..b38f54e002ba6044b49e242ff25d468203390204 100644 --- a/Src/BalanceTree/FDumbCostKernel.hpp +++ b/Src/BalanceTree/FDumbCostKernel.hpp @@ -194,7 +194,7 @@ public: CellClass* cell = _tree->getCell( - LeafCellCoordinate.getMortonIndex(_treeHeight - 1), + LeafCellCoordinate.getMortonIndex(), _treeHeight - 1); flopsP2P += tmpCost; @@ -210,7 +210,7 @@ public: FSize tmpCost = 0; CellClass* cell = _tree->getCell( - LeafCellCoordinate.getMortonIndex(_treeHeight - 1), + LeafCellCoordinate.getMortonIndex(), _treeHeight - 1); flopsP2P += tmpCost; diff --git a/Src/Containers/FNeighborIndexes.hpp b/Src/Containers/FNeighborIndexes.hpp index 60dc570de2b9bcbac7f27a2744f887fd63cd9b18..d55945ccd70e1e634f8e2eb19c44bc884c70791a 100644 --- a/Src/Containers/FNeighborIndexes.hpp +++ b/Src/Containers/FNeighborIndexes.hpp @@ -53,7 +53,7 @@ class FCoordinateNeighborIndex : public FAbstractNeighborIndex{ public: FCoordinateNeighborIndex(const MortonIndex inMindex, const int inLevel) - : mindex(inMindex), level(inLevel), coord(mindex, level) { + : mindex(inMindex), level(inLevel), coord(mindex) { currentMinX = (coord.getX()==0? 0 : -1); currentMinY = (coord.getY()==0? 0 : -1); @@ -87,7 +87,7 @@ public: } MortonIndex getIndex(const int inX, const int inY, const int inZ) override{ - return FTreeCoordinate(inX+coord.getX(), inY+coord.getY(), inZ+coord.getZ()).getMortonIndex(level); + return FTreeCoordinate(inX+coord.getX(), inY+coord.getY(), inZ+coord.getZ()).getMortonIndex(); } }; @@ -233,4 +233,3 @@ public: }; #endif // FNEIGHBORINDEXES_HPP - diff --git a/Src/Containers/FOctree.hpp b/Src/Containers/FOctree.hpp index e008b0cad8087d64d8f5453139260ef4e6593cfb..7bc5cf6c6b9b81553bdd1090d2206c33b3e24f90 100644 --- a/Src/Containers/FOctree.hpp +++ b/Src/Containers/FOctree.hpp @@ -187,7 +187,7 @@ public: template void insert(const FPoint& inParticlePosition, Args... args){ const FTreeCoordinate host = getCoordinateFromPosition( inParticlePosition ); - const MortonIndex particleIndex = host.getMortonIndex(leafIndex); + const MortonIndex particleIndex = host.getMortonIndex(); if(root->isLeafPart()){ ((SubOctreeWithLeaves*)root)->insert( particleIndex, host, this->height, inParticlePosition, args... ); } @@ -200,7 +200,7 @@ public: * @param indexToRemove the index of the leaf to remove */ LeafClass* createLeaf(const MortonIndex indexToCreate ){ - const FTreeCoordinate host(indexToCreate,this->height-1); + const FTreeCoordinate host(indexToCreate); if(root->isLeafPart()){ return ((SubOctreeWithLeaves*)root)->createLeaf( indexToCreate, host, this->height ); } @@ -222,7 +222,7 @@ public: * @return the morton index */ MortonIndex getMortonFromPosition(const FPoint& position) const { - return getCoordinateFromPosition(position).getMortonIndex(leafIndex); + return getCoordinateFromPosition(position).getMortonIndex(); } /* @@ -803,7 +803,7 @@ public: // if we are not on the current cell if( !(!idxX && !idxY && !idxZ) ){ const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // if not a brother if( mortonOther>>3 != inIndex>>3 ){ // get cell @@ -888,7 +888,7 @@ public: // if we are not on the current cell if( neighSeparation<1 || idxX || idxY || idxZ ){ const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOtherParent = otherParent.getMortonIndex(inLevel-1) << 3; + const MortonIndex mortonOtherParent = otherParent.getMortonIndex() << 3; // Get child CellClass** const cells = getCellPt(mortonOtherParent, inLevel); @@ -950,7 +950,7 @@ public: // if we are not on the current cell if( neighSeparation<1 || idxX || idxY || idxZ ){ const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOtherParent = otherParent.getMortonIndex(inLevel-1) << 3; + const MortonIndex mortonOtherParent = otherParent.getMortonIndex() << 3; // Get child CellClass** const cells = getCellPt(mortonOtherParent, inLevel); @@ -1016,7 +1016,7 @@ public: if(!FMath::Between(parentCell.getZ() + idxZ,0,boxLimite)) continue; const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOtherParent = otherParent.getMortonIndex(inLevel-1) << 3; + const MortonIndex mortonOtherParent = otherParent.getMortonIndex() << 3; // Get child CellClass** const cells = getCellPt(mortonOtherParent, inLevel); @@ -1076,7 +1076,7 @@ public: if(!FMath::Between(parentCell.getZ() + idxZ,0,boxLimite)) continue; const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOtherParent = otherParent.getMortonIndex(inLevel-1) << 3; + const MortonIndex mortonOtherParent = otherParent.getMortonIndex() << 3; // Get child CellClass** const cells = getCellPt(mortonOtherParent, inLevel); @@ -1173,7 +1173,7 @@ public: } - const MortonIndex mortonOtherParent = otherParentInBox.getMortonIndex(inLevel-1) << 3; + const MortonIndex mortonOtherParent = otherParentInBox.getMortonIndex() << 3; // Get child CellClass** const cells = getCellPt(mortonOtherParent, inLevel); @@ -1270,7 +1270,7 @@ public: } - const MortonIndex mortonOtherParent = otherParentInBox.getMortonIndex(inLevel-1) << 3; + const MortonIndex mortonOtherParent = otherParentInBox.getMortonIndex() << 3; // Get child CellClass** const cells = getCellPt(mortonOtherParent, inLevel); @@ -1353,7 +1353,7 @@ public: // if we are not on the current cell if( idxX || idxY || idxZ ){ const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // get cell ContainerClass* const leaf = getLeafSrc(mortonOther); // add to list if not null @@ -1393,7 +1393,7 @@ public: // if we are not on the current cell if( idxX || idxY || idxZ ){ const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // get cell ContainerClass* const leaf = getLeafSrc(mortonOther); // add to list if not null @@ -1436,7 +1436,7 @@ public: // if we are not on the current cell if( idxX || idxY || idxZ ){ const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // get cell CellClass** const leaf = getCellPt(mortonOther, inLevel); @@ -1477,7 +1477,7 @@ public: // if we are not on the current cell if( idxX || idxY || idxZ ){ const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // get cell CellClass** const leaf = getCellPt(mortonOther, inLevel); @@ -1567,7 +1567,7 @@ public: } other.setZ(otherZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // get cell ContainerClass* const leaf = getLeafSrc(mortonOther); // add to list if not null @@ -1656,7 +1656,7 @@ public: } other.setZ(otherZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); + const MortonIndex mortonOther = other.getMortonIndex(); // get cell ContainerClass* const leaf = getLeafSrc(mortonOther); // add to list if not null @@ -1746,4 +1746,3 @@ public: }; #endif //FOCTREE_HPP - diff --git a/Src/Containers/FTreeCoordinate.hpp b/Src/Containers/FTreeCoordinate.hpp index 40d805d27e0a6d22398f7f9bc77305c58c849e96..6b919e6ad7bfe8a6fbeeb4401058154c08d45001 100644 --- a/Src/Containers/FTreeCoordinate.hpp +++ b/Src/Containers/FTreeCoordinate.hpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #ifndef FTREECOORDINATE_HPP @@ -19,6 +19,7 @@ #include #include "../Utils/FGlobal.hpp" +#include "../Utils/FPoint.hpp" #include "../Utils/FMath.hpp" #include "../Components/FAbstractSerializable.hpp" @@ -33,130 +34,62 @@ * It is directly related to morton index, as interleaves * bits from this coordinate make the morton index */ -class FTreeCoordinate : public FAbstractSerializable { +class FTreeCoordinate : public FAbstractSerializable, public FPoint { private: - int data[3]; //< all box-th position + using point_t = FPoint; + enum {Dim = point_t::Dim}; -public: +public: /** Default constructor (position = {0,0,0})*/ - FTreeCoordinate() { - data[0] = data[1] = data[2] = 0; - } + FTreeCoordinate(): point_t() {} - /** Default constructor (position = {0,0,0})*/ - explicit FTreeCoordinate(const MortonIndex mindex, const int indexLevel) { - setPositionFromMorton(mindex, indexLevel); + /** Constructor from Morton index */ + [[gnu::deprecated]] + explicit FTreeCoordinate(const MortonIndex mindex, const int) { + setPositionFromMorton(mindex); } - /** - * Default constructor - * @param inX the x - * @param inY the y - * @param inZ the z - */ - explicit FTreeCoordinate(const int inX,const int inY,const int inZ) { - data[0] = inX; - data[1] = inY; - data[2] = inZ; + explicit FTreeCoordinate(const MortonIndex mindex) { + setPositionFromMorton(mindex); } - explicit FTreeCoordinate(const int inPosition[3]) { - data[0] = inPosition[0]; - data[1] = inPosition[1]; - data[2] = inPosition[2]; - } + /** Constructor from args + * @param inX the x + * @param inY the y + * @param inZ the z + */ + explicit FTreeCoordinate(const int inX,const int inY,const int inZ) + : point_t(inX, inY, inZ) + {} + + explicit FTreeCoordinate(const int inPosition[3]) + : point_t(inPosition) + {} /** * Copy constructor - * @param other the source class to copy */ - FTreeCoordinate(const FTreeCoordinate& other) { - data[0] = other.data[0]; - data[1] = other.data[1]; - data[2] = other.data[2]; - } + FTreeCoordinate(const FTreeCoordinate&) = default; - /** - * Copy constructor - * @param other the source class to copy - */ - FTreeCoordinate(const FTreeCoordinate& other, const int inOffset) { - data[0] = other.data[0] + inOffset; - data[1] = other.data[1] + inOffset; - data[2] = other.data[2] + inOffset; - } + /** Copy and increment constructor + * @param other the source class to copy + */ + FTreeCoordinate(const FTreeCoordinate& other, const int inOffset) + : point_t(other, inOffset) + {} /** - * Copy constructor + * Copy assignment * @param other the source class to copy * @return this a reference to the current object */ - FTreeCoordinate& operator=(const FTreeCoordinate& other){ - data[0] = other.data[0]; - data[1] = other.data[1]; - data[2] = other.data[2]; - return *this; - } - - /** - * Position setter - * @param inX the new x - * @param inY the new y - * @param inZ the new z - */ - void setPosition(const int inX,const int inY,const int inZ){ - data[0] = inX; - data[1] = inY; - data[2] = inZ; - } - - /** - * X Getter - * @return data[0] - */ - int getX() const{ - return data[0]; - } - - /** - * Y Getter - * @return data[1] - */ - int getY() const{ - return data[1]; - } + FTreeCoordinate& operator=(const FTreeCoordinate& other) = default; - /** - * Z Getter - * @return data[2] - */ - int getZ() const{ - return data[2]; + [[gnu::deprecated]] + MortonIndex getMortonIndex(const int /*inLevel*/) const { + return getMortonIndex(); } - /** - * X Setter, simply change x position - * @param the new x - */ - void setX(const int inX){ - data[0] = inX; - } - - /** - * Y Setter, simply change y position - * @param the new y - */ - void setY(const int inY){ - data[1] = inY; - } - - /** - * Z Setter, simply change z position - * @param the new z - */ - void setZ(const int inZ){ - data[2] = inZ; - } /** * To get the morton index of the current position @@ -164,15 +97,18 @@ public: * @param inLevel the level of the component * @return morton index */ - MortonIndex getMortonIndex(const int inLevel) const{ + MortonIndex getMortonIndex() const{ MortonIndex index = 0x0LL; MortonIndex mask = 0x1LL; - // the ordre is xyz.xyz... - MortonIndex mx = data[0] << 2; - MortonIndex my = data[1] << 1; - MortonIndex mz = data[2]; - - for(int indexLevel = 0; indexLevel < inLevel ; ++indexLevel){ + // the order is xyz.xyz... + MortonIndex mx = point_t::data()[0] << 2; + MortonIndex my = point_t::data()[1] << 1; + MortonIndex mz = point_t::data()[2]; + + while( (mask <= mz) + || ((mask << 1) <= my) + || ((mask << 2) <= mx)) + { index |= (mz & mask); mask <<= 1; index |= (my & mask); @@ -188,79 +124,52 @@ public: return index; } + [[gnu::deprecated]] + void setPositionFromMorton(MortonIndex inIndex, const int /*inLevel*/){ + setPositionFromMorton(inIndex); + } + /** This function set the position of the current object using a morton index - * @param inIndex the morton index to compute position - * @param the level of the morton index - */ - void setPositionFromMorton(MortonIndex inIndex, const int inLevel){ + * @param inIndex the morton index to compute position + */ + void setPositionFromMorton(MortonIndex inIndex) { MortonIndex mask = 0x1LL; - data[0] = 0; - data[1] = 0; - data[2] = 0; + point_t::data()[0] = 0; + point_t::data()[1] = 0; + point_t::data()[2] = 0; - for(int indexLevel = 0; indexLevel < inLevel ; ++indexLevel){ - data[2] |= int(inIndex & mask); + while(inIndex >= mask) { + point_t::data()[2] |= int(inIndex & mask); inIndex >>= 1; - data[1] |= int(inIndex & mask); + point_t::data()[1] |= int(inIndex & mask); inIndex >>= 1; - data[0] |= int(inIndex & mask); + point_t::data()[0] |= int(inIndex & mask); mask <<= 1; } - } - /** Test equal operator - * @param other the coordinate to compare - * @return true if other & current object have same position - */ - bool operator==(const FTreeCoordinate& other) const { - return data[0] == other.data[0] && data[1] == other.data[1] && data[2] == other.data[2]; - } /** Test equal operator * @param other the coordinate to compare * @return true if other & current object have same position */ bool equals(const int inX, const int inY, const int inZ) const { - return data[0] == inX && data[1] == inY && data[2] == inZ; + return point_t::data()[0] == inX + && point_t::data()[1] == inY + && point_t::data()[2] == inZ; } - /** To test difference - * - */ - bool operator!=(const FTreeCoordinate& other) const{ - return data[0] != other.data[0] || data[1] != other.data[1] || data[2] != other.data[2]; - } + /** Use base class save */ + using point_t::save; + /** Use base class restore */ + using point_t::restore; - /** - * Operator stream FTreeCoordinate to std::ostream - * This can be used to simply write out a tree coordinate - * @param[in,out] output where to write the coordinate - * @param[in] inCoordinate the coordinate to write out - * @return the output for multiple << operators - */ - template - friend StreamClass& operator<<(StreamClass& output, const FTreeCoordinate& inCoordinate){ - output << "(" << inCoordinate.getX() << ", " << inCoordinate.getY() << ", " << inCoordinate.getZ() <<")"; - return output; // for multiple << operators. - } - - /** Save current object */ - template - void save(BufferWriterClass& buffer) const { - buffer << data[0] << data[1] << data[2]; - } - /** Retrieve current object */ - template - void restore(BufferReaderClass& buffer) { - buffer >> data[0] >> data[1] >> data[2]; - } /** To know the size when we save it */ FSize getSavedSize() const { - return FSize(sizeof(data[0]) + sizeof(data[1]) + sizeof(data[2])); + return FSize(3 * sizeof(point_t::data()[0])); } @@ -281,43 +190,12 @@ public: return str; } - /* @brief Compute the index of the cells in neighborhood of a given cell - * @param OtreeHeight Height of the Octree - * @param indexes target array to store the MortonIndexes computed - * @param indexInArray store - */ - int getNeighborsIndexes(const int OctreeHeight, MortonIndex indexes[26], int indexInArray[26]) const{ - int idxNeig = 0; - int limite = 1 << (OctreeHeight - 1); - // We test all cells around - for(int idxX = -1 ; idxX <= 1 ; ++idxX){ - if(!FMath::Between(this->getX() + idxX,0, limite)) continue; - - for(int idxY = -1 ; idxY <= 1 ; ++idxY){ - if(!FMath::Between(this->getY() + idxY,0, limite)) continue; - - for(int idxZ = -1 ; idxZ <= 1 ; ++idxZ){ - if(!FMath::Between(this->getZ() + idxZ,0, limite)) continue; - - // if we are not on the current cell - if( idxX || idxY || idxZ ){ - const FTreeCoordinate other(this->getX() + idxX, this->getY() + idxY, this->getZ() + idxZ); - indexes[ idxNeig ] = other.getMortonIndex(OctreeHeight - 1); - indexInArray[ idxNeig ] = ((idxX+1)*3 + (idxY+1)) * 3 + (idxZ+1); - ++idxNeig; - } - } - } - } - return idxNeig; - } - - - /* @brief Compute the indexes of the neighborhood of the calling cell - * @param OtreeHeight Height of the Octree - * @param indexes target array to store the MortonIndexes computed - */ - int getNeighborsIndexes(const int OctreeHeight, MortonIndex indexes[26]) const{ + /** @brief Compute the index of the cells in neighborhood of a given cell + * @param OtreeHeight Height of the Octree + * @param indexes target array to store the MortonIndexes computed + * @param indexInArray store (must have the same length as indexes) + */ + int getNeighborsIndexes(const int OctreeHeight, MortonIndex indexes[26], int* indexInArray = nullptr) const { int idxNeig = 0; int limite = 1 << (OctreeHeight - 1); // We test all cells around @@ -333,7 +211,9 @@ public: // if we are not on the current cell if( idxX || idxY || idxZ ){ const FTreeCoordinate other(this->getX() + idxX, this->getY() + idxY, this->getZ() + idxZ); - indexes[ idxNeig ] = other.getMortonIndex(OctreeHeight - 1); + indexes[ idxNeig ] = other.getMortonIndex(); + if(indexInArray) + indexInArray[ idxNeig ] = ((idxX+1)*3 + (idxY+1)) * 3 + (idxZ+1); ++idxNeig; } } @@ -342,8 +222,11 @@ public: return idxNeig; } - int getInteractionNeighbors(const int inLevel, MortonIndex inNeighbors[/*189+26+1*/216], int inNeighborsPosition[/*189+26+1*/216], - const int neighSeparation = 1) const{ + /** + * @param inNeighborsPosition (must have the same length as inNeighbors) + */ + int getInteractionNeighbors(const int inLevel, MortonIndex inNeighbors[/*189+26+1*/216], int* inNeighborsPosition, + const int neighSeparation = 1) const { // Then take each child of the parent's neighbors if not in directNeighbors // Father coordinate const FTreeCoordinate parentCell(this->getX()>>1,this->getY()>>1,this->getZ()>>1); @@ -365,7 +248,7 @@ public: // if we are not on the current cell if(neighSeparation<1 || idxX || idxY || idxZ ){ const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOther = otherParent.getMortonIndex(inLevel-1); + const MortonIndex mortonOther = otherParent.getMortonIndex(); // For each child for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){ @@ -376,7 +259,8 @@ public: // Test if it is a direct neighbor if(FMath::Abs(xdiff) > neighSeparation || FMath::Abs(ydiff) > neighSeparation || FMath::Abs(zdiff) > neighSeparation){ // add to neighbors - inNeighborsPosition[idxNeighbors] = ((( (xdiff+3) * 7) + (ydiff+3))) * 7 + zdiff + 3; + if(inNeighborsPosition) + inNeighborsPosition[idxNeighbors] = ((( (xdiff+3) * 7) + (ydiff+3))) * 7 + zdiff + 3; inNeighbors[idxNeighbors++] = (mortonOther << 3) | idxCousin; } } @@ -389,47 +273,7 @@ public: } int getInteractionNeighbors(const int inLevel, MortonIndex inNeighbors[/*189+26+1*/216], const int neighSeparation = 1) const{ - // Then take each child of the parent's neighbors if not in directNeighbors - // Father coordinate - const FTreeCoordinate parentCell(this->getX()>>1,this->getY()>>1,this->getZ()>>1); - - // Limite at parent level number of box (split by 2 by level) - const int limite = FMath::pow2(inLevel-1); - - int idxNeighbors = 0; - // We test all cells around - for(int idxX = -1 ; idxX <= 1 ; ++idxX){ - if(!FMath::Between(parentCell.getX() + idxX,0,limite)) continue; - - for(int idxY = -1 ; idxY <= 1 ; ++idxY){ - if(!FMath::Between(parentCell.getY() + idxY,0,limite)) continue; - - for(int idxZ = -1 ; idxZ <= 1 ; ++idxZ){ - if(!FMath::Between(parentCell.getZ() + idxZ,0,limite)) continue; - - // if we are not on the current cell - if(neighSeparation<1 || idxX || idxY || idxZ ){ - const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOther = otherParent.getMortonIndex(inLevel-1); - - // For each child - for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){ - const int xdiff = ((otherParent.getX()<<1) | ( (idxCousin>>2) & 1)) - this->getX(); - const int ydiff = ((otherParent.getY()<<1) | ( (idxCousin>>1) & 1)) - this->getY(); - const int zdiff = ((otherParent.getZ()<<1) | (idxCousin&1)) - this->getZ(); - - // Test if it is a direct neighbor - if(FMath::Abs(xdiff) > neighSeparation || FMath::Abs(ydiff) > neighSeparation || FMath::Abs(zdiff) > neighSeparation){ - // add to neighbors - inNeighbors[idxNeighbors++] = (mortonOther << 3) | idxCousin; - } - } - } - } - } - } - - return idxNeighbors; + return getInteractionNeighbors(inLevel, inNeighbors, nullptr, neighSeparation); } }; @@ -437,5 +281,3 @@ public: #endif //FTREECOORDINATE_HPP - - diff --git a/Src/Core/FFmmAlgorithmOmp4.hpp b/Src/Core/FFmmAlgorithmOmp4.hpp index 54d288a0118b3cb9dbd48d0e25a1eb609ebacb40..b8bbd2790c270ed744516640c64006e5f2a3b542 100644 --- a/Src/Core/FFmmAlgorithmOmp4.hpp +++ b/Src/Core/FFmmAlgorithmOmp4.hpp @@ -1,6 +1,8 @@ #ifndef FFMMALGORITHMOMP4_HPP #define FFMMALGORITHMOMP4_HPP +#include + #include "../Utils/FGlobal.hpp" #include "../Utils/FAssert.hpp" #include "../Utils/FLog.hpp" @@ -1007,4 +1009,3 @@ protected: #endif // FFMMALGORITHMOMP4_HPP - diff --git a/Src/Core/FFmmAlgorithmThreadProcPeriodic.hpp b/Src/Core/FFmmAlgorithmThreadProcPeriodic.hpp index a58f12a3a19f5681b69b95dabb89440d4d0beb39..d0bd67719dfcbee0755c2afdff4bf3236884f6a7 100644 --- a/Src/Core/FFmmAlgorithmThreadProcPeriodic.hpp +++ b/Src/Core/FFmmAlgorithmThreadProcPeriodic.hpp @@ -1831,7 +1831,7 @@ protected: otherParentInBox.setZ( otherParentInBox.getZ() - boxLimite ); } - const MortonIndex mortonOtherParent = otherParentInBox.getMortonIndex(inLevel-1); + const MortonIndex mortonOtherParent = otherParentInBox.getMortonIndex(); // For each child for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){ @@ -1871,7 +1871,7 @@ protected: const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ); - const MortonIndex mortonOtherParent = otherParent.getMortonIndex(inLevel-1); + const MortonIndex mortonOtherParent = otherParent.getMortonIndex(); // For each child for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){ diff --git a/Src/Files/FFmaGenericLoader.hpp b/Src/Files/FFmaGenericLoader.hpp index f08e3fc729a43623155c0a4d8eb5c9943799d36c..8f5a8d6fe2e79d646abaa355c6d7f8b191b75fb6 100644 --- a/Src/Files/FFmaGenericLoader.hpp +++ b/Src/Files/FFmaGenericLoader.hpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== // author Berenger Bramas and Olivier Coulaud @@ -36,7 +36,7 @@ /** \brief Particle class used in FMA loader and writer. * * - * The pieces of data are : PosX, PosY, PosZ, physicalValue, + * The pieces of data are : PosX, PosY, PosZ, physicalValue, * Potential, forceX, forceY, forceZ. The first 4 are mandatory. * Data is stored as FReal. * @@ -165,10 +165,10 @@ public: * example below shows how to use the loader to read from a file. * * - * \code - * // Instanciate the loader with the particle file. - * FFmaGenericLoader loader("../Data/unitCubeXYZQ20k.fma"); // extension fma -> ascii format - * // Retrieve the number of particles + * \code + * // Instanciate the loader with the particle file. + * FFmaGenericLoader loader("../Data/unitCubeXYZQ20k.fma"); // extension fma -> ascii format + * // Retrieve the number of particles * FSize nbParticles = loader.getNumberOfParticles(); * * // Create an array of particles, initialize to 0. @@ -190,7 +190,7 @@ public: * \endcode * * `DatatypeSize` can have one of two values: - * - 4, float ; + * - 4, float ; * - 8, double. * * `Number_of_records_per_line` gives the data count for each line of @@ -241,7 +241,7 @@ public: * @param binary true if the file to open is in binary mode */ FFmaGenericLoader(const std::string & filename,const bool binary ): - file(nullptr), binaryFile(binary), centerOfBox(0.0,0.0,0.0), boxWidth(0.0), + file(nullptr), binaryFile(binary), centerOfBox(0.0,0.0,0.0), boxWidth(0.0), nbParticles(0), tmpVal(nullptr), otherDataToRead(0) { this->open_file(filename, binary); @@ -254,7 +254,7 @@ public: * * - The opening mode is guessed from the file extension : `.fma` will open * in ASCII mode, `.bfma` will open in binary mode. - * - All information accessible in the header can be retreived after this call. + * - All information accessible in the header can be retreived after this call. * - To test if the file has successfully been opened, call hasNotFinished(). * * @param filename the name of the file to open. Must end with `.fma` or `.bfma`. @@ -268,7 +268,7 @@ public: binaryFile = false; } else { std::cout << "FFmaGenericLoader: " - << "Only .fma or .bfma input file are allowed. Got " + << "Only .fma or .bfma input file are allowed. Got " << filename << "." << std::endl; std::exit ( EXIT_FAILURE) ; @@ -297,10 +297,9 @@ public: /** * To get the number of particles from this loader - * @param the number of particles the loader can fill */ FSize getNumberOfParticles() const{ - return this->nbParticles; + return this->getParticleCount(); } /** @@ -308,8 +307,25 @@ public: * @return box center */ FPoint getCenterOfBox() const{ + return this->getBoxCenter(); + } + + /** + * \brief Get the distribution particle count + * \return The distribution particle count + */ + FSize getParticleCount() const { + return this->nbParticles; + } + + /** + * \brief Get distribution center + * \return A point representing the box center + */ + FPoint getBoxCenter() const{ return this->centerOfBox; } + /** * The box width from the simulation file opened by the loader * @return box width @@ -502,7 +518,7 @@ private: }; -/**\class FFmaGenericWriter +/** * \warning This class only works in shared memory (doesn't work with MPI). * * \brief Writes a set of particles to an FMA formated file. @@ -529,14 +545,13 @@ private: * \endcode * * `DatatypeSize` can have one of two values: - * - 4, float ; + * - 4, float; * - 8, double. * * `Number_of_records_per_line` gives the data count for each line of * the `Particle_values`. For example : - * - 4, the particle values are X Y Z Q; - * - 8, the particle values are X Y Z Q P FX FY FZ
- + * - 4, the particle values are `X Y Z Q`; + * - 8, the particle values are `X Y Z Q P FX FY FZ`. */ template class FFmaGenericWriter { @@ -642,9 +657,9 @@ public: /** * Writes the header of FMA file. - * + * * Should be used if we write the particles with writeArrayOfReal method - * + * * @param centerOfBox The center of the Box (FPoint class) * @param boxWidth The width of the box * @param nbParticles Number of particles in the box (or to save) @@ -672,7 +687,7 @@ public: * @tparam dataPart The class of the particle array. * @param dataToWrite Array of particles of type dataPart * @param N Number of element in the array - * + * * Example 1 * \code * FmaRParticle * particles = new FmaRParticle[nbParticles]; @@ -682,7 +697,7 @@ public: * Fwriter.writeHeader(Centre,BoxWith, nbParticles,*particles) ; * Fwriter.writeArrayOfParticles(particles, nbParticles); * \endcode - * + * * Example2 * \code * FReal * particles = new FReal[4*NbPoints] ; // store 4 data per particle @@ -736,13 +751,13 @@ public: /** * Write an array of data in a file Fill - * + * * @param dataToWrite array of particles of type FReal * @param nbData number of data per particle * @param N number of particles - * + * * The size of the array is N*nbData - * + * * example * \code * FmaRParticle * const particles = new FmaRParticle[nbParticles]; @@ -853,5 +868,3 @@ private: #endif //FFmaGenericLoader_HPP - - diff --git a/Src/Files/FMpiFmaDivider.hpp b/Src/Files/FMpiFmaDivider.hpp index ad826937e1508294ce1bf161ec3fa8bd266880f1..ee9d3fee8cb30e33c3b8109b964cc61fce0192ab 100644 --- a/Src/Files/FMpiFmaDivider.hpp +++ b/Src/Files/FMpiFmaDivider.hpp @@ -143,7 +143,7 @@ private: return FCoordinateComputer:: GetCoordinateFromPosition(_boxCenter, _boxWidth, _divisionLevel, getPosition()). - getMortonIndex(_divisionLevel); + getMortonIndex(); } diff --git a/Src/Files/FMpiTreeBuilder.hpp b/Src/Files/FMpiTreeBuilder.hpp index 87b5ecec6def1dee1acf607d7f31a18cee3d4cd0..95ed92bb00982bc3c6cd1ba978b78290c9aceb6e 100644 --- a/Src/Files/FMpiTreeBuilder.hpp +++ b/Src/Files/FMpiTreeBuilder.hpp @@ -101,7 +101,7 @@ public: host.setZ( FCoordinateComputer::GetTreeCoordinate( originalParticlesUnsorted[idxPart].particle.getPosition().getZ() - boxCorner.getZ(), loader.getBoxWidth(), boxWidthAtLeafLevel, TreeHeight )); - originalParticlesUnsorted[idxPart].index = host.getMortonIndex(TreeHeight - 1); + originalParticlesUnsorted[idxPart].index = host.getMortonIndex(); } // Sort particles @@ -140,7 +140,7 @@ public: host.setZ( FCoordinateComputer::GetTreeCoordinate( originalParticlesUnsorted[idxPart].particle.getPosition().getZ() - boxCorner.getZ(), boxWidth, boxWidthAtLeafLevel, TreeHeight )); - originalParticlesUnsorted[idxPart].index = host.getMortonIndex(TreeHeight - 1); + originalParticlesUnsorted[idxPart].index = host.getMortonIndex(); } FLOG( FLog::Controller << "Particles Distribution: " << "\tPrepare particles (" << counterTime.tacAndElapsed() << "s)\n"; FLog::Controller.flush(); ); diff --git a/Src/Files/FTreeBuilder.hpp b/Src/Files/FTreeBuilder.hpp index f5182371750179f508ed02d15908479970b21386..279fbe93c7fef1b4201a74924978d64d6ec70ee6 100644 --- a/Src/Files/FTreeBuilder.hpp +++ b/Src/Files/FTreeBuilder.hpp @@ -108,7 +108,7 @@ public: boxWidth,boxWidthAtLeafLevel, NbLevels ) ); // Store morton index and original idx - particleIndexes[idxParts].mindex = host.getMortonIndex(NbLevels-1); + particleIndexes[idxParts].mindex = host.getMortonIndex(); particleIndexes[idxParts].particlePositionInArray = idxParts; } diff --git a/Src/GroupTree/Core/FGroupTaskAlgorithm.hpp b/Src/GroupTree/Core/FGroupTaskAlgorithm.hpp index 98a4b10d3819c7687c05e4e584572d550bbac8f0..12ec1fc2277dbe438a918e5317dc318ee1f5096c 100644 --- a/Src/GroupTree/Core/FGroupTaskAlgorithm.hpp +++ b/Src/GroupTree/Core/FGroupTaskAlgorithm.hpp @@ -147,7 +147,7 @@ protected: MortonIndex interactionsIndexes[26]; int interactionsPosition[26]; - FTreeCoordinate coord(mindex, tree->getHeight()-1); + FTreeCoordinate coord(mindex); int counter = coord.getNeighborsIndexes(tree->getHeight(),interactionsIndexes,interactionsPosition); for(int idxInter = 0 ; idxInter < counter ; ++idxInter){ @@ -234,7 +234,7 @@ protected: MortonIndex interactionsIndexes[189]; int interactionsPosition[189]; - const FTreeCoordinate coord(mindex, idxLevel); + const FTreeCoordinate coord(mindex); int counter = coord.getInteractionNeighbors(idxLevel,interactionsIndexes,interactionsPosition); for(int idxInter = 0 ; idxInter < counter ; ++idxInter){ @@ -618,7 +618,7 @@ protected: MortonIndex interactionsIndexes[26]; int interactionsPosition[26]; - FTreeCoordinate coord(mindex, tree->getHeight()-1); + FTreeCoordinate coord(mindex); int counter = coord.getNeighborsIndexes(tree->getHeight(),interactionsIndexes,interactionsPosition); ParticleContainerClass interactionsObjects[26]; @@ -673,11 +673,11 @@ protected: FAssertLF(containers->getLeafMortonIndex((*outsideInteractions)[outInterIdx].insideIdxInBlock) == (*outsideInteractions)[outInterIdx].insideIndex); ParticleContainerClass* ptrLeaf = &interParticles; - kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].insideIndex, tree->getHeight()-1), + kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].insideIndex), &particles , &ptrLeaf, &(*outsideInteractions)[outInterIdx].relativeOutPosition, 1); const int otherPosition = getOppositeNeighIndex((*outsideInteractions)[outInterIdx].relativeOutPosition); ptrLeaf = &particles; - kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].outIndex, tree->getHeight()-1), + kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].outIndex), &interParticles , &ptrLeaf, &otherPosition, 1); } } diff --git a/Src/GroupTree/Core/FGroupTaskDepAlgorithm.hpp b/Src/GroupTree/Core/FGroupTaskDepAlgorithm.hpp index 163585bdd98f48ac0431cb2d342d45810a81f108..4e1744b293fdb8b6945d0dd50d26b069de23cdb6 100644 --- a/Src/GroupTree/Core/FGroupTaskDepAlgorithm.hpp +++ b/Src/GroupTree/Core/FGroupTaskDepAlgorithm.hpp @@ -204,7 +204,7 @@ protected: MortonIndex interactionsIndexes[26]; int interactionsPosition[26]; - FTreeCoordinate coord(mindex, tree->getHeight()-1); + FTreeCoordinate coord(mindex); int counter = coord.getNeighborsIndexes(tree->getHeight(),interactionsIndexes,interactionsPosition); for(int idxInter = 0 ; idxInter < counter ; ++idxInter){ @@ -291,7 +291,7 @@ protected: MortonIndex interactionsIndexes[189]; int interactionsPosition[189]; - const FTreeCoordinate coord(mindex, idxLevel); + const FTreeCoordinate coord(mindex); int counter = coord.getInteractionNeighbors(idxLevel,interactionsIndexes,interactionsPosition); for(int idxInter = 0 ; idxInter < counter ; ++idxInter){ @@ -777,11 +777,11 @@ protected: FAssertLF(containers->getLeafMortonIndex((*outsideInteractions)[outInterIdx].insideIdxInBlock) == (*outsideInteractions)[outInterIdx].insideIndex); ParticleContainerClass* ptrLeaf = &interParticles; - kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].insideIndex, tree->getHeight()-1), + kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].insideIndex), &particles , &ptrLeaf, &(*outsideInteractions)[outInterIdx].relativeOutPosition, 1); const int otherPosition = getOppositeNeighIndex((*outsideInteractions)[outInterIdx].relativeOutPosition); ptrLeaf = &particles; - kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].outIndex, tree->getHeight()-1), + kernel->P2POuter( FTreeCoordinate((*outsideInteractions)[outInterIdx].outIndex), &interParticles , &ptrLeaf, &otherPosition, 1); } } @@ -816,7 +816,7 @@ protected: MortonIndex interactionsIndexes[26]; int interactionsPosition[26]; - FTreeCoordinate coord(mindex, tree->getHeight()-1); + FTreeCoordinate coord(mindex); int counter = coord.getNeighborsIndexes(tree->getHeight(),interactionsIndexes,interactionsPosition); ParticleContainerClass interactionsObjects[26]; diff --git a/Src/GroupTree/Core/FGroupTree.hpp b/Src/GroupTree/Core/FGroupTree.hpp index 6d15f6f99644ece906cb63dcbab5153aab31e1e2..944d3f7c40e4a788ede9aa7fc2f36e90193485b1 100644 --- a/Src/GroupTree/Core/FGroupTree.hpp +++ b/Src/GroupTree/Core/FGroupTree.hpp @@ -203,7 +203,7 @@ public: const FTreeCoordinate host = FCoordinateComputer::GetCoordinateFromPositionAndCorner(this->boxCorner, this->boxWidth, treeHeight, FPoint(xpos[idxPart], ypos[idxPart], zpos[idxPart]) ); - const MortonIndex particleIndex = host.getMortonIndex(treeHeight-1); + const MortonIndex particleIndex = host.getMortonIndex(); particlesToSort[idxPart].mindex = particleIndex; particlesToSort[idxPart].originalIndex = idxPart; } @@ -260,7 +260,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); // Add leaf @@ -344,7 +344,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } @@ -405,7 +405,7 @@ public: const FTreeCoordinate host = FCoordinateComputer::GetCoordinateFromPositionAndCorner(this->boxCorner, this->boxWidth, treeHeight, FPoint(xpos[idxPart], ypos[idxPart], zpos[idxPart]) ); - const MortonIndex particleIndex = host.getMortonIndex(treeHeight-1); + const MortonIndex particleIndex = host.getMortonIndex(); particlesToSort[idxPart].mindex = particleIndex; particlesToSort[idxPart].originalIndex = idxPart; } @@ -466,7 +466,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); // Add leaf @@ -551,7 +551,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } @@ -606,7 +606,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } diff --git a/Src/GroupTree/Core/FGroupTreeDyn.hpp b/Src/GroupTree/Core/FGroupTreeDyn.hpp index 83558cff646154f100902cc7e21d3a8ce5ab6ab1..de88bfa6ac7211722866ef541cdcf1ff2ed9016f 100644 --- a/Src/GroupTree/Core/FGroupTreeDyn.hpp +++ b/Src/GroupTree/Core/FGroupTreeDyn.hpp @@ -243,7 +243,7 @@ public: const FTreeCoordinate host = FCoordinateComputer::GetCoordinateFromPositionAndCorner(this->boxCorner, this->boxWidth, treeHeight, inParticlesContainer[idxPart].pos); - const MortonIndex particleIndex = host.getMortonIndex(treeHeight-1); + const MortonIndex particleIndex = host.getMortonIndex(); inParticlesContainer[idxPart].mindex = particleIndex; inParticlesContainer[idxPart].originalIndex = idxPart; } @@ -296,7 +296,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } } @@ -397,7 +397,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } @@ -458,7 +458,7 @@ public: const FTreeCoordinate host = FCoordinateComputer::GetCoordinateFromPositionAndCorner(this->boxCorner, this->boxWidth, treeHeight, inParticlesContainer[idxPart].pos); - const MortonIndex particleIndex = host.getMortonIndex(treeHeight-1); + const MortonIndex particleIndex = host.getMortonIndex(); inParticlesContainer[idxPart].mindex = particleIndex; inParticlesContainer[idxPart].originalIndex = idxPart; } @@ -513,7 +513,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } } @@ -615,7 +615,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } @@ -671,7 +671,7 @@ public: CompositeCellClass newNode = newBlock->getCompleteCell(cellIdInBlock); newNode.setMortonIndex(currentBlockIndexes[cellIdInBlock]); FTreeCoordinate coord; - coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock], idxLevel); + coord.setPositionFromMorton(currentBlockIndexes[cellIdInBlock]); newNode.setCoordinate(coord); } @@ -881,4 +881,3 @@ public: }; #endif // FGROUPTREEDYN_HPP - diff --git a/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp b/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp index a3e57187e6215bd95698dca1370bf0120cab9f25..36e47e61fd31a65350560369ca5e3ac54b24cee8 100644 --- a/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp +++ b/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #ifndef FABSTRACTSPHERICALKERNEL_HPP @@ -71,7 +71,7 @@ protected: for(int idxChild = 0 ; idxChild < 8 ; ++idxChild ){ FTreeCoordinate childBox; - childBox.setPositionFromMorton(idxChild,1); + childBox.setPositionFromMorton(idxChild); const FPoint M2MVector ( father.getX() - (treeWidthAtLevel * FReal(1 + (childBox.getX() * 2))), @@ -627,7 +627,7 @@ private: harmonic.result(index_j_k) *= local_exp[index_j_k]; result += harmonic.result(index_j_k).getReal(); - ++index_j_k; + ++index_j_k; // k>0 for (int k = 1 ; k <= j ; ++k, ++index_j_k){ @@ -683,5 +683,3 @@ public: #endif //FABSTRACTSPHERICALKERNEL_HPP - - diff --git a/Src/ScalFmmConfig.h.cmake b/Src/ScalFmmConfig.h.cmake index 0c4c2960f17f539e9ae77a78ae489ed6e066c355..00b2066e4443163df8f302dad781d0a978606dbf 100644 --- a/Src/ScalFmmConfig.h.cmake +++ b/Src/ScalFmmConfig.h.cmake @@ -38,6 +38,7 @@ #cmakedefine SCALFMM_USE_FFT #cmakedefine SCALFMM_USE_MKL_AS_FFTW +#cmakedefine SCALFMM_USE_ESSL_AS_FFTW ////////////////////////////////////////////////////// // MPI diff --git a/Src/Utils/FAlgorithmTimers.hpp b/Src/Utils/FAlgorithmTimers.hpp index ee41b38f438d0c850e55198a5d8c0074698aae47..f9eb1f2a56a7b70e5cf03258e160a75f8d408eed 100644 --- a/Src/Utils/FAlgorithmTimers.hpp +++ b/Src/Utils/FAlgorithmTimers.hpp @@ -17,6 +17,13 @@ #ifndef FALGORITHMTIMERS_HPP #define FALGORITHMTIMERS_HPP +#include +#include + +#include "FTic.hpp" + +using FTimerMap = std::map; + /** * @brief Collection of timers for FMM operators. * @@ -25,56 +32,38 @@ */ class FAlgorithmTimers{ public: - /// The timer names - enum FTimers { - P2MTimer, - M2MTimer, - M2LTimer, - L2LTimer, - L2PTimer, - P2PTimer, - NearTimer, - nbTimers ///< Timer count - }; + static constexpr const char* P2MTimer = "P2M"; + static constexpr const char* M2MTimer = "M2M"; + static constexpr const char* M2LTimer = "M2L"; + static constexpr const char* L2LTimer = "L2L"; + static constexpr const char* L2PTimer = "L2P"; + static constexpr const char* P2PTimer = "P2P"; + static constexpr const char* M2PTimer = "M2P"; + static constexpr const char* P2LTimer = "P2L"; + static constexpr const char* NearTimer = "Near"; + enum {nbTimers = 9}; -protected: - /// Timer array - FTic Timers[nbTimers]; + /// Timers + FTimerMap Timers; -public: /// Constructor: resets all timers - FAlgorithmTimers() - { - for(int i = 0; i < nbTimers ; ++i){ - Timers[i].reset(); - } - } + FAlgorithmTimers() = default; /// Default copy contructor FAlgorithmTimers(const FAlgorithmTimers&) = default; /// Default move contructor FAlgorithmTimers(FAlgorithmTimers&&) = default; - /// Returns the timer array - const FTic * getAllTimers() const { - return Timers; - } - - /// Returns the timer count - int getNbOfTimerRecorded() const { - return nbTimers; - } - /// Elapsed time between last FTic::tic() and FTic::tac() for given timer. - double getTime(FTimers OpeTimer) const{ + double getTime(std::string TimerName) const{ //assert to verify size - return Timers[OpeTimer].elapsed(); + return Timers.at(TimerName).elapsed(); } /// Cumulated time between all FTic::tic() and FTic::tac() for given timer. - double getCumulatedTime(FTimers OpeTimer) const{ + double getCumulatedTime(std::string TimerName) const{ //assert to verify size - return Timers[OpeTimer].cumulated(); + return Timers.at(TimerName).cumulated(); } }; diff --git a/Src/Utils/FDft.hpp b/Src/Utils/FDft.hpp index a18301b45473889ce2acea77ca6b175043fc889a..e6659db03510a455f259485ee676c8711321a82d 100644 --- a/Src/Utils/FDft.hpp +++ b/Src/Utils/FDft.hpp @@ -26,10 +26,11 @@ #include #include -// include fftw3 (specify path in cmake) -// if MKL: path/to/mkl/include/fftw/fftw3.h -// elseif libfftw_dev: usr/include/fftw3.h +#ifdef SCALFMM_USE_ESSL_AS_FFTW +#include +#else #include +#endif // for @class FDft only #include "FBlas.hpp" diff --git a/Src/Utils/FPoint.hpp b/Src/Utils/FPoint.hpp index a33cacffd2f8e10d31e27a910b2da3eb734cfd13..ece9f09181edac97a16aa417676cd2818a557eec 100644 --- a/Src/Utils/FPoint.hpp +++ b/Src/Utils/FPoint.hpp @@ -32,14 +32,14 @@ * a few convenience operations such as addition, scalar multiplication and * division and formated stream output. * - * \tparam Real The floating number type + * \tparam _Real The floating number type * \tparam Dim The space dimension **/ template class FPoint : public std::array<_Real, _Dim> { public: /// Floating number type - using Real = _Real; + using FReal = _Real; /// Space dimension count constexpr static const std::size_t Dim = _Dim; @@ -57,22 +57,22 @@ private: /** Recursive template for constructor */ - template + template void _fill_data(const A& arg, const Args... args) { - this->data()[Dim-sizeof...(args)-1] = Real(arg); + this->data()[Dim-sizeof...(args)-1] = FReal(arg); _fill_data(args...); } /** Recursive template end condition for constructor */ - template + template void _fill_data(const A& arg) { - this->data()[Dim-1] = Real(arg); + this->data()[Dim-1] = FReal(arg); } public: /** Default constructor */ - FPoint() : std::array{{0}} {}; + FPoint() = default; /** Copy constructor */ FPoint(const FPoint&) = default; @@ -85,21 +85,21 @@ public: } /** Constructor from array */ - FPoint(const Real array[Dim]) { + FPoint(const FReal array_[Dim]) { for(std::size_t i = 0; i < Dim; ++i) { - this->data()[i] = array[i]; + this->data()[i] = array_[i]; } } /** Constructor from args */ - template - FPoint(const Real& arg, const Args... args) { + template + FPoint(const FReal& arg, const Args... args) { static_assert(sizeof...(args)+1 == Dim, "FPoint argument list isn't the right length."); _fill_data(arg, args...); } /** Additive contructor, same as FPoint(other + add_value) */ - FPoint(const FPoint& other, const Real add_value) { + FPoint(const FPoint& other, const FReal add_value) { for(std::size_t i = 0; i < Dim; ++i) { this->data()[i] = other.data()[i] + add_value; } @@ -124,15 +124,15 @@ public: * \param other A FPoint object. */ template = nullptr> - FPoint& operator=(const FPoint& other) { + FPoint& operator=(const FPoint& other) { this->copy(other); return *this; } /** Sets the point value */ - template - void setPosition(const Real& X, const Args... YandZ) { + template + void setPosition(const FReal& X, const Args... YandZ) { static_assert(sizeof...(YandZ)+1 == Dim, "FPoint argument list isn't the right length."); _fill_data(X, YandZ...); } @@ -140,7 +140,7 @@ public: /** \brief Get x * \return this->data()[0] */ - Real getX() const{ + FReal getX() const{ return this->data()[0]; } @@ -148,7 +148,7 @@ public: /** \brief Get y * \return this->data()[1] */ - Real getY() const{ + FReal getY() const{ return this->data()[1]; } @@ -156,7 +156,7 @@ public: /** \brief Get z * \return this->data()[2] */ - Real getZ() const{ + FReal getZ() const{ return this->data()[2]; } @@ -164,7 +164,7 @@ public: /** \brief Set x * \param the new x */ - void setX(const Real inX){ + void setX(const FReal inX){ this->data()[0] = inX; } @@ -172,7 +172,7 @@ public: /** \brief Set y * \param the new y */ - void setY(const Real inY){ + void setY(const FReal inY){ this->data()[1] = inY; } @@ -180,7 +180,7 @@ public: /** \brief Set z * \param the new z */ - void setZ(const Real inZ){ + void setZ(const FReal inZ){ this->data()[2] = inZ; } @@ -188,7 +188,7 @@ public: /** \brief Add to the x-dimension the inX value * \param inXthe increment in x */ - void incX(const Real inX){ + void incX(const FReal inX){ this->data()[0] += inX; } @@ -196,7 +196,7 @@ public: /** \brief Add to the y-dimension the inY value * \param in<<<<<data()[1] += inY; } @@ -204,36 +204,36 @@ public: /** \brief Add to z-dimension the inZ value * \param inZ the increment in z */ - void incZ(const Real inZ){ + void incZ(const FReal inZ){ this->data()[2] += inZ; } - /** \brief Get a pointer on the coordinate of FPoint + /** \brief Get a pointer on the coordinate of FPoint * \return the data value array */ - Real * getDataValue(){ + FReal * getDataValue(){ return this->data() ; } - /** \brief Get a pointer on the coordinate of FPoint + /** \brief Get a pointer on the coordinate of FPoint * \return the data value array */ - const Real * getDataValue() const{ + const FReal * getDataValue() const{ return this->data() ; } /** \brief Compute the distance to the origin * \return the norm of the FPoint */ - Real norm() const { + FReal norm() const { return FMath::Sqrt(norm2()) ; } /** \brief Compute the distance to the origin * \return the square norm of the FPoint */ - Real norm2() const { - Real square_sum = 0; + FReal norm2() const { + FReal square_sum = 0; for(std::size_t i = 0; i < Dim; ++i) { square_sum += this->data()[i]*this->data()[i]; } @@ -255,7 +255,7 @@ public: /** Addition operator */ template = nullptr> - friend FPoint operator+(FPoint lhs, const FPoint& rhs) { + friend FPoint operator+(FPoint lhs, const FPoint& rhs) { lhs += rhs; return lhs; } @@ -271,7 +271,7 @@ public: /** Scalar addition */ template = nullptr> - friend FPoint operator+(FPoint lhs, const T& val) { + friend FPoint operator+(FPoint lhs, const T& val) { lhs += val; return lhs; } @@ -289,7 +289,7 @@ public: /** Subtraction operator */ template = nullptr> - friend FPoint operator-(FPoint lhs, const FPoint& rhs) { + friend FPoint operator-(FPoint lhs, const FPoint& rhs) { lhs -= rhs; return lhs; } @@ -305,7 +305,7 @@ public: /** Scalar subtraction */ template = nullptr> - friend FPoint operator-(FPoint lhs, const T& rhs) { + friend FPoint operator-(FPoint lhs, const T& rhs) { lhs -= rhs; return lhs; } @@ -313,7 +313,7 @@ public: /** Right scalar multiplication assignment operator */ template = nullptr> - FPoint& operator *=(const T& val) { + FPoint& operator *=(const T& val) { for(std::size_t i = 0; i < Dim; ++i) { this->data()[i] *= val; } @@ -322,21 +322,21 @@ public: /** Right scalar multiplication operator */ template = nullptr> - friend FPoint operator*(FPoint lhs, const T& val) { + friend FPoint operator*(FPoint lhs, const T& val) { lhs *= val; return lhs; } /** Left scalar multiplication operator */ template = nullptr> - friend FPoint operator*(const T& val, FPoint rhs) { + friend FPoint operator*(const T& val, FPoint rhs) { rhs *= val; return rhs; } /** Data to data division assignment */ template = nullptr> - FPoint& operator /=(const FPoint& other) { + FPoint& operator /=(const FPoint& other) { for(std::size_t i = 0; i < Dim; ++i) { this->data()[i] *= other.data()[i]; } @@ -345,14 +345,14 @@ public: /** Data to data division operator */ template = nullptr> - friend FPoint operator/(FPoint lhs, const FPoint& rhs) { + friend FPoint operator/(FPoint lhs, const FPoint& rhs) { lhs /= rhs; return lhs; } /** Right scalar division assignment operator */ template = nullptr> - FPoint& operator /=(const T& val) { + FPoint& operator /=(const T& val) { auto this_it = this->begin(); for(std::size_t i = 0; i < Dim; i++, ++this_it) { *this_it /= val; @@ -363,14 +363,14 @@ public: /** Right scalar division operator */ template = nullptr> - friend FPoint operator/(FPoint lhs, const T& val) { + friend FPoint operator/(FPoint lhs, const T& val) { lhs /= val; return lhs; } /** Equality test operator */ template = nullptr> - friend bool operator==(const FPoint& lhs, const FPoint& rhs) { + friend bool operator==(const FPoint& lhs, const FPoint& rhs) { auto lhs_it = lhs.begin(), rhs_it = rhs.begin(); for(std::size_t i = 0; i < Dim; i++, ++lhs_it, ++rhs_it) { if( *lhs_it != *rhs_it) { @@ -382,7 +382,7 @@ public: /** Equality test operator */ template = nullptr> - friend bool operator==(const FPoint& lhs, const FPoint& rhs) { + friend bool operator==(const FPoint& lhs, const FPoint& rhs) { auto lhs_it = lhs.begin(), rhs_it = rhs.begin(); for(std::size_t i = 0; i < Dim; i++, ++lhs_it, ++rhs_it) { if(! Ffeq(*lhs_it, *rhs_it)) { @@ -394,12 +394,12 @@ public: /** Non equality test operator */ template = nullptr> - friend bool operator!=(const FPoint& lhs, const FPoint& rhs) { + friend bool operator!=(const FPoint& lhs, const FPoint& rhs) { return ! (lhs == rhs); } /** Formated output stream operator */ - friend std::ostream& operator<<(std::ostream& os, const FPoint& pos) { + friend std::ostream& operator<<(std::ostream& os, const FPoint& pos) { os << "["; for(auto it = pos.begin(); it != pos.end()-1; it++) os << *it << ", "; @@ -408,10 +408,15 @@ public: } /** Formated input stream operator */ - friend std::istream& operator>>(std::istream& is, const FPoint& pos) { - for(std::size_t i = 0; i < Dim; ++i) { + friend std::istream& operator>>(std::istream& is, FPoint& pos) { + char c; + is >> c; // opening '[' + for(std::size_t i = 0; i + 1 < Dim; ++i) { is >> pos.data()[i]; + is >> c; // get coma ',' } + is >> pos.data()[Dim-1]; + is >> c; // closing ']' return is; } diff --git a/Src/Utils/FTic.hpp b/Src/Utils/FTic.hpp index 911c88043091d1985fb8324bd377bd52d013c5e4..72527b6e454f50ab0a2db5d67ab54ce8c00dae2e 100644 --- a/Src/Utils/FTic.hpp +++ b/Src/Utils/FTic.hpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #ifndef FTIC_HPP @@ -18,7 +18,11 @@ #include "FGlobal.hpp" -#ifdef _OPENMP +#define USE_STD_CHRONO + +#if defined(USE_STD_CHRONO) + #include +#elif defined(_OPENMP) #include #elif defined(WINDOWS) // We need an os specific function #include @@ -42,7 +46,7 @@ * * - use elapsed() to get the last time interval; * - use cumulated() to get the total running time; - * - use reset() to stop and reset the counter. + * - use reset() to stop and reset the counter. * * \code * FTic timer; @@ -66,12 +70,12 @@ private: double start = 0; ///< start time (tic) double end = 0; ///< stop time (tac) - double cumulate = 0; ///< the cumulate time + double cumulate = 0; ///< cumulated duration public: /// Constructor FTic() { - tic(); + this->reset(); } /// Copy constructor @@ -100,12 +104,12 @@ public: res.cumulate += other.cumulate; return res; } - + /// Resets the timer /**\warning Use tic() to restart the timer. */ void reset() { - start = 0; - end = 0; + start = FTic::GetTime(); + end = start; cumulate = 0; } @@ -114,26 +118,35 @@ public: this->start = FTic::GetTime(); } + /// Peek at current elapsed time without stopping timer + double peek() const { + return FTic::GetTime() - this->start;; + } + /// Stop measuring time and add to cumulated time. - void tac(){ + double tac(){ this->end = FTic::GetTime(); - cumulate += elapsed(); + auto lapse = this->elapsed(); + cumulate += lapse; + return lapse; } /// Elapsed time between the last tic() and tac() (in seconds). /** \return the time elapsed between tic() & tac() in second. */ - double elapsed() const{ + double elapsed() const { return this->end - this->start; } /// Cumulated tic() - tac() time spans /** \return the time elapsed between ALL tic() & tac() in second. */ - double cumulated() const{ + double cumulated() const { return cumulate; } /// Combination of tic() and elapsed(). - /** \return the time elapsed between tic() & tac() in second. */ + /** + * \todo deprecate + * \return the time elapsed between tic() & tac() in second. */ double tacAndElapsed() { tac(); return elapsed(); @@ -145,7 +158,11 @@ public: * \return A system dependent time point. */ static double GetTime(){ -#ifdef _OPENMP +#if defined(USE_STD_CHRONO) + using clock = std::chrono::high_resolution_clock; + using duration = std::chrono::duration; + return duration(clock::now().time_since_epoch()).count(); +#elif defined(_OPENMP) return omp_get_wtime(); #elif defined(WINDOWS) return static_cast(GetTickCount())/1000.0; @@ -159,4 +176,3 @@ public: #endif - diff --git a/Tests/GroupTree/testBlockedMpiAlgorithm.cpp b/Tests/GroupTree/testBlockedMpiAlgorithm.cpp index d9567b14e6de476b0c25307c0fb22402b7729f30..e6058ab3c3a97ddfd0c8ba691a4b0aa9dad07d9b 100644 --- a/Tests/GroupTree/testBlockedMpiAlgorithm.cpp +++ b/Tests/GroupTree/testBlockedMpiAlgorithm.cpp @@ -115,7 +115,7 @@ int main(int argc, char* argv[]){ loader.getBoxWidth(), NbLevels, myParticles[myParticles.getSize()-1].position ); - const MortonIndex myLeftLimite = host.getMortonIndex(NbLevels-1); + const MortonIndex myLeftLimite = host.getMortonIndex(); MortonIndex leftLimite = -1; if(mpiComm.global().processId() != 0){ FMpi::Assert(MPI_Recv(&leftLimite, sizeof(leftLimite), MPI_BYTE, diff --git a/Tests/GroupTree/testBlockedMpiChebyshev.cpp b/Tests/GroupTree/testBlockedMpiChebyshev.cpp index 141e296367b711a07ee7addc40d880302e585a88..721908d355e8f143c32bc77384daf3446884dd5a 100644 --- a/Tests/GroupTree/testBlockedMpiChebyshev.cpp +++ b/Tests/GroupTree/testBlockedMpiChebyshev.cpp @@ -124,7 +124,7 @@ int main(int argc, char* argv[]){ loader.getBoxWidth(), TreeHeight, myParticles[myParticles.getSize()-1].position ); - const MortonIndex myLeftLimite = host.getMortonIndex(TreeHeight-1); + const MortonIndex myLeftLimite = host.getMortonIndex(); MortonIndex leftLimite = -1; if(mpiComm.global().processId() != 0){ FMpi::Assert(MPI_Recv(&leftLimite, sizeof(leftLimite), MPI_BYTE, diff --git a/Tests/GroupTree/testBlockedRotationMpi.cpp b/Tests/GroupTree/testBlockedRotationMpi.cpp index e2c30375a17c53ba6ef9ddb94fad2cfb30df12a0..0e0048adf70343be2f0ae124c5ed784e04c11745 100644 --- a/Tests/GroupTree/testBlockedRotationMpi.cpp +++ b/Tests/GroupTree/testBlockedRotationMpi.cpp @@ -128,7 +128,7 @@ int main(int argc, char* argv[]){ loader.getBoxWidth(), TreeHeight, myParticles[myParticles.getSize()-1].position ); - const MortonIndex myLeftLimite = host.getMortonIndex(TreeHeight-1); + const MortonIndex myLeftLimite = host.getMortonIndex(); MortonIndex leftLimite = -1; if(mpiComm.global().processId() != 0){ FMpi::Assert(MPI_Recv(&leftLimite, sizeof(leftLimite), MPI_BYTE, diff --git a/Tests/GroupTree/testBlockedRotationMpiCuda.cpp b/Tests/GroupTree/testBlockedRotationMpiCuda.cpp index 79f80987ad7d7aee7a148fbde60af9dcb31e7f0a..563c63e800017f10aa1c1a879df6ee246d36f220 100644 --- a/Tests/GroupTree/testBlockedRotationMpiCuda.cpp +++ b/Tests/GroupTree/testBlockedRotationMpiCuda.cpp @@ -135,7 +135,7 @@ int main(int argc, char* argv[]){ loader.getBoxWidth(), TreeHeight, myParticles[myParticles.getSize()-1].position ); - const MortonIndex myLeftLimite = host.getMortonIndex(TreeHeight-1); + const MortonIndex myLeftLimite = host.getMortonIndex(); MortonIndex leftLimite = -1; if(mpiComm.global().processId() != 0){ FMpi::Assert(MPI_Recv(&leftLimite, sizeof(leftLimite), MPI_BYTE, diff --git a/Tests/GroupTree/testBlockedUniformBench.cpp b/Tests/GroupTree/testBlockedUniformBench.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56f3be19bacf564a455337c01a614f9ef6bab9df --- /dev/null +++ b/Tests/GroupTree/testBlockedUniformBench.cpp @@ -0,0 +1,194 @@ + +// ==== CMAKE ===== +// @FUSE_BLAS +// @FUSE_FFT +// @FUSE_STARPU +// ================ +// Keep in private GIT + + +#include "../../Src/Utils/FGlobal.hpp" + +#include "../../Src/GroupTree/Core/FGroupTree.hpp" + +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Containers/FVector.hpp" + +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + +#include "Kernels/Interpolation/FInterpMatrixKernel.hpp" +#include "../../Src/Kernels/Uniform/FUnifKernel.hpp" + +#include "../../Src/GroupTree/Uniform/FUnifCellPOD.hpp" + +#include "../../Src/Utils/FMath.hpp" +#include "../../Src/Utils/FMemUtils.hpp" +#include "../../Src/Utils/FParameters.hpp" + +#include "../../Src/Files/FRandomLoader.hpp" +#include "../../Src/Files/FFmaGenericLoader.hpp" + +#include "../../Src/GroupTree/Core/FGroupSeqAlgorithm.hpp" +#include "../../Src/GroupTree/Core/FGroupTaskAlgorithm.hpp" +#ifdef SCALFMM_USE_OMP4 +#include "../../Src/GroupTree/Core/FGroupTaskDepAlgorithm.hpp" +#endif +#ifdef SCALFMM_USE_STARPU +#include "../../Src/GroupTree/Core/FGroupTaskStarpuAlgorithm.hpp" +#include "../../Src/GroupTree/StarPUUtils/FStarPUKernelCapacities.hpp" +#endif +#include "../../Src/GroupTree/Core/FP2PGroupParticleContainer.hpp" + +#include "../../Src/Utils/FParameterNames.hpp" + +#include + + +#define RANDOM_PARTICLES + +int main(int argc, char* argv[]){ + const FParameterNames LocalOptionBlocSize { {"-bs"}, "The size of the block of the blocked tree"}; + const FParameterNames LocalOptionValidate { {"-validation"}, "To compare with direct computation"}; + FHelpDescribeAndExit(argc, argv, "Perform Lagrange Kernel based simulation with StarPU", + FParameterDefinitions::OctreeHeight, +#ifdef RANDOM_PARTICLES + FParameterDefinitions::NbParticles, +#else + FParameterDefinitions::InputFile, +#endif + FParameterDefinitions::NbThreads, + LocalOptionBlocSize, LocalOptionValidate); + + // Initialize the types + typedef double FReal; + static const int ORDER = 5; + typedef FInterpMatrixKernelR MatrixKernelClass; + + typedef FUnifCellPODCore GroupCellSymbClass; + typedef FUnifCellPODPole GroupCellUpClass; + typedef FUnifCellPODLocal GroupCellDownClass; + typedef FUnifCellPOD GroupCellClass; + + typedef FP2PGroupParticleContainer GroupContainerClass; + typedef FGroupTree< FReal, GroupCellClass, GroupCellSymbClass, GroupCellUpClass, GroupCellDownClass, GroupContainerClass, 1, 4, FReal> GroupOctreeClass; + + typedef FStarPUAllCpuCapacities> GroupKernelClass; + typedef FStarPUCpuWrapper GroupCpuWrapper; + typedef FGroupTaskStarPUAlgorithm GroupAlgorithm; + + // Get params + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int groupSize = FParameters::getValue(argc,argv,LocalOptionBlocSize.options, 250); + + // Load the particles +#ifdef RANDOM_PARTICLES + FRandomLoader loader(FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000), 1.0, FPoint(0,0,0), 0); +#else + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + FFmaGenericLoader loader(filename); +#endif + FAssertLF(loader.isOpen()); + FTic timer; + + FP2PParticleContainer allParticles; + for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue; +#ifdef RANDOM_PARTICLES + physicalValue = 0.10; + loader.fillParticle(&particlePosition); +#else + loader.fillParticle(&particlePosition, &physicalValue); +#endif + allParticles.push(particlePosition, physicalValue); + } + std::cout << "Particles loaded in " << timer.tacAndElapsed() << "s\n"; + + // Put the data into the tree + timer.tic(); + GroupOctreeClass groupedTree(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox(), groupSize, &allParticles); + groupedTree.printInfoBlocks(); + std::cout << "Tree created in " << timer.tacAndElapsed() << "s\n"; + + // Run the algorithm + const MatrixKernelClass MatrixKernel; + GroupKernelClass groupkernel(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox(), &MatrixKernel); + GroupAlgorithm groupalgo(&groupedTree,&groupkernel); + + timer.tic(); + groupalgo.execute(); + timer.tac(); + std::cout << "@EXEC TIME = " << timer.elapsed() << "s\n"; + + // Validate the result + if(FParameters::existParameter(argc, argv, LocalOptionValidate.options) == true){ + FSize offsetParticles = 0; + FReal*const allPhysicalValues = allParticles.getPhysicalValues(); + FReal*const allPosX = const_cast( allParticles.getPositions()[0]); + FReal*const allPosY = const_cast( allParticles.getPositions()[1]); + FReal*const allPosZ = const_cast( allParticles.getPositions()[2]); + + groupedTree.forEachCellLeaf >([&](GroupCellClass cellTarget, FP2PGroupParticleContainer * leafTarget){ + const FReal*const physicalValues = leafTarget->getPhysicalValues(); + const FReal*const posX = leafTarget->getPositions()[0]; + const FReal*const posY = leafTarget->getPositions()[1]; + const FReal*const posZ = leafTarget->getPositions()[2]; + const FSize nbPartsInLeafTarget = leafTarget->getNbParticles(); + + for(FSize idxPart = 0 ; idxPart < nbPartsInLeafTarget ; ++idxPart){ + allPhysicalValues[offsetParticles + idxPart] = physicalValues[idxPart]; + allPosX[offsetParticles + idxPart] = posX[idxPart]; + allPosY[offsetParticles + idxPart] = posY[idxPart]; + allPosZ[offsetParticles + idxPart] = posZ[idxPart]; + } + + offsetParticles += nbPartsInLeafTarget; + }); + + FAssertLF(offsetParticles == loader.getNumberOfParticles()); + + FReal*const allDirectPotentials = allParticles.getPotentials(); + FReal*const allDirectforcesX = allParticles.getForcesX(); + FReal*const allDirectforcesY = allParticles.getForcesY(); + FReal*const allDirectforcesZ = allParticles.getForcesZ(); + + for(int idxTgt = 0 ; idxTgt < offsetParticles ; ++idxTgt){ + for(int idxMutual = idxTgt + 1 ; idxMutual < offsetParticles ; ++idxMutual){ + FP2PR::MutualParticles( + allPosX[idxTgt],allPosY[idxTgt],allPosZ[idxTgt], allPhysicalValues[idxTgt], + &allDirectforcesX[idxTgt], &allDirectforcesY[idxTgt], &allDirectforcesZ[idxTgt], &allDirectPotentials[idxTgt], + allPosX[idxMutual],allPosY[idxMutual],allPosZ[idxMutual], allPhysicalValues[idxMutual], + &allDirectforcesX[idxMutual], &allDirectforcesY[idxMutual], &allDirectforcesZ[idxMutual], &allDirectPotentials[idxMutual] + ); + } + } + + FMath::FAccurater potentialDiff; + FMath::FAccurater fx, fy, fz; + offsetParticles = 0; + groupedTree.forEachCellLeaf >([&](GroupCellClass cellTarget, FP2PGroupParticleContainer * leafTarget){ + const FReal*const potentials = leafTarget->getPotentials(); + const FReal*const forcesX = leafTarget->getForcesX(); + const FReal*const forcesY = leafTarget->getForcesY(); + const FReal*const forcesZ = leafTarget->getForcesZ(); + const FSize nbPartsInLeafTarget = leafTarget->getNbParticles(); + + for(int idxTgt = 0 ; idxTgt < nbPartsInLeafTarget ; ++idxTgt){ + potentialDiff.add(allDirectPotentials[idxTgt + offsetParticles], potentials[idxTgt]); + fx.add(allDirectforcesX[idxTgt + offsetParticles], forcesX[idxTgt]); + fy.add(allDirectforcesY[idxTgt + offsetParticles], forcesY[idxTgt]); + fz.add(allDirectforcesZ[idxTgt + offsetParticles], forcesZ[idxTgt]); + } + + offsetParticles += nbPartsInLeafTarget; + }); + + std::cout << "Error : Potential " << potentialDiff << "\n"; + std::cout << "Error : fx " << fx << "\n"; + std::cout << "Error : fy " << fy << "\n"; + std::cout << "Error : fz " << fz << "\n"; + } + + return 0; +} + diff --git a/Tests/Utils/testFFT.cpp b/Tests/Utils/testFFT.cpp index 9706a9fe665165c9fed61a76ea2ec49f83c8a477..1795f9fbc640378d566aeb83d6bd22d38b902d26 100644 --- a/Tests/Utils/testFFT.cpp +++ b/Tests/Utils/testFFT.cpp @@ -21,7 +21,11 @@ #include #include +#ifdef SCALFMM_USE_ESSL_AS_FFTW +#include +#else #include +#endif #include "Utils/FGlobal.hpp" #include "Utils/FComplex.hpp" diff --git a/Tests/Utils/testOctreePrintMorton.cpp b/Tests/Utils/testOctreePrintMorton.cpp index 5c8081c24401f6a6cd88f54e0ba4727097cbd618..de7a6e7ba97e4e5c3cbfc6b7739243894b9f4878 100644 --- a/Tests/Utils/testOctreePrintMorton.cpp +++ b/Tests/Utils/testOctreePrintMorton.cpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== @@ -126,7 +126,7 @@ int main(int argc, char ** argv){ }while(sscanf(buffer,"%d %d %d",&x,&y,&z) != 3); FTreeCoordinate coord(x,y,z); - const MortonIndex index = coord.getMortonIndex(requiredlevel) ; + const MortonIndex index = coord.getMortonIndex() ; std::cout << " Morton Index is " << index << " \t " << std::hex << index << "H \t " << MortonToBinary(index,requiredlevel) << "D\n\n"; } break; @@ -158,7 +158,7 @@ int main(int argc, char ** argv){ host.setY( int(FMath::dfloor(( FReal(y) - centerOfBox.getY() - rootBoxWidth/2) / boxWidthAtThisLevel ) )); host.setZ( int(FMath::dfloor(( FReal(z) - centerOfBox.getZ() - rootBoxWidth/2) / boxWidthAtThisLevel ) )); - const MortonIndex index = host.getMortonIndex(requiredlevel); + const MortonIndex index = host.getMortonIndex(); std::cout << " Morton Index is " << index << " \t " << std::hex << index << "h \t " << MortonToBinary(index,requiredlevel) << "d\n\n"; } break; @@ -193,7 +193,7 @@ int main(int argc, char ** argv){ for(int y = sy ; y <= ey ; ++y){ for(int x = sx ; x <= ex ; ++x){ FTreeCoordinate coord(x,y,z); - const MortonIndex index = coord.getMortonIndex(requiredlevel); + const MortonIndex index = coord.getMortonIndex(); std::cout << "[x = " << x << " y = " << y << " z = " << z << "]\n"; std::cout << " Morton Index is " << index << " \t " << std::hex << index << "H \t " << MortonToBinary(index,requiredlevel) << "D\n\n"; } @@ -219,7 +219,7 @@ int main(int argc, char ** argv){ for(int y = 0 ; y < maxBoxAtThisLevel ; ++y){ for(int x = 0 ; x < maxBoxAtThisLevel ; ++x){ FTreeCoordinate coord(x,y,z); - const MortonIndex index = coord.getMortonIndex(requiredlevel); + const MortonIndex index = coord.getMortonIndex(); std::cout << "[x = " << x << " y = " << y << " z = " << z << "]\n"; std::cout << " Morton Index is " << index << " \t " << std::hex << index << "H \t " << MortonToBinary(index,requiredlevel) << "D\n\n"; } @@ -274,7 +274,7 @@ int main(int argc, char ** argv){ }while(sscanf(buffer,"%lld",&index) != 1); FTreeCoordinate coord; - coord.setPositionFromMorton(index,requiredlevel); + coord.setPositionFromMorton(index); std::cout << " This position is in the boxe x = "<< coord.getX() << " y = " << coord.getY() << " z = " << coord.getZ() << "\n"; @@ -293,6 +293,3 @@ int main(int argc, char ** argv){ return 0; } - - - diff --git a/Tests/noDist/Adaptive/MockParticle.hpp b/Tests/noDist/Adaptive/MockParticle.hpp deleted file mode 100644 index e7d34ac66531d89a1e3d6c1df322063be78e48a7..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/MockParticle.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _SCALFMM_TEST_MOCKPARTICLE_HPP_ -#define _SCALFMM_TEST_MOCKPARTICLE_HPP_ - -#include "Utils/FPoint.hpp" - -namespace scalfmm { - namespace tests { - - template - struct MockParticle { - - constexpr static const std::size_t Dim = _Dim; - using Real = _Real; - using position_t = FPoint; - - static std::size_t idx; - - MockParticle(position_t pos) : - _pos(pos), - index(++idx) - {} - - MockParticle(position_t pos, std::size_t new_index) : - _pos(pos), - index(new_index) - { - idx = new_index+1; - } - - - position_t _pos; - std::size_t index; - - position_t& position(const position_t& p) {return (_pos = p);} - position_t& position() {return _pos;} - const position_t& position() const {return _pos;} - }; - - template - std::size_t MockParticle::idx = 0; - } -} - - -#endif diff --git a/Tests/noDist/Adaptive/test_Abstract.hpp b/Tests/noDist/Adaptive/test_Abstract.hpp deleted file mode 100644 index 24a980a565e120d29c848fbadffcc6ddf09a11d6..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_Abstract.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SCALFMM_TEST_ABSTRACT_HPP_ -#define SCALFMM_TEST_ABSTRACT_HPP_ - -#include -#include - -#define RUN(test_function_name) \ - std::cout << #test_function_name << std::endl; \ - run_test(& std::remove_reference::type :: test_function_name); - -template -struct test_Abstract { - virtual void set_up() {} - virtual void tear_down() {} - virtual void run_all() = 0; - - virtual void run_test(void (T::*test_function)()) { - this->set_up(); - (dynamic_cast(this)->*test_function)(); - this->tear_down(); - - } -}; - -#endif diff --git a/Tests/noDist/Adaptive/test_FBox.cpp b/Tests/noDist/Adaptive/test_FBox.cpp deleted file mode 100644 index 1549956057c6686a07c1cd6015d697fb1c3e6105..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FBox.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include -#include -#include - -#include "test_Abstract.hpp" - -#include "Utils/FPoint.hpp" -#include "Utils/FConstFuncs.hpp" -#include "Adaptive/new/FBox.hpp" - -namespace scalfmm { - namespace tests { - - - struct test_Box : public test_Abstract { - - constexpr static const std::size_t Dim = 3; - using position_t = FPoint; - using box_t = FBox; - - void run_all() { - RUN(test_constructor_1 ); - RUN(test_constructor_2 ); - RUN(test_constructor_3 ); - RUN(test_constructor_4 ); - RUN(test_constructor_5 ); - RUN(test_assign_copy_operator); - RUN(test_assign_move_operator); - RUN(test_center ); - RUN(test_corner ); - RUN(test_contains ); - } - - - /// Test default constructor - void test_constructor_1() { - box_t b; - position_t p {0,0,0}; - assert(b.c1 == p); - assert(b.c2 == p); - } - - /// Test constructor with minimum and maximum corners - void test_constructor_2() { - position_t p1 = {0,0,0}; - position_t p2 = {100,100,100}; - - box_t b(p1, p2); - assert(b.c1 == p1); - assert(b.c2 == p2); - } - - /// Test constructor with initializer lists - void test_constructor_3() { - position_t p {0,0,0}; - box_t d({0,0,0},{0,0,0}); - - assert(d.c1 == p); - assert(d.c2 == p); - } - - /// Test copy constructor - void test_constructor_4() { - position_t p1 = {0,0,0}; - position_t p2 = {100,100,100}; - box_t c(p1, p2); - - box_t e(c); - assert(c.c1 == e.c1); - assert(c.c2 == e.c2); - - // test deep copy - c.set(p2, p1 + position_t{-1,0,0}); - - assert(c.c1 != e.c1); - assert(c.c2 == e.c2); - } - - void test_constructor_5() { - position_t p1 = {0,100,0}; - position_t p2 = {100,0,100}; - box_t c(p1, p2); - - for(std::size_t i = 0; i < Dim; ++i) { - assert(Ffeq(c.c1[i], std::fmin(p1[i], p2[i]))); - assert(Ffeq(c.c2[i], std::fmax(p1[i], p2[i]))); - } - } - - void test_assign_copy_operator() { - position_t p1 = {0,0,0}; - position_t p2 = {100,100,100}; - box_t a(p1, p2); - - box_t b; - b = a; - assert(a.c1 == b.c1); - assert(a.c2 == b.c2); - assert(a.center() == b.center()); - } - - void test_assign_move_operator() { - position_t p1 = {0,0,0}; - position_t p2 = {100,100,100}; - box_t a(p1, p2); - - box_t b; - b = std::move(a); - assert(a.c1 == b.c1); - assert(a.c2 == b.c2); - } - - - void test_center() { - position_t p1 = {0,10,50}; - position_t p2 = {100,100,100}; - position_t p3 = {50,55,75}; - - box_t b{p1, p2}; - - assert(b.center() == p3); - - // Test center after copy - box_t c(b); - assert(c.center() == p3); - - b.set({20,30,40}, {120, 130, 140}); - assert(b.center() == position_t(70, 80, 90)); - } - - void test_corner() { - position_t p0 = { 0, 0, 0}; - position_t p1 = { 0, 0,100}; - position_t p2 = { 0,100, 0}; - position_t p3 = { 0,100,100}; - position_t p4 = {100, 0, 0}; - position_t p5 = {100, 0,100}; - position_t p6 = {100,100, 0}; - position_t p7 = {100,100,100}; - - box_t b = {p0, p7}; - - assert(b.corner(0) == p0); - assert(b.corner(1) == p1); - assert(b.corner(2) == p2); - assert(b.corner(3) == p3); - assert(b.corner(4) == p4); - assert(b.corner(5) == p5); - assert(b.corner(6) == p6); - assert(b.corner(7) == p7); - - b.corner(0, {1,1,1}); - assert(b.corner(0) == b.c1); - assert(b.corner(0) == position_t(1,1,1)); - b.corner(0, {0,0,0}); - - b.corner(2, {20, 80, 30}); - assert(b.c1 == position_t(20, 0, 30)); - assert(b.c2 == position_t(100, 80, 100)); - - b.corner(5, {0, 20, 25}); - assert(b.c1 == position_t(0, 20, 25)); - assert(b.c2 == position_t(20, 80, 30)); - } - - struct DummyObject { - position_t p; - position_t position() const {return p;} - }; - - void test_contains() { - box_t b = {{0,0,0}, {100,100,100}}; - - assert(b.contains(b.c1)); - assert(b.contains(b.c2)); - assert(b.contains({50,50,50})); - assert(! b.contains({150,50,50})); - assert(! b.contains({50,150,50})); - assert(! b.contains({50,50,150})); - assert(! b.contains({50,150,150})); - assert(! b.contains({150,150,50})); - assert(! b.contains({150,50,150})); - assert(! b.contains({150,150,150})); - - assert(b.contains(DummyObject {{ 50, 50, 50}})); - assert(! b.contains(DummyObject{{150, 50, 50}})); - assert(! b.contains(DummyObject{{ 50,150, 50}})); - assert(! b.contains(DummyObject{{ 50, 50,150}})); - assert(! b.contains(DummyObject{{ 50,150,150}})); - assert(! b.contains(DummyObject{{150,150, 50}})); - assert(! b.contains(DummyObject{{150, 50,150}})); - assert(! b.contains(DummyObject{{150,150,150}})); - - - } - - }; - - } -} - -int main() { - scalfmm::tests::test_Box().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FInOrderNodeIterator.cpp b/Tests/noDist/Adaptive/test_FInOrderNodeIterator.cpp deleted file mode 100644 index 491e91cc2355c8e750d4f2778c4a0a2adf5c1b35..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FInOrderNodeIterator.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#include -#include - -#include "test_Abstract.hpp" -#include "MockParticle.hpp" - -#include "Adaptive/new/FTree.hpp" -#include "Adaptive/new/FNode.hpp" -#include "Adaptive/new/FInOrderNodeIterator.hpp" - -#include "Utils/make_unique.hpp" - -namespace scalfmm { - namespace tests { - struct test_InOrderNodeIterator : public test_Abstract { - - using Real = double; - constexpr static std::size_t Dim = 3; - - using tree_t = FTree >, NodeEmptyData >; - using node_t = typename tree_t::node_t; - using box_t = typename tree_t::box_t; - using iterator_t = FInOrderNodeIterator; - - - tree_t* tree = nullptr; - node_t* root = nullptr; - box_t box {{0,0,0}, 100}; - - - public: - - /** Sets up a tree in which only the root node and its second child - * have children. - * - * 0 ___________________o____ ... - * | | | | - * 1 o ___o____ o o ... - * |||||||| - * 2 oooooooo - */ - void set_up() { - assert(nullptr == tree); - tree = new tree_t(box); - root = tree->root(); - root->split(); - root->getChild(1)->split(); - } - - void tear_down() { - delete tree; - tree = nullptr; - root = nullptr; - } - - void run_all() { - RUN(test_constructor_default); - RUN(test_constructor_custom); - RUN(test_constructor_copy); - RUN(test_constructor_move); - RUN(test_operator_copy); - RUN(test_operator_move); - - RUN(test_prefix_increment); - RUN(test_prefix_decrement); - RUN(test_incr_inverse_decr); - RUN(test_single_node_tree); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_default() { - iterator_t a; - - assert(a._root == nullptr); - assert(a._cur == nullptr); - assert(a._is_end == false); - assert(a._is_rend == false); - } - - void test_constructor_custom() { - iterator_t a(root); - - assert(a._root == root); - assert(a._cur == root->getChild(0)); - assert(a._is_end == false); - assert(a._is_rend == false); - - assert(a._cur_state == decltype(a._cur_state) ({0,-1})); - } - - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_copy () { - iterator_t a(root); - iterator_t b(a); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_move () { - auto a = std::make_unique(root); - iterator_t b(std::move(*a)); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_operator_copy () { - iterator_t a(root); - iterator_t b; - b = a; - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_operator_move () { - auto a = std::make_unique(root); - iterator_t b; - b = std::move(*a); - } - - /** Tests a single node tree */ - void test_single_node_tree() { - tree_t stree(box); - node_t* sroot = stree.root(); - - iterator_t it(sroot); - assert(it.operator->() == sroot); - assert(it._is_end == false); - assert(it._is_rend == false); - ++it; - assert(it._is_end == true); - assert(it._is_rend == false); - --it; - assert(it.operator->() == sroot); - --it; - assert(it._is_end == false); - assert(it._is_rend == true); - ++it; - assert(it.operator->() == sroot); - assert(it._is_end == false); - assert(it._is_rend == false); - } - - /** Walks the tree, checking each step */ - void test_prefix_increment() { - iterator_t it(root); - - assert(root->getChild(0) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(0) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(1) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(2) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(3) == &(*it)); - ++it; - assert(root->getChild(1) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(4) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(5) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(6) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(7) == &(*it)); - ++it; - assert(root->getChild(2) == &(*it)); - ++it; - assert(root->getChild(3) == &(*it)); - ++it; - assert(root == &(*it)); - ++it; - assert(root->getChild(4) == &(*it)); - ++it; - assert(root->getChild(5) == &(*it)); - ++it; - assert(root->getChild(6) == &(*it)); - ++it; - assert(root->getChild(7) == &(*it)); - iterator_t it2(++it); - ++it; - assert(it2 == it); - - assert(it2._is_end == true); - assert(it2._is_rend == false); - } - - /** Moves iterator past the end and plays back the walk */ - void test_prefix_decrement() { - iterator_t it(root); - - for(int i = 0; i < 17; ++i) { - ++it; - } - assert(it._is_end == true); - --it; - assert(it._is_end == false); - - assert(root->getChild(7) == &(*it)); - --it; - assert(root->getChild(6) == &(*it)); - --it; - assert(root->getChild(5) == &(*it)); - --it; - assert(root->getChild(4) == &(*it)); - --it; - assert(root == &(*it)); - --it; - assert(root->getChild(3) == &(*it)); - --it; - assert(root->getChild(2) == &(*it)); - --it; - assert(root->getChild(1)->getChild(7) == &(*it)); - --it; - assert(root->getChild(1)->getChild(6) == &(*it)); - --it; - assert(root->getChild(1)->getChild(5) == &(*it)); - --it; - assert(root->getChild(1)->getChild(4) == &(*it)); - --it; - assert(root->getChild(1) == &(*it)); - --it; - assert(root->getChild(1)->getChild(3) == &(*it)); - --it; - assert(root->getChild(1)->getChild(2) == &(*it)); - --it; - assert(root->getChild(1)->getChild(1) == &(*it)); - --it; - assert(root->getChild(1)->getChild(0) == &(*it)); - --it; - assert(root->getChild(0) == &(*it)); - --it; - assert(it._is_rend == true); - } - - - void test_incr_inverse_decr() { - iterator_t it(root); - - while(! (it)._is_end) { - auto cur = it._cur; - ++it; - auto cur2 = it._cur; - --it; - assert(cur == it._cur); - ++it; - assert(cur2 == it._cur); - } - - while(! (it)._is_rend) { - auto cur = it._cur; - --it; - auto cur2 = it._cur; - ++it; - assert(cur == it._cur); - --it; - assert(cur2 == it._cur); - } - - } - - - }; - } -} - -int main() { - scalfmm::tests::test_InOrderNodeIterator().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FNode.cpp b/Tests/noDist/Adaptive/test_FNode.cpp deleted file mode 100644 index 09be218ff089c8aad9b53eeaa5be27ffa15440c2..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FNode.cpp +++ /dev/null @@ -1,635 +0,0 @@ -#include -#include - -#include - -#include "test_Abstract.hpp" -#include "MockParticle.hpp" - -#include "Adaptive/new/FNode.hpp" - - -namespace scalfmm { - namespace tests { - - struct test_Node : test_Abstract { - - template - struct DummyTree { - constexpr static const std::size_t Dim = _Dim; - using Real = _Real; - using particle_t = MockParticle; - using node_t = FNode, NodeEmptyData >; - using leaf_list_t = std::unordered_set; - using position_t = typename node_t::position_t; - using box_t = typename node_t::box_t; - - box_t _box; - node_t* _root; - leaf_list_t _leaves; - std::size_t _leaf_max_particle_count = 10; - - DummyTree(Real side_length) { - _box.set(_box.c1, position_t()+side_length); - _root = new node_t(this); - } - - ~DummyTree() { - delete _root; - } - - box_t box() const {return _box;} - node_t* root() const {return _root;} - leaf_list_t& leaves() {return _leaves;} - std::size_t max_height() const {return 20;} - std::size_t leaf_max_particle_count() const {return _leaf_max_particle_count;} - friend bool operator==(const DummyTree& t1, const DummyTree& t2) { - return &t1 == &t2; - } - }; - - - - using Real = double; - static constexpr std::size_t Dim = 3; - using tree_t = DummyTree; - using node_t = typename tree_t::node_t; - using box_t = typename tree_t::box_t; - using position_t = typename tree_t::position_t; - using particle_t = typename tree_t::particle_t; - - - static constexpr Real box_side_length = 100; - static constexpr std::size_t particle_count = 1000; - - tree_t* tree; - - std::random_device rd; - std::mt19937 random_generator; - std::uniform_int_distribution random_index; - std::uniform_real_distribution random_real; - - test_Node() : - random_generator(rd()), - random_index(0, Fpow(2,Dim)-1), - random_real(0, box_side_length) - {} - - void set_up() { - tree = new tree_t(box_side_length); - } - - void tear_down() { - delete tree; - } - - void run_all() { - RUN(test_constructor_from_tree); - RUN(test_constructor_from_parent); - RUN(test_getters); - RUN(test_is_adjacent); - RUN(test_in_order_traversal); - RUN(test_post_order_traversal); - RUN(test_pre_order_traversal); - RUN(test_split_simple); - RUN(test_split_max_height); - RUN(test_split_interaction_lists_update); - RUN(test_fuse_interaction_lists_update); - RUN(test_insert); - RUN(test_insert_random); - RUN(test_reshape_fuse); - RUN(test_reshape_split); - } - - - void test_constructor_from_tree() { - assert(tree->root()->getDepth() == 0); - assert(tree->root()->getParent() == nullptr); - assert(tree->root()->getBox() == tree->box()); - assert(tree->root()->getIndex() == 0); - for(auto child : tree->root()->getChildren()) { - assert(child == nullptr); - } - - assert(tree->leaves().size() == 1); - assert(tree->leaves().count(tree->root()) == 1); - - } - - void test_constructor_from_parent() { - try { - node_t* node = new node_t(*(tree->root()), Fpow(2,Dim)+1); - assert(false); - node->getParent(); - } catch(std::invalid_argument& e) { } - - - const node_t* node = new node_t(*(tree->root()), 5); - - box_t b = box_t( tree->box().center(), tree->box().corner(5) ); - - assert(node->getDepth() == 1); - assert(node->getParent() == tree->root()); - assert(node->getBox() == b); - assert(node->getIndex() == 5); - for(auto child : node->getChildren()) { - assert(child == nullptr); - } - - delete node; - } - - void test_getters() { - tree->root()->create_children(); - tree->root()->delete_particle_container(); - node_t* node = tree->root(); - node_t* leaf = tree->root()->getChild(0); - - // Test getters on a leaf - //assert(leaf->data() == NodeEmptyData{}); - assert(leaf->getChildren() == typename node_t::child_node_array_t{{}}); - assert(leaf->getChild(0) == nullptr); - assert(leaf->getParent() == node); - assert(leaf->getDepth() == 1); - assert(leaf->getIndex() == 0); - assert(leaf->getTree() == *tree); - assert(leaf->getBox() == box_t(node->getBox().center(), node->getBox().corner(0))); - assert(leaf->getParticleContainer() != nullptr); - leaf->getParticleContainer()->push_back({{0,0,0}}); - assert(leaf->getParticleCount() == 1); - - - // Test getters on an inner node - //assert(leaf->data() == NodeEmptyData()); - assert(node->getChild(0) == leaf); - assert(node->getChild(0) == leaf); - assert(node->getParent() == nullptr); - assert(node->getDepth() == 0); - assert(node->getIndex() == 0); - assert(node->getTree() == *tree); - assert(node->getBox() == tree->box() ); - assert(node->getParticleContainer() == nullptr); - assert(node->getParticleCount() == 0); - - assert(*(node->getChild(0)) == *leaf); - - } - - void test_is_adjacent() { - // A node is adjacent to itself - node_t* root = tree->root(); - assert( root->is_adjacent(root) ); - assert(! root->is_adjacent(nullptr) ); - - tree->root()->create_children(); - // A node is not adjacent to its children - assert( ! root->is_adjacent(root->getChild(0)) ); - assert( ! root->is_adjacent(root->getChild(1)) ); - assert( ! root->is_adjacent(root->getChild(2)) ); - assert( ! root->is_adjacent(root->getChild(3)) ); - assert( ! root->is_adjacent(root->getChild(4)) ); - assert( ! root->is_adjacent(root->getChild(5)) ); - assert( ! root->is_adjacent(root->getChild(6)) ); - assert( ! root->is_adjacent(root->getChild(7)) ); - - // Sibling nodes are adjacent - auto check_siblings = [](node_t* node, node_t* parent) { - for(std::size_t i = 0; i < node_t::child_count; ++i) { - assert( node->is_adjacent(parent->getChild(0)) ); - } - }; - for(std::size_t i = 0; i < node_t::child_count; ++i) { - node_t* child = tree->root()->getChild(i); - check_siblings(child, tree->root()); - - child->create_children(); - for(std::size_t j = 0; j < node_t::child_count; ++j) { - assert( ! child->is_adjacent(child->getChild(j)) ); - check_siblings(child->getChild(j), child); - } - } - - // Some random checks - auto get_node = [&root](std::vector indexes) { - node_t* node = root; - for(std::size_t p : indexes) - node = node->getChild(p); - return node; - }; - - assert(get_node({0,7})->is_adjacent(get_node({1,0}))); - //TODO: add tests btw nodes that have different parents - } - - - void test_in_order_traversal() { - std::vector> indexes; - std::function lambda = [&](node_t* node) { - indexes.emplace_back(node->getDepth(), node->getIndex()); - }; - - tree->root()->create_children(); - tree->root()->getChild(1)->create_children(); - - tree->root()->for_each_in_order(lambda); - - assert((indexes[ 0] == std::pair(1, 0)) ); - assert((indexes[ 1] == std::pair(2, 8)) ); - assert((indexes[ 2] == std::pair(2, 9)) ); - assert((indexes[ 3] == std::pair(2,10)) ); - assert((indexes[ 4] == std::pair(2,11)) ); - assert((indexes[ 5] == std::pair(1, 1)) ); - assert((indexes[ 6] == std::pair(2,12)) ); - assert((indexes[ 7] == std::pair(2,13)) ); - assert((indexes[ 8] == std::pair(2,14)) ); - assert((indexes[ 9] == std::pair(2,15)) ); - assert((indexes[10] == std::pair(1, 2)) ); - assert((indexes[11] == std::pair(1, 3)) ); - assert((indexes[12] == std::pair(0, 0)) ); - assert((indexes[13] == std::pair(1, 4)) ); - assert((indexes[14] == std::pair(1, 5)) ); - assert((indexes[15] == std::pair(1, 6)) ); - assert((indexes[16] == std::pair(1, 7)) ); - } - - void test_post_order_traversal() { - std::vector> indexes; - std::function lambda = [&](node_t* node) { - indexes.emplace_back(node->getDepth(), node->getIndex()); - }; - - tree->root()->create_children(); - tree->root()->getChild(1)->create_children(); - - tree->root()->for_each_post_order(lambda); - - assert((indexes[ 0] == std::pair(1, 0)) ); - assert((indexes[ 1] == std::pair(2, 8)) ); - assert((indexes[ 2] == std::pair(2, 9)) ); - assert((indexes[ 3] == std::pair(2,10)) ); - assert((indexes[ 4] == std::pair(2,11)) ); - assert((indexes[ 5] == std::pair(2,12)) ); - assert((indexes[ 6] == std::pair(2,13)) ); - assert((indexes[ 7] == std::pair(2,14)) ); - assert((indexes[ 8] == std::pair(2,15)) ); - assert((indexes[ 9] == std::pair(1, 1)) ); - assert((indexes[10] == std::pair(1, 2)) ); - assert((indexes[11] == std::pair(1, 3)) ); - assert((indexes[12] == std::pair(1, 4)) ); - assert((indexes[13] == std::pair(1, 5)) ); - assert((indexes[14] == std::pair(1, 6)) ); - assert((indexes[15] == std::pair(1, 7)) ); - assert((indexes[16] == std::pair(0, 0)) ); - - } - - void test_pre_order_traversal() { - std::vector> indexes; - std::function lambda = [&](node_t* node) { - indexes.emplace_back(node->getDepth(), node->getIndex()); - }; - - tree->root()->create_children(); - tree->root()->getChild(1)->create_children(); - - tree->root()->for_each_pre_order(lambda); - - assert((indexes[ 0] == std::pair(0, 0)) ); - assert((indexes[ 1] == std::pair(1, 0)) ); - assert((indexes[ 2] == std::pair(1, 1)) ); - assert((indexes[ 3] == std::pair(2, 8)) ); - assert((indexes[ 4] == std::pair(2, 9)) ); - assert((indexes[ 5] == std::pair(2,10)) ); - assert((indexes[ 6] == std::pair(2,11)) ); - assert((indexes[ 7] == std::pair(2,12)) ); - assert((indexes[ 8] == std::pair(2,13)) ); - assert((indexes[ 9] == std::pair(2,14)) ); - assert((indexes[10] == std::pair(2,15)) ); - assert((indexes[11] == std::pair(1, 2)) ); - assert((indexes[12] == std::pair(1, 3)) ); - assert((indexes[13] == std::pair(1, 4)) ); - assert((indexes[14] == std::pair(1, 5)) ); - assert((indexes[15] == std::pair(1, 6)) ); - assert((indexes[16] == std::pair(1, 7)) ); - - } - - - struct interaction_list_struct { - using interaction_list_t = typename node_t::interaction_list_t; - interaction_list_t U; - interaction_list_t V; - interaction_list_t W; - interaction_list_t X; - - interaction_list_struct(tree_t* tree, node_t* node) { - tree->root()->for_each_in_order([&](node_t* n) { - if(n == node && n->is_leaf()) { - this->U.insert(n); - return; - } - - if(node->is_leaf()) { - if(n->is_leaf() && n->is_adjacent(node)) { - this->U.insert(n); - } - if(n->getParent() && node->is_adjacent(n->getParent()) - && ! node->is_adjacent(n) - && node->getDepth() < n->getDepth() ) { - this->W.insert(n); - } - } - - if(n->getDepth() == node->getDepth()) { - if(node->getParent() - && n->getParent() - && ! node->is_adjacent(n) - && n->getParent() != node->getParent() - && node->getParent()->is_adjacent(n->getParent())) { - this->V.insert(n); - } - } - - if(n->is_leaf()) { - if(node->getParent() - && n->is_adjacent(node->getParent()) - && ! n->is_adjacent(node) - && n->getDepth() < node->getDepth()) { - this->X.insert(n); - } - } - }); - } - }; - - void test_split_simple() { - // Split the root - tree->root()->split(); - // The root is no longer a leaf - assert(! tree->root()->is_leaf()); - // The root's children have been created - assert(tree->root()->getChild(0) != nullptr); - assert(tree->root()->getChild(1) != nullptr); - assert(tree->root()->getChild(2) != nullptr); - assert(tree->root()->getChild(3) != nullptr); - assert(tree->root()->getChild(4) != nullptr); - assert(tree->root()->getChild(5) != nullptr); - assert(tree->root()->getChild(6) != nullptr); - assert(tree->root()->getChild(7) != nullptr); - // Tree leaf list update : each child must be in the list once - assert(tree->leaves().count(tree->root()) == 0); - assert(tree->leaves().count(tree->root()->getChild(0)) == 1); - assert(tree->leaves().count(tree->root()->getChild(1)) == 1); - assert(tree->leaves().count(tree->root()->getChild(2)) == 1); - assert(tree->leaves().count(tree->root()->getChild(3)) == 1); - assert(tree->leaves().count(tree->root()->getChild(4)) == 1); - assert(tree->leaves().count(tree->root()->getChild(5)) == 1); - assert(tree->leaves().count(tree->root()->getChild(6)) == 1); - assert(tree->leaves().count(tree->root()->getChild(7)) == 1); - // Split a child - node_t* node = tree->root()->getChild(1); - node->split(); - // Node is no longer a leaf - assert(! node->is_leaf()); - // Check that the node's children have been added to the leaf list - assert(tree->leaves().count(node) == 0); - assert(tree->leaves().count(node->getChild(0)) == 1); - assert(tree->leaves().count(node->getChild(1)) == 1); - assert(tree->leaves().count(node->getChild(2)) == 1); - assert(tree->leaves().count(node->getChild(3)) == 1); - assert(tree->leaves().count(node->getChild(4)) == 1); - assert(tree->leaves().count(node->getChild(5)) == 1); - assert(tree->leaves().count(node->getChild(6)) == 1); - assert(tree->leaves().count(node->getChild(7)) == 1); - // other leaves are still in the list - assert(tree->leaves().count(tree->root()->getChild(0)) == 1); - assert(tree->leaves().count(tree->root()->getChild(2)) == 1); - assert(tree->leaves().count(tree->root()->getChild(3)) == 1); - assert(tree->leaves().count(tree->root()->getChild(4)) == 1); - assert(tree->leaves().count(tree->root()->getChild(5)) == 1); - assert(tree->leaves().count(tree->root()->getChild(6)) == 1); - assert(tree->leaves().count(tree->root()->getChild(7)) == 1); - } - - void test_split_max_height() { - node_t* node = tree->root(); - std::size_t i; - // Check that the split limit works - for(i = 0; i < tree->max_height() && node != nullptr; ++i) { - node->split(); - node = node->getChild(1); - } - - assert(node != nullptr); - assert(node->getDepth() == tree->max_height()); - - node->split(); - for(auto c : node->getChildren()) { - assert(c == nullptr); - } - - } - - std::size_t random_child_index() { - return random_index(random_generator); - } - - void setup_random_tree(const std::size_t& split_count) { - // Randomly split N leaves - for(std::size_t i = 0; i < split_count; ++i) { - node_t* node = tree->root(); - // Follow random path until we hit a leaf - while( ! node->is_leaf()) { - node = node->getChild(random_child_index()); - } - node->split(); - } - } - - - - void test_split_interaction_lists_update() { - setup_random_tree(20); - - tree->root()->for_each_in_order([&](node_t* node) { - interaction_list_struct lists(tree, node); - assert(node->U == lists.U); - assert(node->V == lists.V); - assert(node->W == lists.W); - assert(node->X == lists.X); - }); - } - - void test_fuse_interaction_lists_update() { - setup_random_tree(10); - - while(! tree->root()->is_leaf()) { - node_t* cursor = tree->root(); - while(! cursor->is_leaf()) { - cursor = cursor->getChild(random_child_index()); - } - - cursor->getParent()->fuse(); - - tree->root()->for_each_in_order([&](node_t* node) { - interaction_list_struct lists(tree, node); - assert(node->U == lists.U); - assert(node->V == lists.V); - assert(node->W == lists.W); - assert(node->X == lists.X); - }); - } - } - - position_t random_position() { - position_t p; - for(auto&& i : p) - i = random_real(random_generator); - return p; - } - - void test_insert() { - tree->_leaf_max_particle_count = 2; - - node_t* root = tree->root(); - - root->insert({{24, 24, 24},1}); // goes in first child - root->insert({{76, 76, 76},2}); // goes in last child - root->insert({{26, 30, 74},3}); // goes in second child - - // _leaf_max_particle_count is exceeded, the node should have split - - assert(! root->is_leaf()); - assert(root->getChild(0)->is_leaf()); - assert(root->getChild(1)->is_leaf()); - assert(root->getChild(2)->is_leaf()); - assert(root->getChild(3)->is_leaf()); - assert(root->getChild(4)->is_leaf()); - assert(root->getChild(5)->is_leaf()); - assert(root->getChild(6)->is_leaf()); - assert(root->getChild(7)->is_leaf()); - - std::size_t particle_count = 0; - for(auto child : root->getChildren()) { - for(auto&& particle : *(child->getParticleContainer())) { - assert(child->getBox().contains(particle)); - ++particle_count; - } - } - - assert(particle_count == 3); - - } - - - void test_insert_random() { - std::vector particle_list; - particle_list.reserve(particle_count); - - for(std::size_t i = 0; i < particle_count; ++i) { - particle_list.push_back(particle_t{random_position(), i}); - tree->root()->insert(particle_list.back()); - } - - std::size_t particle_counter = 0; - - tree->root()->for_each_in_order([&](node_t* node) { - if(! node->is_leaf()) { - assert(node->getParticleContainer() == nullptr); - } else { - for(auto&& p : *(node->getParticleContainer())) { - ++particle_counter; - assert(node->getBox().contains(p.position())); - } - } - }); - - assert(particle_count == particle_counter); - } - - - void test_reshape_fuse() { - // Set max particle count - tree->_leaf_max_particle_count = 8; - // Insert exactly max particle count particles - tree->root()->insert({{12.5,12.5,12.5}}); - tree->root()->insert({{12.5,12.5,37.5}}); - tree->root()->insert({{12.5,37.5,12.5}}); - tree->root()->insert({{12.5,37.5,37.5}}); - tree->root()->insert({{37.5,12.5,12.5}}); - tree->root()->insert({{37.5,12.5,37.5}}); - tree->root()->insert({{37.5,37.5,12.5}}); - tree->root()->insert({{37.5,37.5,37.5}}); - // Check that root has not yet been divided - assert(tree->root()->is_leaf()); - // Add one more particle - tree->root()->insert({{12.5,12.5,62.5}}); - // Check that root has been divided - assert(! tree->root()->is_leaf()); - // Add particles until 2*max_particle_count - tree->root()->insert({{12.5,12.5,87.5}}); - tree->root()->insert({{12.5,37.5,62.5}}); - tree->root()->insert({{12.5,37.5,87.5}}); - tree->root()->insert({{37.5,12.5,62.5}}); - tree->root()->insert({{37.5,12.5,87.5}}); - tree->root()->insert({{37.5,37.5,62.5}}); - tree->root()->insert({{37.5,37.5,87.5}}); - - // Remove max_particle_count particles - std::size_t i = 0; - for(node_t* leaf : tree->leaves()) { - while(leaf->getParticleCount() > tree->_leaf_max_particle_count / 2) { - leaf->extract(0); - if(++i >= tree->_leaf_max_particle_count) { - break; - } - } - } - - tree->root()->reshape(); - - assert(tree->root()->is_leaf()); - } - - void test_reshape_split() { - // Set max particle count - tree->_leaf_max_particle_count = 8; - // Insert exactly max particle count particles - tree->root()->getParticleContainer()->push_back({{12.5,12.5,12.5}}); - tree->root()->getParticleContainer()->push_back({{12.5,12.5,37.5}}); - tree->root()->getParticleContainer()->push_back({{12.5,37.5,12.5}}); - tree->root()->getParticleContainer()->push_back({{12.5,37.5,37.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,12.5,12.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,12.5,37.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,37.5,12.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,37.5,37.5}}); - - assert(tree->root()->is_leaf()); - tree->root()->reshape(); - assert(tree->root()->is_leaf()); - - // Insert max particle count particles again - tree->root()->getParticleContainer()->push_back({{12.5,12.5,62.5}}); - tree->root()->getParticleContainer()->push_back({{12.5,12.5,87.5}}); - tree->root()->getParticleContainer()->push_back({{12.5,37.5,62.5}}); - tree->root()->getParticleContainer()->push_back({{12.5,37.5,87.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,12.5,62.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,12.5,87.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,37.5,62.5}}); - tree->root()->getParticleContainer()->push_back({{37.5,37.5,87.5}}); - // Check that root has not yet been divided - assert(tree->root()->is_leaf()); - // Reshape tree - tree->root()->reshape(); - // Root shouldn't be a leaf anymore - assert(! tree->root()->is_leaf()); - } - - }; - } -} - - -int main() { - scalfmm::tests::test_Node().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FNodeIterator.cpp b/Tests/noDist/Adaptive/test_FNodeIterator.cpp deleted file mode 100644 index 5af464db2cec0fc6ba0f47bdd94a2366fed8f23f..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FNodeIterator.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include - -#include "test_Abstract.hpp" -#include "MockParticle.hpp" - -#include "Adaptive/new/FTree.hpp" -#include "Adaptive/new/FNode.hpp" -#include "Adaptive/new/FNodeIterator.hpp" - -#include "Utils/make_unique.hpp" - -namespace scalfmm { - namespace tests { - - struct test_NodeIterator : public test_Abstract { - - using Real = double; - constexpr static std::size_t Dim = 3; - - using tree_t = FTree >, NodeEmptyData >; - using node_t = typename tree_t::node_t; - using box_t = typename tree_t::box_t; - - struct test_iterator : public FNodeIterator { - using base_t = FNodeIterator; - - int pp = 0; - int mm = 0; - - using base_t::base_t; - using base_t::operator++; - using base_t::operator--; - - template void move_to_boundary() {} - test_iterator& operator++(){++pp; return *this;} - test_iterator& operator--(){++mm; return *this;} - }; - - tree_t* tree = nullptr; - node_t* root = nullptr; - box_t box {{0,0,0}, 100}; - - - public: - - void set_up() { - assert(nullptr == tree); - tree = new tree_t(box); - root = tree->root(); // Allocated by tree constructor - } - - void tear_down() { - delete tree; - tree = nullptr; - root = nullptr; // Deleted by tree destructor - } - - void run_all() { - RUN(test_constructor_default); - RUN(test_constructor_custom); - RUN(test_constructor_copy); - RUN(test_constructor_move); - RUN(test_operator_copy); - RUN(test_operator_move); - RUN(test_operator_dereference); - RUN(test_increment_postfix); - RUN(test_decrement_postfix); - } - - void test_constructor_default() { - test_iterator a; - assert(a._root == nullptr); - assert(a._cur == nullptr); - assert(a._is_end == false); - assert(a._is_rend == false); - } - - void test_constructor_custom() { - test_iterator a(root); - - assert(a._root == root); - assert(a._is_end == false); - assert(a._is_rend == false); - } - - void test_constructor_copy() { - test_iterator a(root); - a._is_end = true; - a._is_rend = true; - test_iterator b(a); - - assert(a._root == b._root ); - assert(a._cur == b._cur ); - assert(a._is_end == b._is_end ); - assert(a._is_rend == b._is_rend ); - assert(a._cur_state == b._cur_state); - } - - void test_constructor_move() { - auto a = std::make_unique(root); - a->_is_end = true; - a->_is_rend = true; - - auto _root = a->_root; - auto _cur = a->_cur; - auto _cur_state = a->_cur_state; - auto _is_end = a->_is_end; - auto _is_rend = a->_is_rend; - - test_iterator b(std::move(*a)); - - assert(_root == b._root ); - assert(_cur == b._cur ); - assert(_is_end == b._is_end ); - assert(_is_rend == b._is_rend ); - assert(_cur_state == b._cur_state); - } - - void test_operator_copy() { - test_iterator a(root); - a._is_end = true; - a._is_rend = true; - test_iterator b; - b = a; - - assert(a._root == b._root ); - assert(a._cur == b._cur ); - assert(a._is_end == b._is_end ); - assert(a._is_rend == b._is_rend ); - assert(a._cur_state == b._cur_state); - } - - void test_operator_move() { - auto a = std::make_unique(root); - a->_is_end = true; - a->_is_rend = true; - - auto _root = a->_root; - auto _cur = a->_cur; - auto _cur_state = a->_cur_state; - auto _is_end = a->_is_end; - auto _is_rend = a->_is_rend; - - test_iterator b; - b = std::move(*a); - - assert(_root == b._root ); - assert(_cur == b._cur ); - assert(_is_end == b._is_end ); - assert(_is_rend == b._is_rend ); - assert(_cur_state == b._cur_state); - } - - void test_operator_dereference() { - test_iterator a(root); - a._cur = root; - assert(&(*a) == root); - - const test_iterator b(a); - assert(&(*b) == root); - - auto c = std::make_unique(a); - assert(&((*c)->getTree()) == tree); - - auto d = std::make_unique(a); - assert(&((*d)->getTree()) == tree); - } - - void test_increment_postfix() { - test_iterator a(root); - int plus = (a++).pp; - assert(plus == 0); - assert(a.pp == 1); - } - - void test_decrement_postfix() { - test_iterator a(root); - int minus = (a--).mm; - assert(minus == 0); - assert(a.mm == 1); - } - - - }; - } -} - - -int main() { - scalfmm::tests::test_NodeIterator().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FPostOrderNodeIterator.cpp b/Tests/noDist/Adaptive/test_FPostOrderNodeIterator.cpp deleted file mode 100644 index 0a7c377230fedbc7b6c78ad40c1ceb9140d7c25b..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FPostOrderNodeIterator.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include -#include - -#include "test_Abstract.hpp" -#include "MockParticle.hpp" - -#include "Adaptive/new/FTree.hpp" -#include "Adaptive/new/FNode.hpp" -#include "Adaptive/new/FPrePostOrderNodeIterator.hpp" - -#include "Utils/make_unique.hpp" - -namespace scalfmm { - namespace tests { - struct test_PostOrderNodeIterator : public test_Abstract { - - using Real = double; - constexpr static std::size_t Dim = 3; - - using tree_t = FTree >, NodeEmptyData >; - using node_t = typename tree_t::node_t; - using box_t = typename tree_t::box_t; - using iterator_t = FPostOrderNodeIterator; - - - tree_t* tree = nullptr; - node_t* root = nullptr; - box_t box {{0,0,0}, 100}; - - - public: - - /** Sets up a tree in which only the root node and its second child - * have children. - * - * 0 ___________________o____ ... - * | | | | - * 1 o ___o____ o o ... - * |||||||| - * 2 oooooooo - */ - void set_up() { - assert(nullptr == tree); - tree = new tree_t(box); - root = tree->root(); - root->split(); - root->getChild(1)->split(); - } - - void tear_down() { - delete tree; - tree = nullptr; - } - - void run_all() { - RUN(test_constructor_default); - RUN(test_constructor_custom); - RUN(test_constructor_copy); - RUN(test_constructor_move); - RUN(test_operator_copy); - RUN(test_operator_move); - - RUN(test_prefix_increment); - RUN(test_prefix_decrement); - RUN(test_incr_inverse_decr); - RUN(test_single_node_tree); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_default() { - iterator_t a; - - assert(a._root == nullptr); - assert(a._cur == nullptr); - assert(a._is_end == false); - assert(a._is_rend == false); - } - - void test_constructor_custom() { - iterator_t a(root); - - assert(a._root == root); - assert(a._cur == root->getChild(0)); - assert(a._is_end == false); - assert(a._is_rend == false); - - //assert(a._cur_state == decltype(a._cur_state) ({-1})); - } - - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_copy () { - iterator_t a(root); - iterator_t b(a); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_move () { - auto a = std::make_unique(root); - iterator_t b(std::move(*a)); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_operator_copy () { - iterator_t a(root); - iterator_t b; - b = a; - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_operator_move () { - auto a = std::make_unique(root); - iterator_t b; - b = std::move(*a); - } - - /** Tests a single node tree */ - void test_single_node_tree() { - tree_t stree(box); - node_t* sroot = stree.root(); - - iterator_t it(sroot); - assert(it.operator->() == sroot); - assert(it._is_end == false); - assert(it._is_rend == false); - ++it; - assert(it._is_end == true); - assert(it._is_rend == false); - --it; - assert(it.operator->() == sroot); - --it; - assert(it._is_end == false); - assert(it._is_rend == true); - ++it; - assert(it.operator->() == sroot); - assert(it._is_end == false); - assert(it._is_rend == false); - } - - /** Walks the tree, checking each step */ - void test_prefix_increment() { - iterator_t it(root); - - assert(root->getChild(0) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(0) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(1) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(2) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(3) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(4) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(5) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(6) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(7) == &(*it)); - ++it; - assert(root->getChild(1) == &(*it)); - ++it; - assert(root->getChild(2) == &(*it)); - ++it; - assert(root->getChild(3) == &(*it)); - ++it; - assert(root->getChild(4) == &(*it)); - ++it; - assert(root->getChild(5) == &(*it)); - ++it; - assert(root->getChild(6) == &(*it)); - ++it; - assert(root->getChild(7) == &(*it)); - ++it; - assert(root == &(*it)); - iterator_t it2(++it); - ++it; - assert(it2 == it); - - assert(it2._is_end == true); - assert(it2._is_rend == false); - } - - /** Moves iterator past the end and plays back the walk */ - void test_prefix_decrement() { - iterator_t it(root); - - for(int i = 0; i < 17; ++i) { - ++it; - } - assert(it._is_end == true); - --it; - assert(it._is_end == false); - - assert(root == &(*it)); - --it; - assert(root->getChild(7) == &(*it)); - --it; - assert(root->getChild(6) == &(*it)); - --it; - assert(root->getChild(5) == &(*it)); - --it; - assert(root->getChild(4) == &(*it)); - --it; - assert(root->getChild(3) == &(*it)); - --it; - assert(root->getChild(2) == &(*it)); - --it; - assert(root->getChild(1) == &(*it)); - --it; - assert(root->getChild(1)->getChild(7) == &(*it)); - --it; - assert(root->getChild(1)->getChild(6) == &(*it)); - --it; - assert(root->getChild(1)->getChild(5) == &(*it)); - --it; - assert(root->getChild(1)->getChild(4) == &(*it)); - --it; - assert(root->getChild(1)->getChild(3) == &(*it)); - --it; - assert(root->getChild(1)->getChild(2) == &(*it)); - --it; - assert(root->getChild(1)->getChild(1) == &(*it)); - --it; - assert(root->getChild(1)->getChild(0) == &(*it)); - --it; - assert(root->getChild(0) == &(*it)); - --it; - assert(it._is_rend == true); - } - - void print(iterator_t it) { - int i = 0; - while(! it._is_end) { - std::cout << i++ << " " << (it++)._cur << std::endl; - } - } - - void test_incr_inverse_decr() { - iterator_t it(root); - - while(! (it)._is_end) { - auto cur = it._cur; - ++it; - auto cur2 = it._cur; - --it; - assert(cur == it._cur); - ++it; - assert(cur2 == it._cur); - } - - while(! (it)._is_rend) { - auto cur = it._cur; - --it; - auto cur2 = it._cur; - ++it; - assert(cur == it._cur); - --it; - assert(cur2 == it._cur); - } - - } - - - }; - } -} - -int main() { - scalfmm::tests::test_PostOrderNodeIterator().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FPreOrderNodeIterator.cpp b/Tests/noDist/Adaptive/test_FPreOrderNodeIterator.cpp deleted file mode 100644 index b8cae24e8ea81e7750179c461ac19b955b748847..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FPreOrderNodeIterator.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include -#include - -#include "test_Abstract.hpp" -#include "MockParticle.hpp" - -#include "Adaptive/new/FTree.hpp" -#include "Adaptive/new/FNode.hpp" -#include "Adaptive/new/FPrePostOrderNodeIterator.hpp" - -#include "Utils/make_unique.hpp" - -namespace scalfmm { - namespace tests { - struct test_PreOrderNodeIterator : public test_Abstract { - - using Real = double; - constexpr static std::size_t Dim = 3; - - using tree_t = FTree >, NodeEmptyData >; - using node_t = typename tree_t::node_t; - using box_t = typename tree_t::box_t; - using iterator_t = FPreOrderNodeIterator; - - - tree_t* tree = nullptr; - node_t* root = nullptr; - box_t box {{0,0,0}, 100}; - - - public: - - /** Sets up a tree in which only the root node and its second child - * have children. - * - * 0 ___________________o____ ... - * | | | | - * 1 o ___o____ o o ... - * |||||||| - * 2 oooooooo - */ - void set_up() { - assert(nullptr == tree); - tree = new tree_t(box); - root = tree->root(); - root->split(); - root->getChild(1)->split(); - } - - void tear_down() { - delete tree; - tree = nullptr; - } - - void run_all() { - RUN(test_constructor_default); - RUN(test_constructor_custom); - RUN(test_constructor_copy); - RUN(test_constructor_move); - RUN(test_operator_copy); - RUN(test_operator_move); - - RUN(test_prefix_increment); - RUN(test_prefix_decrement); - RUN(test_incr_inverse_decr); - RUN(test_single_node_tree); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_default() { - iterator_t a; - - assert(a._root == nullptr); - assert(a._cur == nullptr); - assert(a._is_end == false); - assert(a._is_rend == false); - } - - void test_constructor_custom() { - iterator_t a(root); - - assert(a._root == root); - assert(a._cur == root); - assert(a._is_end == false); - assert(a._is_rend == false); - - assert(a._cur_state == decltype(a._cur_state) ({-1})); - } - - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_copy () { - iterator_t a(root); - iterator_t b(a); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_constructor_move () { - auto a = std::make_unique(root); - iterator_t b(std::move(*a)); - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_operator_copy () { - iterator_t a(root); - iterator_t b; - b = a; - } - - /** Tested for NodeIterator, testing that it is correctly accessible */ - void test_operator_move () { - auto a = std::make_unique(root); - iterator_t b; - b = std::move(*a); - } - - /** Tests a single node tree */ - void test_single_node_tree() { - tree_t stree(box); - node_t* sroot = stree.root(); - - iterator_t it(sroot); - assert(it.operator->() == sroot); - assert(it._is_end == false); - assert(it._is_rend == false); - ++it; - assert(it._is_end == true); - assert(it._is_rend == false); - --it; - assert(it.operator->() == sroot); - --it; - assert(it._is_end == false); - assert(it._is_rend == true); - ++it; - assert(it.operator->() == sroot); - assert(it._is_end == false); - assert(it._is_rend == false); - } - - /** Walks the tree, checking each step */ - void test_prefix_increment() { - iterator_t it(root); - - assert(root == &(*it)); - ++it; - assert(root->getChild(0) == &(*it)); - ++it; - assert(root->getChild(1) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(0) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(1) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(2) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(3) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(4) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(5) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(6) == &(*it)); - ++it; - assert(root->getChild(1)->getChild(7) == &(*it)); - ++it; - assert(root->getChild(2) == &(*it)); - ++it; - assert(root->getChild(3) == &(*it)); - ++it; - assert(root->getChild(4) == &(*it)); - ++it; - assert(root->getChild(5) == &(*it)); - ++it; - assert(root->getChild(6) == &(*it)); - ++it; - assert(root->getChild(7) == &(*it)); - iterator_t it2(++it); - ++it; - assert(it2 == it); - - assert(it2._is_end == true); - assert(it2._is_rend == false); - } - - /** Moves iterator past the end and plays back the walk */ - void test_prefix_decrement() { - iterator_t it(root); - - for(int i = 0; i < 17; ++i) { - ++it; - } - assert(it._is_end == true); - --it; - assert(it._is_end == false); - - assert(root->getChild(7) == &(*it)); - --it; - assert(root->getChild(6) == &(*it)); - --it; - assert(root->getChild(5) == &(*it)); - --it; - assert(root->getChild(4) == &(*it)); - --it; - assert(root->getChild(3) == &(*it)); - --it; - assert(root->getChild(2) == &(*it)); - --it; - assert(root->getChild(1)->getChild(7) == &(*it)); - --it; - assert(root->getChild(1)->getChild(6) == &(*it)); - --it; - assert(root->getChild(1)->getChild(5) == &(*it)); - --it; - assert(root->getChild(1)->getChild(4) == &(*it)); - --it; - assert(root->getChild(1)->getChild(3) == &(*it)); - --it; - assert(root->getChild(1)->getChild(2) == &(*it)); - --it; - assert(root->getChild(1)->getChild(1) == &(*it)); - --it; - assert(root->getChild(1)->getChild(0) == &(*it)); - --it; - assert(root->getChild(1) == &(*it)); - --it; - assert(root->getChild(0) == &(*it)); - --it; - assert(root == &(*it)); - --it; - assert(it._is_rend == true); - } - - void print(iterator_t it) { - int i = 0; - while(! it._is_end) { - std::cout << i++ << " " << (it++)._cur << std::endl; - } - } - - void test_incr_inverse_decr() { - iterator_t it(root); - - while(! (it)._is_end) { - auto cur = it._cur; - ++it; - auto cur2 = it._cur; - --it; - assert(cur == it._cur); - ++it; - assert(cur2 == it._cur); - } - - while(! (it)._is_rend) { - auto cur = it._cur; - --it; - auto cur2 = it._cur; - ++it; - assert(cur == it._cur); - --it; - assert(cur2 == it._cur); - } - - } - - - }; - } -} - -int main() { - scalfmm::tests::test_PreOrderNodeIterator().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FTree.cpp b/Tests/noDist/Adaptive/test_FTree.cpp deleted file mode 100644 index 600bed5bb48a6a93f8158aa63c85d8658a06370f..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FTree.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include - -#include "test_Abstract.hpp" -#include "MockParticle.hpp" - -#include "Adaptive/new/FNode.hpp" -#include "Adaptive/new/FTree.hpp" - -#define BOX_SIDE_LEN 100 - - -namespace scalfmm { - namespace tests { - - class test_Tree : public test_Abstract { - - using Real = double; - constexpr static std::size_t Dim = 3; - using particle_t = MockParticle; - using particle_container_t = std::vector; - using tree_t = FTree; - using node_t = typename tree_t::node_t; - using box_t = typename tree_t::box_t; - using position_t = typename box_t::position_t; - - box_t box {position_t(), 100}; - tree_t* tree = nullptr; - - public: - void run_all() { - RUN(test_constructor); - RUN(test_swap); - RUN(test_constructor_move); - } - - void set_up() { - assert(tree == nullptr); - - this->tree = new tree_t(box); - } - - void tear_down() { - delete this->tree; - this->tree = nullptr; - } - - void test_constructor() { - assert(tree->root() != nullptr); - } - - void test_swap() { - box_t t_box = {position_t(), 50}; - tree_t t(t_box); - - auto root = tree->root(); - auto t_root = t.root(); - - auto leaves = tree->leaves(); - auto t_leaves = t.leaves(); - - auto max_height = tree->max_height(); - auto t_max_height = t.max_height(); - - auto leaf_max_particle_count = tree->leaf_max_particle_count(); - auto t_leaf_max_particle_count = t.leaf_max_particle_count(); - - t.swap(*tree); - - assert(tree->box() == t_box); - assert(tree->root() == t_root); - assert(tree->leaves() == t_leaves); - assert(tree->max_height() == t_max_height); - assert(tree->leaf_max_particle_count() == t_leaf_max_particle_count); - assert(&(tree->root()->getTree()) == tree); - - assert(t.box() == box); - assert(t.root() == root); - assert(t.leaves() == leaves); - assert(t.max_height() == max_height); - assert(t.leaf_max_particle_count() == leaf_max_particle_count); - assert(&(t.root()->getTree()) == &t); - } - - void test_constructor_move() { - auto root = tree->root(); - auto leaves = tree->leaves(); - auto max_height = tree->max_height(); - auto leaf_max_particle_count = tree->leaf_max_particle_count(); - - tree_t t(std::move(*tree)); - - assert(t.box() == box ); - assert(t.root() == root ); - assert(t.leaves() == leaves ); - assert(t.max_height() == max_height); - assert(t.leaf_max_particle_count() == leaf_max_particle_count); - - tree_t s {tree_t(box)}; - } - - }; - } -} - - -int main() { - scalfmm::tests::test_Tree().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_FZCurve.cpp b/Tests/noDist/Adaptive/test_FZCurve.cpp deleted file mode 100644 index 60e4627764a5e93c5d831b40d2e9bb8f96eb8453..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_FZCurve.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include "test_Abstract.hpp" - -#include "Utils/FConstFuncs.hpp" -#include "Adaptive/new/FZCurve.hpp" - -namespace scalfmm { - namespace tests { - - - struct test_ZCurve : public test_Abstract { - using Real = double; - constexpr static const std::size_t Dim = 3; - constexpr static const std::size_t pos_count = FZCurve::pos_count; - using boolpos_t = FZCurve::position_t; - using position_t = FPoint; - - void run_all() { - RUN(test_curve_1); - RUN(test_curve_2); - } - - - // Tests that the position and index functions are the inverse of each other - void test_curve_1 () { - FZCurve indexer; - - std::array pos; - - //std::cout << std::endl; - for(std::size_t i = 0; i < pos_count; ++i) { - pos[i] = indexer.position(i); - std::size_t j = indexer.index(pos[i]); - //std::cout << i << pos[i] << j << std::endl; - assert(i == j); - } - } - - // Tests that the position and index 2 overload functions are the inverse of each other - void test_curve_2 () { - FZCurve indexer; - position_t center = {50,50,50}; - std::array pos; - for(std::size_t i = 0; i < pos_count; ++i) { - pos[i] = position_t(indexer.position(i)) * 75; - std::size_t j = indexer.index(pos[i], center); - assert(i == j); - } - } - - }; - - } -} - -int main() { - scalfmm::tests::test_ZCurve().run_all(); -} diff --git a/Tests/noDist/Adaptive/test_Position.cpp b/Tests/noDist/Adaptive/test_Position.cpp deleted file mode 100644 index d57865a83eef673babc0cfadd680e1929829d860..0000000000000000000000000000000000000000 --- a/Tests/noDist/Adaptive/test_Position.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include - -#include "test_Abstract.hpp" - -#include "Utils/FPoint.hpp" -#include "Utils/FConstFuncs.hpp" - -namespace scalfmm { - namespace tests { - - using Real = double; - constexpr const size_t Dim = 3; - using position = FPoint; - - - struct test_Position : public test_Abstract { - - void run_all() { - RUN(test_constructor_default ); - RUN(test_constructor_arguments ); - RUN(test_constructor_copy ); - RUN(test_constructor_move ); - RUN(test_operator_assignment_copy ); - RUN(test_operator_assignment_move ); - RUN(test_operator_equal_int); - RUN(test_operator_equal_float); - RUN(test_operator_plus ); - RUN(test_operator_mult ); - RUN(test_iterators ); - } - - void test_constructor_default() { - position a; - for(Real& i : a) { - assert(Ffeq(i, 0)); - } - } - - void test_constructor_arguments() { - position b(0.1, 0.2, 0.3); - assert(Ffeq(b[0], 0.1)); - assert(Ffeq(b[1], 0.2)); - assert(Ffeq(b[2], 0.3)); - } - - void test_constructor_copy() { - position b(0.1, 0.2, 0.3); - position c(b); - assert(Ffeq(b[0], c[0])); - assert(Ffeq(b[1], c[1])); - assert(Ffeq(b[2], c[2])); - - c[0] = b[0]+1; - assert(! Ffeq(b[0], c[0])); - } - - void test_constructor_move() { - position a(position(0.1, 0.2, 0.3)); - assert(Ffeq(a[0], 0.1)); - assert(Ffeq(a[1], 0.2)); - assert(Ffeq(a[2], 0.3)); - } - - void test_operator_assignment_copy() { - position a, b(0.1, 0.5, 28.33); - a = b; - assert(Ffeq(b[0], a[0])); - assert(Ffeq(b[1], a[1])); - assert(Ffeq(b[2], a[2])); - - a[0] = b[0] + 1; - assert(! Ffeq(b[0], a[0])); - } - - void test_operator_assignment_move() { - position a, b(0.1, 0.5, 28.33); - a = std::move(b); - - assert(Ffeq(b[0], a[0])); - assert(Ffeq(b[1], a[1])); - assert(Ffeq(b[2], a[2])); - } - - void test_operator_equal_int() { - FPoint a (1, 2, 3); - FPoint b (1, 2, 3); - FPoint c (1, 1, 0); - FPoint d (0, 1, 3); - - assert(a == b); - assert(b == a); - assert(a != c); - assert(c != a); - assert(a != d); - assert(d != a); - } - - void test_operator_equal_float() { - position a (0.1, 0.2, 0.3); - position b (0.1, 0.2, 0.3); - position c (0.1, 0.1, 0); - position d (0, 0.1, 0.3); - - assert(a == b); - assert(b == a); - assert(a != c); - assert(c != a); - assert(a != d); - assert(d != a); - } - - void test_operator_plus() { - position a(0.1, 0.2, 0.3); - position b(0.5, 0.6, 0.7); - - position c = a + b; - position d; - d = a + b; - position e = d - b; - - assert(c == a + b); - assert(d == a + b); - - assert(a == d - b); - assert(a == e); - - position f = a + position(1,2,3); - assert(a != f); - f -= position(1,2,3); - assert(a == f); - - position g(a); - g = position(1,0,0); - assert(a != g); - } - - void test_operator_mult() { - const int mul = 3; - position a (1,2,3); - position b (a[0]*mul, a[1]*mul, a[2]*mul); - - position c = a * mul; - position d = mul * a; - - assert(b == c); - assert(b == d); - assert(mul * a == b); - - position e = c / mul; - assert(a == e); - - } - - void test_iterators() { - position a(0.1, 0.2, 0.3); - int i = 0; - for(auto z : a) { - (void)z; - i++; - } - assert(i == 3); - - i = 0; - for(auto z = a.rbegin(); z != a.rend(); ++z) { - i++; - } - assert(i == 3); - } - }; - - } -} - - -int main() { - scalfmm::tests::test_Position().run_all(); -} diff --git a/Tests/noDist/ChebyshevPeriodic.cpp b/Tests/noDist/ChebyshevPeriodic.cpp index 58425bb91554795e28c847fd014f2832deff99c9..d1babc715d7b083940d0e7c9c5b4b3ed714cbcf6 100644 --- a/Tests/noDist/ChebyshevPeriodic.cpp +++ b/Tests/noDist/ChebyshevPeriodic.cpp @@ -83,12 +83,6 @@ int main(int argc, char* argv[]) const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); const int PeriodicDeep = FParameters::getValue(argc,argv,FParameterDefinitions::PeriodicityNbLevels.options, 3); -#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 << "\t Octree Depth \t"<< TreeHeight <> Sequential version.\n" << std:: -#endif std::cout << "Parameters "<< std::endl << " Octree Depth \t"<< TreeHeight < -#include - -#include "Utils/FParameters.hpp" -#include "Utils/FParameterNames.hpp" - -#include "PerfTest/PerfTestUtils.hpp" - -#include "PerfTest/TreeLoaderBasic.hpp" -#include "PerfTest/TreeLoaderFCheb.hpp" - -#ifdef SCALFMM_USE_MPI -#include "PerfTest/TreeLoaderMpiSplitFCheb.hpp" -#include "PerfTest/TreeLoaderMpiGenericFCheb.hpp" -#endif - -#include "PerfTest/KernelLoaderFChebSym.hpp" - -#include "PerfTest/AlgoLoaderThread.hpp" -#include "PerfTest/AlgoLoaderTask.hpp" -#include "PerfTest/AlgoLoaderSectionTask.hpp" -#include "PerfTest/AlgoLoaderCostZones.hpp" -#include "PerfTest/AlgoLoaderThreadBalance.hpp" - -#ifdef SCALFMM_USE_MPI -#include "PerfTest/AlgoLoaderThreadProc.hpp" -#endif - -#define HOST_NAME_MAX 64 - -/** - * \brief Runs a generic sequence of actions to use an algorithm. - * - * This function runs the basic steps that are needed to run an FMM algorithm - * over a set of particles. It does the following steps : - * - * - Load a tree using the class defined as a TreeLoader - * - Prepare the needed kernels using the KernelLoader - * - Prepare and run the algorithm using the AlgorithmLoader - * - * See documentation of FTreeLoader, FKernelLoader, FAlgoLoader. - */ -template class KernelLoader, - template class KL> class AlgoLoader> -void runperf(FPerfTestParams& params) -{ - TreeLoader treeLoader(params); - KernelLoader kernelLoader(params, treeLoader); - AlgoLoader algoLoader(params, treeLoader, kernelLoader); - algoLoader.run(); - - char hostname[HOST_NAME_MAX]; - memset(hostname,'\0',HOST_NAME_MAX); - if ( -1 == gethostname(hostname, HOST_NAME_MAX-1) ) { - perror("Could not get hostname"); - strncpy(hostname, "unknown", HOST_NAME_MAX); - } - - std::cout << "@@ " - << "host:" << hostname << " " - << "algo:" << params.algo << " " - << "file:" << params.filename.substr( - params.filename.find_last_of('/')+1 ) << " " - << "particles:" << treeLoader._loader.getNumberOfParticles() << " " - << "procs:" << params.nbProcs << " " - << "threads:" << params.nbThreads << " " - << "height:" << params.treeHeight << " " - << "subheight:" << params.subTreeHeight << " " - << algoLoader.getRunInfoString() - << "P2M:" << algoLoader.getCumulatedTime(FAlgorithmTimers::P2MTimer) << " " - << "M2M:" << algoLoader.getCumulatedTime(FAlgorithmTimers::M2MTimer) << " " - << "M2L:" << algoLoader.getCumulatedTime(FAlgorithmTimers::M2LTimer) << " " - << "L2L:" << algoLoader.getCumulatedTime(FAlgorithmTimers::L2LTimer) << " " - << "P2PL2P:" << algoLoader.getCumulatedTime(FAlgorithmTimers::NearTimer) << " " - << std::endl; -} - -namespace ParName { - const FParameterNames Algo = {{"--algo"},"Algorithm to run (basic, task, costzones, sectiontask, autobalance" -#ifdef SCALFMM_USE_MPI - ", mpi-split, mpi-generic" -#endif - ")."}; - const FParameterNames Schedule = {{"--schedule"},"OpenMP scheduling policy (static, dynamic)."}; - const FParameterNames ChunkSize = {{"--chunk-size"},"OpenMP chunk size for basic dynamic algorithm."}; -} - -int main (int argc, char** argv) -{ - // Parameter handling ////////////// - FHelpDescribeAndExit(argc, argv, - "Performance test program for FMM balancing techniques. " -#ifdef SCALFMM_USE_MPI - "This program has been compiled with MPI superpowers !" -#endif - , - FParameterDefinitions::InputFile, - FParameterDefinitions::OctreeHeight, - FParameterDefinitions::OctreeSubHeight, - FParameterDefinitions::NbThreads, - ParName::Algo, - ParName::Schedule, - ParName::ChunkSize); - FPerfTestParams params; - { - using namespace FParameterDefinitions; - using namespace FParameters; - params.filename = getStr(argc,argv,InputFile.options, - "../Data/unitCubeXYZQ100.bfma"); - params.treeHeight = getValue(argc, argv, OctreeHeight.options, 5); - params.subTreeHeight = getValue(argc, argv, OctreeSubHeight.options, 2); - params.nbThreads = getValue(argc, argv, NbThreads.options, 1); - params.algo = getStr(argc,argv,ParName::Algo.options,"task"); - params.omp_chunk_size = getValue(argc, argv, ParName::ChunkSize.options, 0); - -#ifdef SCALFMM_USE_MPI - std::string prefix("mpi-"); - if( params.algo.substr(0, prefix.size()) == prefix ) { - params.mpiContext = new FMpi(argc,argv); - params.nbProcs = params.mpiContext->global().processCount(); - } -#endif - } - // End of Parameter handling /////// - - char hostname[HOST_NAME_MAX]; - memset(hostname,'\0',HOST_NAME_MAX); - if ( -1 == gethostname(hostname, HOST_NAME_MAX-1) ) { - perror("Could not get hostname"); - strncpy(hostname, "unknown", HOST_NAME_MAX); - } - std::cout << "Hostname: " << hostname << std::endl; - - omp_set_num_threads(params.nbThreads); - - using FReal = double; - constexpr const int ORDER = 7; - - if( "basic" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderThread> - (params); - } else if( "task" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderTask> - (params); - } else if ( "costzones" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderCostZones> - (params); - } else if ( "sectiontask" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderSectionTask> - (params); - } else if ( "autobalance" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderThreadBalance> - (params); -#ifdef SCALFMM_USE_MPI - } else if ( "mpi-split" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderThreadProc> - (params); - } else if ( "mpi-generic" == params.algo ) { - runperf, - KernelLoaderFChebSym, - AlgoLoaderThreadProc> - (params); -#endif - } else { - std::cout << "Unknown algorithm: " << params.algo << std::endl; - } - -#ifdef SCALFMM_USE_MPI - if( nullptr != params.mpiContext ) { - delete params.mpiContext; - } -#endif - -} diff --git a/Tests/noDist/PerfTest/AlgoLoaderCostZones.hpp b/Tests/noDist/PerfTest/AlgoLoaderCostZones.hpp deleted file mode 100644 index 017c553815d7001b208fbcf2c2b8177a01a5b258..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/AlgoLoaderCostZones.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _ALGOLOADERCOSTZONES_HPP_ -#define _ALGOLOADERCOSTZONES_HPP_ - -#include -#include - -#include "PerfTestUtils.hpp" - -#include "Core/FFmmAlgorithmThread.hpp" - -#include "BalanceTree/FFmmAlgorithmThreadBalanced.hpp" -#include "BalanceTree/FCostCell.hpp" -#include "BalanceTree/FCostZones.hpp" - -/** - * \brief Algorithm loader for FFmmAlgorithmThreadBalanced. - * - * See FAlgoLoader documentation. - * - * \warning : This loader requires that the KernelLoader supply a type definition - * for a `CostKernelClass` - */ -template class _KernelLoader> -class AlgoLoaderCostZones : public FAlgoLoader<_TreeLoader, _KernelLoader> { -public: - // Types definitions - - /// The TreeLoader type that is used. - using TreeLoader = _TreeLoader; - using KernelLoader = _KernelLoader; - - using FReal = typename TreeLoader::FReal; - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using LeafClass = typename TreeLoader::LeafClass; - using OctreeClass = typename TreeLoader::OctreeClass; - using KernelClass = typename KernelLoader::KernelClass; - using CostKernelClass= typename KernelLoader::CostKernelClass; - - static_assert(std::is_base_of::value, - "The tree cells must derive from FCostCell."); - - using FMMClass = FFmmAlgorithmThreadBalanced - ; - using CostFmmClass = FFmmAlgorithmThread - ; - - std::stringstream _infostring; - TreeLoader& _treeLoader; - KernelLoader& _kernelLoader; - - std::unique_ptr _algo; - - - /// Builds the loader - AlgoLoaderCostZones(FPerfTestParams& /*params*/, - TreeLoader& treeLoader, - KernelLoader& kernelLoader) : - _treeLoader(treeLoader), - _kernelLoader(kernelLoader), - _algo(nullptr) { - - } - - /// Computes the tree cells costs then runs the costzones and FMM algorithms. - void run() { - // The tree loader holds the tree structure - OctreeClass* p_tree = &(_treeLoader._tree); - - // Compute tree cells costs - CostFmmClass costAlgo(p_tree, &(_kernelLoader._costKernel)); - - this->time.tic(); - costAlgo.execute(); - this->time.tac(); - std::cout << "Generating tree cost: " << this->time.elapsed() << "s.\n"; - _infostring << "costgen:" << this->time.elapsed() << " "; - - // Compute cost zones - FCostZones costzones(p_tree, omp_get_max_threads()); - - this->time.tic(); - costzones.run(); - this->time.tac(); - std::cout << "Generating cost zones: " << this->time.elapsed() << "s.\n"; - _infostring << "zonegen:" << this->time.elapsed() << " "; - - // Execute FFM algorithm - this->time.tic(); - _algo = std::unique_ptr( - new FMMClass(p_tree, &(_kernelLoader._kernel), - costzones.getZoneBounds(), costzones.getLeafZoneBounds())); - _algo->execute(); - this->time.tac(); - } - - std::string getRunInfoString() const { - return _infostring.str(); - } - - double getCumulatedTime(FAlgorithmTimers::FTimers timerName) const { - return _algo->getCumulatedTime(timerName); - } - -}; - - - -#endif diff --git a/Tests/noDist/PerfTest/AlgoLoaderSectionTask.hpp b/Tests/noDist/PerfTest/AlgoLoaderSectionTask.hpp deleted file mode 100644 index 245e3c477f3a8f6f848cf08980bf7aaaed6093ef..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/AlgoLoaderSectionTask.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _ALGOLOADERSECTIONTASK_HPP_ -#define _ALGOLOADERSECTIONTASK_HPP_ - -#include - -#include "PerfTestUtils.hpp" - -#include "Core/FFmmAlgorithmSectionTask.hpp" - - -template class _KernelLoader> -class AlgoLoaderSectionTask : public FAlgoLoader<_TreeLoader, _KernelLoader> { -public: - using TreeLoader = _TreeLoader; - using KernelLoader = _KernelLoader; - - - using FReal = typename TreeLoader::FReal; - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using LeafClass = typename TreeLoader::LeafClass; - using OctreeClass = typename TreeLoader::OctreeClass; - using KernelClass = typename KernelLoader::KernelClass; - - using FMMClass = FFmmAlgorithmSectionTask; - - TreeLoader& _treeLoader; - KernelLoader& _kernelLoader; - - std::unique_ptr _algo; - - AlgoLoaderSectionTask(FPerfTestParams& /*params*/, - TreeLoader& treeLoader, - KernelLoader& kernelLoader) : - _treeLoader(treeLoader), - _kernelLoader(kernelLoader), - _algo(nullptr) { - - } - - - void run() { - _algo = std::unique_ptr( - new FMMClass(&(_treeLoader._tree), &(_kernelLoader._kernel))); - _algo->execute(); - } - - double getCumulatedTime(FAlgorithmTimers::FTimers timerName) const { - return _algo->getCumulatedTime(timerName); - } -}; - - - -#endif diff --git a/Tests/noDist/PerfTest/AlgoLoaderTask.hpp b/Tests/noDist/PerfTest/AlgoLoaderTask.hpp deleted file mode 100644 index 2422f7e7c6efb7c7a27fa6b916424276c785a992..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/AlgoLoaderTask.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _ALGOLOADERTASK_HPP_ -#define _ALGOLOADERTASK_HPP_ - -#include - -#include "PerfTestUtils.hpp" - -#include "Core/FFmmAlgorithmTask.hpp" - - -template class _KernelLoader> -class AlgoLoaderTask : public FAlgoLoader<_TreeLoader, _KernelLoader> { -public: - using TreeLoader = _TreeLoader; - using KernelLoader = _KernelLoader; - - - using FReal = typename TreeLoader::FReal; - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using LeafClass = typename TreeLoader::LeafClass; - using OctreeClass = typename TreeLoader::OctreeClass; - using KernelClass = typename KernelLoader::KernelClass; - - using FMMClass = FFmmAlgorithmTask; - - TreeLoader& _treeLoader; - KernelLoader& _kernelLoader; - - std::unique_ptr _algo; - - AlgoLoaderTask(FPerfTestParams& /*params*/, - TreeLoader& treeLoader, - KernelLoader& kernelLoader) : - _treeLoader(treeLoader), - _kernelLoader(kernelLoader), - _algo(nullptr) { - - } - - - void run() { - _algo = std::unique_ptr( - new FMMClass(&(_treeLoader._tree), &(_kernelLoader._kernel))); - _algo->execute(); - } - - double getCumulatedTime(FAlgorithmTimers::FTimers timerName) const { - return _algo->getCumulatedTime(timerName); - } -}; - - - -#endif diff --git a/Tests/noDist/PerfTest/AlgoLoaderThread.hpp b/Tests/noDist/PerfTest/AlgoLoaderThread.hpp deleted file mode 100644 index 322ec6fd205e875a07d67ae26a6bde4dc1160ec3..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/AlgoLoaderThread.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _ALGOLOADERTHREAD_HPP_ -#define _ALGOLOADERTHREAD_HPP_ - -#include -#include - -#include "PerfTestUtils.hpp" - -#include "Core/FFmmAlgorithmThread.hpp" - -/** - * \brief Algorithm loader for FFmmAlgorithmThread - * - * See FAlgoLoader. - */ -template class _KernelLoader> -class AlgoLoaderThread : public FAlgoLoader<_TreeLoader, _KernelLoader> { -public: - - // Type definitions, allows them to be reused by other classes - using TreeLoader = _TreeLoader; - using KernelLoader = _KernelLoader; - - using FReal = typename TreeLoader::FReal; - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using LeafClass = typename TreeLoader::LeafClass; - using OctreeClass = typename TreeLoader::OctreeClass; - using KernelClass = typename KernelLoader::KernelClass; - - /// FMM algorithm class - using FMMClass = FFmmAlgorithmThread; - - /// The tree loader (FTreeLoader) that was used - TreeLoader& _treeLoader; - - /// The kernel loader (FKernelLoader) that was used - KernelLoader& _kernelLoader; - - unsigned int _omp_chunk_size; ///< Chunk size for OpenMP - - /// The #FMMClass algorithm instance - std::unique_ptr _algo; - - AlgoLoaderThread(FPerfTestParams& params, - TreeLoader& treeLoader, - KernelLoader& kernelLoader) : - _treeLoader(treeLoader), - _kernelLoader(kernelLoader), - _omp_chunk_size(params.omp_chunk_size), - _algo(nullptr) { - - } - - void run() { - _algo = std::unique_ptr( - new FMMClass(&(_treeLoader._tree), &(_kernelLoader._kernel))); - _algo->setChunkSize(_omp_chunk_size); - - _algo->execute(); - } - - - virtual std::string getRunInfoString() const { - std::stringstream sstr; - sstr << "chunksize:" << _omp_chunk_size << " "; - return sstr.str(); - } - - double getCumulatedTime(FAlgorithmTimers::FTimers timerName) const { - return _algo->getCumulatedTime(timerName); - } - - -}; - -#endif diff --git a/Tests/noDist/PerfTest/AlgoLoaderThreadBalance.hpp b/Tests/noDist/PerfTest/AlgoLoaderThreadBalance.hpp deleted file mode 100644 index 05cb80de0bccb8d9ae9e26634e5f2a6beecc2eaf..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/AlgoLoaderThreadBalance.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _ALGOLOADERTHREADBALANCE_HPP_ -#define _ALGOLOADERTHREADBALANCE_HPP_ - -#include -#include - -#include "PerfTestUtils.hpp" - -#include "Core/FFmmAlgorithmThreadBalance.hpp" - -/** - * \brief An algorithm loader for FFmmAlgorithmBalance - * - * See FAlgoLoader documentation. - */ -template class _KernelLoader> -class AlgoLoaderThreadBalance : public FAlgoLoader<_TreeLoader, _KernelLoader> { -public: - using TreeLoader = _TreeLoader; - using KernelLoader = _KernelLoader; - - using FReal = typename TreeLoader::FReal; - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using LeafClass = typename TreeLoader::LeafClass; - using OctreeClass = typename TreeLoader::OctreeClass; - using KernelClass = typename KernelLoader::KernelClass; - - using FMMClass = FFmmAlgorithmThreadBalance; - - TreeLoader& _treeLoader; - KernelLoader& _kernelLoader; - - std::unique_ptr _algo; - - AlgoLoaderThreadBalance(FPerfTestParams& params, - TreeLoader& treeLoader, - KernelLoader& kernelLoader) : - _treeLoader(treeLoader), - _kernelLoader(kernelLoader), - _algo(nullptr) { - - } - - void run() { - _algo = std::unique_ptr( - new FMMClass(&(_treeLoader._tree), &(_kernelLoader._kernel))); - - _algo->execute(); - } - - - virtual std::string getRunInfoString() const { - return ""; - } - - double getCumulatedTime(FAlgorithmTimers::FTimers timerName) const { - return _algo->getCumulatedTime(timerName); - } - - -}; - -#endif diff --git a/Tests/noDist/PerfTest/AlgoLoaderThreadProc.hpp b/Tests/noDist/PerfTest/AlgoLoaderThreadProc.hpp deleted file mode 100644 index 9798e4733d0e758782cccb57098fc844837ac314..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/AlgoLoaderThreadProc.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _ALGOLOADERTHREADPROC_HPP_ -#define _ALGOLOADERTHREADPROC_HPP_ - -#include -#include - -#include "PerfTestUtils.hpp" - -#include "Core/FFmmAlgorithmThreadProc.hpp" -#include "Utils/FMpi.hpp" - -/** - * \brief Algorithm loader for FFmmAlgorithmThread - * - * See FAlgoLoader. - */ -template class _KernelLoader> -class AlgoLoaderThreadProc : public FAlgoLoader<_TreeLoader, _KernelLoader> { -public: - - // Type definitions, allows them to be reused by other classes - using TreeLoader = _TreeLoader; - using KernelLoader = _KernelLoader; - - using FReal = typename TreeLoader::FReal; - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using LeafClass = typename TreeLoader::LeafClass; - using OctreeClass = typename TreeLoader::OctreeClass; - using KernelClass = typename KernelLoader::KernelClass; - - /// FMM algorithm class - using FMMClass = FFmmAlgorithmThreadProc; - - FMpi* _mpiContext; - - /// The tree loader (FTreeLoader) that was used - TreeLoader& _treeLoader; - - /// The kernel loader (FKernelLoader) that was used - KernelLoader& _kernelLoader; - - /// The #FMMClass algorithm instance - std::unique_ptr _algo; - - /// Array of MPI gathered cumulated times - double timers[FAlgorithmTimers::nbTimers] {0}; - - - AlgoLoaderThreadProc(FPerfTestParams& params, - TreeLoader& treeLoader, - KernelLoader& kernelLoader) : - _mpiContext(params.mpiContext), - _treeLoader(treeLoader), - _kernelLoader(kernelLoader), - _algo(nullptr) { - - } - - - void run() { - _algo = std::unique_ptr( - new FMMClass(_mpiContext->global(), &(_treeLoader._tree), &(_kernelLoader._kernel))); - _algo->execute(); - - for( int idxTimer = 0; idxTimer < FAlgorithmTimers::nbTimers; ++idxTimer ) { - timers[idxTimer] = _algo->getCumulatedTime(FAlgorithmTimers::FTimers(idxTimer)); - } - - if( _mpiContext->global().processId() == 0) { - MPI_Reduce(MPI_IN_PLACE, timers, FAlgorithmTimers::nbTimers, MPI_DOUBLE, MPI_MAX, 0, _mpiContext->global().getComm()); - } else { - MPI_Reduce(timers, NULL, FAlgorithmTimers::nbTimers, MPI_DOUBLE, MPI_MAX, 0, _mpiContext->global().getComm()); - } - } - - double getCumulatedTime(FAlgorithmTimers::FTimers timerName) const { - return timers[timerName]; - } - -}; - -#endif diff --git a/Tests/noDist/PerfTest/KernelLoaderFChebSym.hpp b/Tests/noDist/PerfTest/KernelLoaderFChebSym.hpp deleted file mode 100644 index 2945c2714e72dc4a91fcad5c19b5a092bcbf5aaf..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/KernelLoaderFChebSym.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - - - -#ifndef _KERNELLOADERFCHEBSYM_HPP_ -#define _KERNELLOADERFCHEBSYM_HPP_ - -#include "PerfTestUtils.hpp" - -#include "Kernels/Interpolation/FInterpMatrixKernel.hpp" -#include "Kernels/Chebyshev/FChebSymKernel.hpp" - -#include "BalanceTree/FChebSymCostKernel.hpp" - -/** - * \brief Kernel loader for the symetric Chebyshev kernel. - * - * \warning This loader requires that TreeLoader::CellClass inherits from - * FChebCell. - * - * \note This loader also provides the typedef CostKernelClass and a member - * _costKernel that cam be used by the AlgoLoaderCostZones. - */ -template -class KernelLoaderFChebSym : public FKernelLoader<_TreeLoader> { - // Meaningfull (?) error message. - static_assert( - std::is_base_of, - typename _TreeLoader::CellClass>::value, - "TreeLoader::CellClass must derive from FChebCell"); - - -public: - // Required type definitions - using TreeLoader = _TreeLoader; - using FReal = typename TreeLoader::FReal; - /// Must derive from FChebCell - using CellClass = typename TreeLoader::CellClass; - using ContainerClass = typename TreeLoader::ContainerClass; - using OctreeClass = typename TreeLoader::OctreeClass; - - using MatrixKernelClass = FInterpMatrixKernelR; - using KernelClass = FChebSymKernel ; - /// Kernel class used to compute the tree cell costs. - using CostKernelClass = FChebSymCostKernel; - - const FReal epsilon = 1e-4; - - /// Matrix used to compute the tree cells interactions. - const MatrixKernelClass _matrixKernel; - /// Kernel used to compute the tree cells interactions. - KernelClass _kernel; - /// Kernel used to compute the tree cells costs. - CostKernelClass _costKernel; - - /// Builds and loads the kernel. - /** \param params Parameters from the main invocation, UNSUSED - * \param treeLoader Tree loader that was used. - */ - KernelLoaderFChebSym(FPerfTestParams& /*params*/, TreeLoader& treeLoader) : - _matrixKernel(), - _kernel(treeLoader._tree.getHeight(), - treeLoader._tree.getBoxWidth(), - treeLoader._tree.getBoxCenter(), - &_matrixKernel), - _costKernel(&(treeLoader._tree), epsilon){ - - } - - -}; - - -#endif diff --git a/Tests/noDist/PerfTest/PerfTestUtils.hpp b/Tests/noDist/PerfTest/PerfTestUtils.hpp deleted file mode 100644 index cc4020467774f17d916461405304e8550da88db6..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/PerfTestUtils.hpp +++ /dev/null @@ -1,150 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _PERFTESTUTILS_HPP_ -#define _PERFTESTUTILS_HPP_ - -#include - -#ifdef SCALFMM_USE_MPI -#include "Utils/FMpi.hpp" -#endif - -#include "Utils/FTic.hpp" -#include "Files/FFmaGenericLoader.hpp" - -#include "Containers/FOctree.hpp" - -/** - * \brief Store the PerfTest program parameters. - */ -struct FPerfTestParams { - int subTreeHeight = 2; ///< Subtree height. - int treeHeight = 5; ///< Tree height. - int nbThreads = 1; ///< Maximum number of threads (when used). - std::string filename = ""; ///< Particles file. - std::string algo = "task"; ///< Algorithm to run. - int omp_chunk_size = 0; ///< OpenMP chunk size for basic algorithm (FFmmAlgorithmThread) - int nbProcs = 1; -#ifdef SCALFMM_USE_MPI - FMpi* mpiContext = nullptr; -#endif -}; - - -/** - * \brief Base class for tree loaders. - * - * This class itself does not provide anything but a base on which to build tree - * loaders. A tree loader should satisfy the following rules. - * - * - Define the public typedefs : CellClass, ContainerClass, LeafClass, - * OctreeClass. - * - Provide public acces to a member of type OctreeClass _tree as the tree - * that is loaded. - * - Tree loading must happen at construction. - * - It may provide any other members or typdefs required by a special - * FKernelLoader or FAlgoLoader. - * - * For convenience, this class provides a timer and a basic loadTree method that - * should be enough to load a tree from and FMA file. - * - * \note It is not mandatory that a loader inherit from this class. It must - * however follow the aforementioned rules. - */ -class FTreeLoader { -public: - /// A timer used to time the loadTree method. - FTic time; -protected: - - /** - * \brief Load a tree from a file. - * - * \param loader The file loader to read from the file. - * \param tree The tree to be filled. - */ - virtual void loadTree() = 0; -}; - -/** - * \brief Base class for kernel loaders. - * - * This class itself does not provide anything but a base on which to build - * kernel loaders. A kernel loader should satisfy the following rules. - * - * - Define the public typedefs : TreeLoader, KernelClass. - * - Provide public acces to a member of type Kernelclass _kernel as the - * kernel that is loaded. - * - Kernel loading must happen at construction. - * - It may provide any other members or typdefs required by a special - * FAlgoLoader. - * - * For convenience, this class provides a timer. - * - * \tparam _TreeLoader The tree loader that was used. - * - * \note It is not mandatory that a loader inherit from this class. It must - * however follow the aforementioned rules. - */ -template -class FKernelLoader { - /// The tree loader that was used (see FTreeLoader). - using TreeLoader = _TreeLoader; -public: - /// A timer - FTic time; -}; - -/** - * \brief Base class for algorithm loaders. - * - * This class itself does not provide anything but a base on which to build - * algorithm loaders. A kernel loader should satisfy the following rules. - * - * - Define the public typedefs : TreeLoader, KernelLoader. - * - Provide public acces to a member of type - * \link TreeLoader Treeloader::OctreeClass* \endlink` _algo` - * as the algorithm that is loaded. This pointer should be valid from the - * end of the ::run method to the destruction of the loader. - * - It may provide any other members or typdefs. - * - * For convenience, this class provides a timer. - * - * \tparam _TreeLoader The tree loader that was used. - * \tparam _KernelLoader The kernel loader *template* that was used, the - * KernelLoader type will then be _KernelLoader<_TreeLoader>. - * - * \note It is not mandatory that a loader inherit from this class. It must - * however follow the aforementioned rules. - */ -template class _KernelLoader> -class FAlgoLoader { - /// The tree loader that was used (see FTreeLoader). - using TreeLoader = _TreeLoader; - /// The kernel loader that was used (see FKernelLoader). - using KernelLoader = _KernelLoader; -public: - /// A timer. - FTic time; - - /// Method that runs the algorithm. - virtual void run() = 0; - - /// Additionnal information for specific algorithm loader. - /** - * The string should be formated as a key:value list separated by spaces. - * For instance : "key1:value1 key2:value2 ". It may be a good idea to add a - * space at the end of the string. - */ - virtual std::string getRunInfoString() const { - return ""; - } -}; - - - - - -#endif diff --git a/Tests/noDist/PerfTest/TreeLoaderBasic.hpp b/Tests/noDist/PerfTest/TreeLoaderBasic.hpp deleted file mode 100644 index c130c5d1968f95ec0b0c95e52996b87369af9a10..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/TreeLoaderBasic.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _TREELOADERBASIC_HPP_ -#define _TREELOADERBASIC_HPP_ - -#include "PerfTestUtils.hpp" - -#include "Containers/FOctree.hpp" -#include "Components/FSimpleLeaf.hpp" -#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" - -#include "BalanceTree/FCostCell.hpp" - -/** - * \brief Basic tree loader. - * - * See FTreeLoader documentation. - */ -template -class TreeLoaderBasic : public FTreeLoader { -public: - using FReal = _FReal; - using BaseClass = _BaseClass; - - // Required type definitions. - using CellClass = FCostCell; - using ContainerClass = FP2PParticleContainerIndexed; - using LeafClass = FSimpleLeaf; - using OctreeClass = FOctree; - - /// File loader. - FFmaGenericLoader _loader; - /// Required tree member. - OctreeClass _tree; - - /// Constructs the loader and loads the tree. - TreeLoaderBasic(FPerfTestParams& params): - _loader(params.filename), - _tree(params.treeHeight, - params.subTreeHeight, - _loader.getBoxWidth(), - _loader.getCenterOfBox()) { - this->loadTree(); - } - - virtual void loadTree() { - std::cout << "Creating & inserting particles" << std::flush; - - time.tic(); - - FPoint position; - FReal physicalValue = 0.0; - for(FSize idxPart = 0 ; idxPart < _loader.getNumberOfParticles() ; ++idxPart) { - // Read particle per particle from file - _loader.fillParticle(&position,&physicalValue); - // put particle in octree - _tree.insert(position, idxPart, physicalValue); - } - - time.tac(); - std::cout << " Done (" << time.elapsed() << " s)." << std::endl; - } - -}; - -#endif diff --git a/Tests/noDist/PerfTest/TreeLoaderFCheb.hpp b/Tests/noDist/PerfTest/TreeLoaderFCheb.hpp deleted file mode 100644 index 8821d98767f9a271addc6e2776e6e952a2f68bd0..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/TreeLoaderFCheb.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _TREELOADERFCHEB_HPP_ -#define _TREELOADERFCHEB_HPP_ - -#include "Kernels/Chebyshev/FChebCell.hpp" - -#include "TreeLoaderBasic.hpp" - - -/** - * \brief Tree loader for a Chebyshev cell type tree. - * - * See FTreeLoader and TreeLoaderBasic documentation. - */ -template -class TreeLoaderFCheb : public TreeLoaderBasic<_FReal, FChebCell<_FReal, _ORDER> > { -public: - - enum {ORDER=_ORDER}; - - /// Constructs the loader and loads the tree. - TreeLoaderFCheb(FPerfTestParams& params): - TreeLoaderBasic<_FReal, FChebCell<_FReal, _ORDER>>(params) - {} - -}; - -#endif diff --git a/Tests/noDist/PerfTest/TreeLoaderMpiGeneric.hpp b/Tests/noDist/PerfTest/TreeLoaderMpiGeneric.hpp deleted file mode 100644 index 4775a9f6d6d0f1be09c6ba2aae71ba8ba4bdcac2..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/TreeLoaderMpiGeneric.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _TREELOADERMPIGENERIC_HPP_ -#define _TREELOADERMPIGENERIC_HPP_ - -#include "PerfTestUtils.hpp" -#include "Utils/FMpi.hpp" - -#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" -#include "BalanceTree/FCostCell.hpp" -#include "Components/FSimpleLeaf.hpp" -#include "Containers/FOctree.hpp" - -#include "Files/FFmaGenericLoader.hpp" -#include "Files/FMpiFmaGenericLoader.hpp" -#include "Files/FMpiTreeBuilder.hpp" - - -/** - * \brief Genericted FMA file tree loader. - * - * See FTreeLoader documentation. - */ -template -class TreeLoaderMpiGeneric : public FTreeLoader { -public: - using FReal = _FReal; - - // Required type definitions. - using BaseClass = _BaseClass; - using CellClass = FCostCell; - using ContainerClass = FP2PParticleContainerIndexed; - using LeafClass = FSimpleLeaf; - using OctreeClass = FOctree; - - /// MPI applcation context. - FMpi* _mpiContext; - /// File loader. - FMpiFmaGenericLoader _loader; - /// Required tree member. - OctreeClass _tree; - - /* Mock particle structure to balance the tree over the processes. */ - struct TestParticle{ - FSize index; // Index of the particle in the original file. - FPoint position; // Spatial position of the particle. - FReal physicalValue; // Physical value of the particle. - /* Returns the particle position. */ - const FPoint& getPosition(){ - return position; - } - }; - - - /// Constructs the loader and loads the tree. - TreeLoaderMpiGeneric(FPerfTestParams& params): - _mpiContext(params.mpiContext), - _loader(params.filename, _mpiContext->global()), - _tree(params.treeHeight, - params.subTreeHeight, - _loader.getBoxWidth(), - _loader.getCenterOfBox()) { - this->loadTree(); - } - - void loadTree() { - if( 0 == _mpiContext->global().processId()) - std::cout << "Creating & inserting particles" << std::flush; - - time.tic(); - - // Temporary array of particles read by this process. - TestParticle* particles = new TestParticle[_loader.getMyNumberOfParticles()]; - memset(particles, 0, (sizeof(TestParticle) * _loader.getMyNumberOfParticles())); - - // Index (in file) of the first particle that will be read by this process. - FSize idxStart = _loader.getStart(); - - // Read particles from parts. - for(FSize idxPart = 0 ; idxPart < _loader.getMyNumberOfParticles() ; ++idxPart){ - // Store the index (in the original file) the particle. - particles[idxPart].index = idxPart + idxStart; - // Read particle from file - _loader.fillParticle(&particles[idxPart].position, - &particles[idxPart].physicalValue); - } - - // Final vector of particles - FVector finalParticles; - FLeafBalance balancer; - - // Redistribute particules between processes - FMpiTreeBuilder< FReal, TestParticle >:: - DistributeArrayToContainer(_mpiContext->global(), - particles, - _loader.getMyNumberOfParticles(), - _tree.getBoxCenter(), - _tree.getBoxWidth(), - _tree.getHeight(), - &finalParticles, - &balancer); - - // Free temporary array memory. - delete[] particles; - - // Insert final particles into tree. - for(FSize idx = 0 ; idx < finalParticles.getSize(); ++idx){ - _tree.insert(finalParticles[idx].position, - finalParticles[idx].index, - finalParticles[idx].physicalValue); - } - - time.tac(); - double elapsedTime = time.elapsed(), minTime, maxTime; - - MPI_Reduce(&elapsedTime,&minTime,1,MPI_DOUBLE,MPI_MIN,0,_mpiContext->global().getComm()); - MPI_Reduce(&elapsedTime,&maxTime,1,MPI_DOUBLE,MPI_MAX,0,_mpiContext->global().getComm()); - - if( 0 == _mpiContext->global().processId()) { - std::cout << " Done ( min-time:" << minTime - << " max-time:" << maxTime - << " )" - << std::endl; - - } - } - -}; - -#endif diff --git a/Tests/noDist/PerfTest/TreeLoaderMpiGenericFCheb.hpp b/Tests/noDist/PerfTest/TreeLoaderMpiGenericFCheb.hpp deleted file mode 100644 index 745126125905d87821f34333998fd59d53fa27ed..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/TreeLoaderMpiGenericFCheb.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _TREELOADERMPIGENERICFCHEB_HPP_ -#define _TREELOADERMPIGENERICFCHEB_HPP_ - -#include "Kernels/Chebyshev/FChebCell.hpp" - -#include "TreeLoaderMpiGeneric.hpp" - - -/** - * \brief Tree loader for a Chebyshev cell type tree. - * - * See FTreeLoader and TreeLoaderBasic documentation. - */ -template -class TreeLoaderMpiGenericFCheb : public TreeLoaderMpiGeneric<_FReal, FChebCell<_FReal, _ORDER> > { -public: - - enum {ORDER=_ORDER}; - - /// Constructs the loader and loads the tree. - TreeLoaderMpiGenericFCheb(FPerfTestParams& params): - TreeLoaderMpiGeneric<_FReal, FChebCell<_FReal, _ORDER>>(params) - {} - -}; - -#endif diff --git a/Tests/noDist/PerfTest/TreeLoaderMpiSplit.hpp b/Tests/noDist/PerfTest/TreeLoaderMpiSplit.hpp deleted file mode 100644 index d38697fe3289086bb3ef4c8e371142c9c148aa43..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/TreeLoaderMpiSplit.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _TREELOADERMPISPLIT_HPP_ -#define _TREELOADERMPISPLIT_HPP_ - -#include "PerfTestUtils.hpp" -#include "Utils/FMpi.hpp" - -#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" -#include "BalanceTree/FCostCell.hpp" -#include "Components/FSimpleLeaf.hpp" -#include "Containers/FOctree.hpp" - -#include "Files/FMpiSplitFmaLoader.hpp" - - -/** - * \brief Splitted FMA file tree loader. - * - * See FTreeLoader documentation. - */ -template -class TreeLoaderMpiSplit : public FTreeLoader { -public: - using FReal = _FReal; - - // Required type definitions. - using BaseClass = _BaseClass; - using CellClass = FCostCell; - using ContainerClass = FP2PParticleContainerIndexed; - using LeafClass = FSimpleLeaf; - using OctreeClass = FOctree; - - /// Mpi application context - FMpi* _mpiContext; - /// File loader. - FMpiSplitFmaLoader _loader; - /// Required tree member. - OctreeClass _tree; - - /// Constructs the loader and loads the tree. - TreeLoaderMpiSplit(FPerfTestParams& params): - _mpiContext(params.mpiContext), - _loader(params.filename,_mpiContext->global().processId()), - _tree(params.treeHeight, - params.subTreeHeight, - _loader.getBoxWidth(), - _loader.getCenterOfBox()) { - if( nullptr == _mpiContext ) { - std::cerr << "No MPI context available" << std::endl; - exit(-1); - } - - this->loadTree(); - } - - void loadTree() { - std::cout << "Creating & inserting particles" << std::flush; - - time.tic(); - - FPoint position; - FReal physicalValue = 0.0; - for(FSize idxPart = 0 ; idxPart < _loader.getMyNumberOfParticles() ; ++idxPart) { - // Read particle per particle from file - _loader.fillParticle(&position,&physicalValue); - // put particle in octree - _tree.insert(position, idxPart, physicalValue); - } - - time.tac(); - std::cout << " Done (" << time.elapsed() << " s)." << std::endl; - } - -}; - -#endif diff --git a/Tests/noDist/PerfTest/TreeLoaderMpiSplitFCheb.hpp b/Tests/noDist/PerfTest/TreeLoaderMpiSplitFCheb.hpp deleted file mode 100644 index 2ede231989c0c12714cacfbbc3fa3705787234f0..0000000000000000000000000000000000000000 --- a/Tests/noDist/PerfTest/TreeLoaderMpiSplitFCheb.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// ==== CMAKE ==== -// Keep in private GIT -// @SCALFMM_PRIVATE - -#ifndef _TREELOADERMPISPLITFCHEB_HPP_ -#define _TREELOADERMPISPLITFCHEB_HPP_ - -#include "Kernels/Chebyshev/FChebCell.hpp" - -#include "TreeLoaderMpiSplit.hpp" - - -/** - * \brief Tree loader for a Chebyshev cell type tree. - * - * See FTreeLoader and TreeLoaderBasic documentation. - */ -template -class TreeLoaderMpiSplitFCheb : public TreeLoaderMpiSplit<_FReal, FChebCell<_FReal, _ORDER> > { -public: - - enum {ORDER=_ORDER}; - - /// Constructs the loader and loads the tree. - TreeLoaderMpiSplitFCheb(FPerfTestParams& params): - TreeLoaderMpiSplit<_FReal, FChebCell<_FReal, _ORDER>>(params) - {} - -}; - -#endif diff --git a/Tests/noDist/testInsert.cpp b/Tests/noDist/testInsert.cpp index 5385885ffd2e0b18e0f6333a1869afcd77a15420..0f8bf953280f0a24f942a0a09bd065f0df568288 100644 --- a/Tests/noDist/testInsert.cpp +++ b/Tests/noDist/testInsert.cpp @@ -185,7 +185,7 @@ int main(int argc, char** argv){ host.setZ( FCoordinateComputer::GetTreeCoordinate( arrayOfParts[idxPart].getPosition().getZ() - boxCorner.getZ(), boxWidth, boxWidthAtLeafLevel, NbLevels )); //Set Morton index from Tree Coordinate - arrayOfParts[idxPart].index = host.getMortonIndex(NbLevels - 1); + arrayOfParts[idxPart].index = host.getMortonIndex(); arrayOfParts[idxPart].indexInFile = idxPart; } diff --git a/Tests/noDist/testTreeBuilder.cpp b/Tests/noDist/testTreeBuilder.cpp index bf04e0a04928830ead0765ec7c5cb882982c7ca8..75b04fb8e3398eec388f13630b7599f367d9c613 100644 --- a/Tests/noDist/testTreeBuilder.cpp +++ b/Tests/noDist/testTreeBuilder.cpp @@ -181,7 +181,7 @@ int main(int argc, char** argv){ host.setZ( FCoordinateComputer::GetTreeCoordinate( arrayOfParts[idxPart].getPosition().getZ() - boxCorner.getZ(), boxWidth, boxWidthAtLeafLevel, NbLevels )); //Set Morton index from Tree Coordinate - arrayOfParts[idxPart].index = host.getMortonIndex(NbLevels - 1); + arrayOfParts[idxPart].index = host.getMortonIndex(); arrayOfParts[idxPart].indexInFile = idxPart; } diff --git a/UTests/utestChebyshevDirectPeriodic.cpp b/UTests/utestChebyshevDirectPeriodic.cpp index c492a74a4c1f8c331c28174a1dc175ffcbd47725..5475b8b10f5defcaf6a34da4415afecaaf5edb14 100644 --- a/UTests/utestChebyshevDirectPeriodic.cpp +++ b/UTests/utestChebyshevDirectPeriodic.cpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== @@ -483,7 +483,7 @@ class TestChebyshevDirect : public FUTester { const FTreeCoordinate boundaryCoord(realCoord.getX() + offsetAtLevel, realCoord.getY() + offsetAtLevel, realCoord.getZ() + offsetAtLevel); - const MortonIndex boundaryIndex = boundaryCoord.getMortonIndex(idxLevel + diffLevel); + const MortonIndex boundaryIndex = boundaryCoord.getMortonIndex(); uassert((boundaryIndex & ~((~0LL)<<3*idxLevel))== iter.getCurrentGlobalIndex()); @@ -545,7 +545,7 @@ class TestChebyshevDirect : public FUTester { const FTreeCoordinate boundaryCoord(realCoord.getX() + offsetAtLevel, realCoord.getY() + offsetAtLevel, realCoord.getZ() + offsetAtLevel); - const MortonIndex boundaryIndex = boundaryCoord.getMortonIndex(idxLevel + diffLevel); + const MortonIndex boundaryIndex = boundaryCoord.getMortonIndex(); uassert((boundaryIndex & ~((~0LL)<<3*idxLevel))== iter.getCurrentGlobalIndex()); @@ -638,7 +638,3 @@ class TestChebyshevDirect : public FUTester { // You must do this TestClass(TestChebyshevDirect) - - - - diff --git a/UTests/utestMorton.cpp b/UTests/utestMorton.cpp index 81e6f8484ab11d91f16310d1f3055a75dae62c7c..76fcceab9bfc46e35a39e9c959b70775a7c97db6 100644 --- a/UTests/utestMorton.cpp +++ b/UTests/utestMorton.cpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #include "FUTester.hpp" @@ -30,49 +30,49 @@ class TestMorton : public FUTester { { FTreeCoordinate pos(5,1,7); FTreeCoordinate cp; - cp.setPositionFromMorton(pos.getMortonIndex(10),10); + cp.setPositionFromMorton(pos.getMortonIndex()); uassert(pos == cp); - uassert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); + uassert(cp.getMortonIndex() == pos.getMortonIndex()); } { FTreeCoordinate pos(2,8,3); FTreeCoordinate cp; - cp.setPositionFromMorton(pos.getMortonIndex(10),10); + cp.setPositionFromMorton(pos.getMortonIndex()); uassert(pos == cp); - uassert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); + uassert(cp.getMortonIndex() == pos.getMortonIndex()); } { FTreeCoordinate pos(51,11,47); FTreeCoordinate cp; - cp.setPositionFromMorton(pos.getMortonIndex(10),10); + cp.setPositionFromMorton(pos.getMortonIndex()); uassert(pos == cp); - uassert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); + uassert(cp.getMortonIndex() == pos.getMortonIndex()); } } void Position(){ { FTreeCoordinate pos(0,0,0); - uassert(pos.getMortonIndex(1) == 0); + uassert(pos.getMortonIndex() == 0); } { FTreeCoordinate pos(1,1,1); - uassert(pos.getMortonIndex(1) == 7); + uassert(pos.getMortonIndex() == 7); } { FTreeCoordinate pos(0,1,1); - uassert(pos.getMortonIndex(1) == 3); + uassert(pos.getMortonIndex() == 3); } { FTreeCoordinate pos(2,2,2); - uassert(pos.getMortonIndex(2) == (7 << 3) ); + uassert(pos.getMortonIndex() == (7 << 3) ); } { FTreeCoordinate pos(1,2,4); - uassert(pos.getMortonIndex(3) == 84 );// 001 010 100 =>> 001010100 => 84d + uassert(pos.getMortonIndex() == 84 );// 001 010 100 =>> 001010100 => 84d } } - + // set test void SetTests(){ AddTest(&TestMorton::Morton,"Test Morton"); @@ -82,5 +82,3 @@ class TestMorton : public FUTester { // You must do this TestClass(TestMorton) - - diff --git a/UTests/utestMpiTreeBuilder.cpp b/UTests/utestMpiTreeBuilder.cpp index 25263a164de33f24ecb1a934b05e5268ae206ed9..795be7c03f8f582553e0f24acca932304588f0f2 100644 --- a/UTests/utestMpiTreeBuilder.cpp +++ b/UTests/utestMpiTreeBuilder.cpp @@ -129,7 +129,7 @@ class TestMpiTreeBuilder : public FUTesterMpi< class TestMpiTreeBuilder> { host.setZ( FCoordinateComputer::GetTreeCoordinate( arrayOfParticles[idxParts].getPosition().getZ() - boxCorner.getZ(), boxWidth, boxWidthAtLeafLevel, TreeHeight )); //Set Morton index from Tree Coordinate - arrayOfParticles[idxParts].index = host.getMortonIndex(TreeHeight - 1); + arrayOfParticles[idxParts].index = host.getMortonIndex(); } //Save the original array struct TestParticle * originalArray = new TestParticle[nbOfParticles]; diff --git a/UTests/utestNeighborIndexes.cpp b/UTests/utestNeighborIndexes.cpp index 17ca07de57e0065fd274ea5d93978c7a4a0f7e08..38aa0d0ade6fb8d0ed7b7d9bea72c977047e8381 100644 --- a/UTests/utestNeighborIndexes.cpp +++ b/UTests/utestNeighborIndexes.cpp @@ -35,7 +35,7 @@ class TestIndexes : public FUTester { for(int z = 0 ; z < 3 ; ++z){ const int zbox = (z*(limit-1))/2; - const MortonIndex mindex = FTreeCoordinate(xbox, ybox, zbox).getMortonIndex(idxLevel); + const MortonIndex mindex = FTreeCoordinate(xbox, ybox, zbox).getMortonIndex(); FCoordinateNeighborIndex coordindexes(mindex, idxLevel); FBitsNeighborIndex bitsindex(mindex, idxLevel); @@ -55,7 +55,7 @@ class TestIndexes : public FUTester { uassert(coordindexes.getIndex(idxX, idxY, idxZ) == bitsindex.getIndex(idxX, idxY, idxZ)); const MortonIndex neigh = bitsindex.getIndex(idxX, idxY, idxZ); - const FTreeCoordinate neighCoord(neigh, idxLevel); + const FTreeCoordinate neighCoord(neigh); uassert(xbox + idxX == neighCoord.getX()); uassert(ybox + idxY == neighCoord.getY()); uassert(zbox + idxZ == neighCoord.getZ()); @@ -80,7 +80,7 @@ class TestIndexes : public FUTester { const int ybox = int(drand48()*double(limit)); const int zbox = int(drand48()*double(limit)); - const MortonIndex mindex = FTreeCoordinate(xbox, ybox, zbox).getMortonIndex(idxLevel); + const MortonIndex mindex = FTreeCoordinate(xbox, ybox, zbox).getMortonIndex(); FCoordinateNeighborIndex coordindexes(mindex, idxLevel); FBitsNeighborIndex bitsindex(mindex, idxLevel); @@ -100,7 +100,7 @@ class TestIndexes : public FUTester { uassert(coordindexes.getIndex(idxX, idxY, idxZ) == bitsindex.getIndex(idxX, idxY, idxZ)); const MortonIndex neigh = bitsindex.getIndex(idxX, idxY, idxZ); - const FTreeCoordinate neighCoord(neigh, idxLevel); + const FTreeCoordinate neighCoord(neigh); uassert(xbox + idxX == neighCoord.getX()); uassert(ybox + idxY == neighCoord.getY()); uassert(zbox + idxZ == neighCoord.getZ()); @@ -125,7 +125,7 @@ class TestIndexes : public FUTester { for(int ybox = 0 ; ybox < limit ; ++ybox){ for(int zbox = 0 ; zbox < limit ; ++zbox){ - const MortonIndex mindex = FTreeCoordinate(xbox, ybox, zbox).getMortonIndex(idxLevel); + const MortonIndex mindex = FTreeCoordinate(xbox, ybox, zbox).getMortonIndex(); FCoordinateNeighborIndex coordindexes(mindex, idxLevel); FBitsNeighborIndex bitsindex(mindex, idxLevel); @@ -145,7 +145,7 @@ class TestIndexes : public FUTester { uassert(coordindexes.getIndex(idxX, idxY, idxZ) == bitsindex.getIndex(idxX, idxY, idxZ)); const MortonIndex neigh = bitsindex.getIndex(idxX, idxY, idxZ); - const FTreeCoordinate neighCoord(neigh, idxLevel); + const FTreeCoordinate neighCoord(neigh); uassert(xbox + idxX == neighCoord.getX()); uassert(ybox + idxY == neighCoord.getY()); uassert(zbox + idxZ == neighCoord.getZ()); @@ -167,12 +167,12 @@ class TestIndexes : public FUTester { const MortonIndex limit = FMath::pow2(idxLevel)*3L; for(MortonIndex idxV1 = 1 ; idxV1 < limit ; ++idxV1){ FBitsNeighborIndex bitsindex(idxV1, idxLevel); - const FTreeCoordinate coord1(idxV1, idxLevel); + const FTreeCoordinate coord1(idxV1); for(MortonIndex idxV2 = 0 ; idxV2 < limit ; ++idxV2){ const bool isneig = bitsindex.areNeighbors(idxV1, idxV2); - const FTreeCoordinate coord2(idxV2, idxLevel); + const FTreeCoordinate coord2(idxV2); const bool isreallyneig = (FMath::Abs(coord1.getX()-coord2.getX()) <= 1) && (FMath::Abs(coord1.getY()-coord2.getY()) <= 1) && (FMath::Abs(coord1.getZ()-coord2.getZ()) <= 1); @@ -195,6 +195,3 @@ class TestIndexes : public FUTester { // You must do this TestClass(TestIndexes) - - - diff --git a/Utils/noDist/FmmAlgorithmTsm.cpp b/Utils/noDist/FmmAlgorithmTsm.cpp index 3579231f9bf1bfacabd62b105f72cbc304282d4e..fc5a7426d05e1141f2af49336cbcf03806b95c49 100644 --- a/Utils/noDist/FmmAlgorithmTsm.cpp +++ b/Utils/noDist/FmmAlgorithmTsm.cpp @@ -4,13 +4,13 @@ // 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. -// +// 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.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== // @@ -221,7 +221,7 @@ struct TempMainStruct{ // for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ double pot = 0.0 , xx,yy,zz; - FPoint FF ; + FPoint FF{} ; for(int idxSrc = 0 ; idxSrc < nbSRC ; ++idxSrc){ xx = posX[idxPart]-tabSrc[idxSrc].position.getX(); yy = posY[idxPart]-tabSrc[idxSrc].position.getY(); @@ -254,5 +254,3 @@ int main(int argc, char** argv){ FRunIf::Run(order, argc, argv); return 0; } - -