This software is tested on Ubuntu 14.04LTS with the GCC compiler (version 5.4.1), and Clang compiler (version 3.8.0). See our Travis CI page for more details.
You will need to install a C++ compiler with C++14 support, and the CMake build software prior to using Aboria, which you can do on a Debian-based OS using
sudo apt-get install build-essential cmake
The only required dependency is the Boost library. Optional dependencies are The Visualization Toolkit, Eigen (version >= 3.3~beta1), H2Lib, Trust and OpenMP, all of which add extra functionality. To install all these dependencies in a Debian-based OS you can type
sudo apt-get install libboost-dev libvtk5-dev libeigen3-dev libthrust-dev
Note | |
---|---|
replace |
Note | |
---|---|
If you wish to use H2Lib you will need to download and compile the source manually |
Aboria is a header-only library, so at a minimum you will need to add the
Aboria/src
directory to your include path and
include the Aboria.h
header, e.g.
#include <Aboria.h>
If you wish to use any of the optional dependencies you will need to install, include and/or link the required library as normal, and define one or more of the following compiler definitions to "turn on" this functionality within Aboria
Table 1. Optional dependencies compiler definitions
Library Name |
Compiler definition |
---|---|
VTK |
HAVE_VTK |
Eigen |
HAVE_EIGEN |
H2Lib |
HAVE_H2LIB |
Thrust |
HAVE_THRUST |
If you are familiar with compiling C++ projects, this might be all the information you need to incorporate Aboria into your own build system. If you wish for more details, the following provides a step-by-step guide on compiling your first Aboria program, using the popular CMake build system.
First clone the Aboria GitHub repository like so
$ git clone https://github.com/martinjrobins/Aboria
Then copy and paste the code below into a C++ source file named getting_started.cpp
.
#include "Aboria.h" using namespace Aboria; int main() { /* * Create a 2d particle container type with one * additional variable "velocity", represented * by a 2d double vector */ ABORIA_VARIABLE(velocity, vdouble2, "velocity") typedef Particles<std::tuple<velocity>, 2> container_t; typedef typename container_t::position position; /* * create a particle set with size N */ const int N = 100; container_t particles(N); std::uniform_real_distribution<double> uni(0, 1); std::default_random_engine gen; for (int i = 0; i < N; ++i) { /* * set a random position, and initialise velocity */ get<position>(particles)[i] = vdouble2(uni(gen), uni(gen)); get<velocity>(particles)[i] = vdouble2(0, 0); } /* * write particle container to a vtk * unstructured grid file */ vtkWriteGrid("aboria", 0, particles.get_grid(true)); }
Now copy and paste the CMake config file below into another file called
CMakeLists.txt
. Note that this assumes that the Aboria
repository is in your current directory, which it will be if you just cloned
the repo using the git command above.
cmake_minimum_required(VERSION 2.8) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") # Boost find_package(Boost 1.50.0 REQUIRED serialization) list(APPEND LIBRARIES ${Boost_LIBRARIES}) list(APPEND INCLUDES ${Boost_INCLUDE_DIRS}) # VTK find_package(VTK REQUIRED) if (VTK_FOUND) add_definitions(-DHAVE_VTK) endif(VTK_FOUND) list(APPEND LIBRARIES ${VTK_LIBRARIES}) list(APPEND INCLUDES ${VTK_INCLUDE_DIRS}) # Aboria set(Aboria_LOG_LEVEL 1 CACHE STRING "Logging level (1 = least, 3 = most)") add_definitions(-DABORIA_LOG_LEVEL=${Aboria_LOG_LEVEL}) list(APPEND INCLUDES Aboria/src) list(APPEND INCLUDES Aboria/third-party) include_directories(src ${INCLUDES}) set(SOURCE getting_started.cpp ) add_executable(getting_started ${SOURCE}) target_link_libraries(getting_started ${LIBRARIES})
If you wish to use The Visualisation Toolkit
or Eigen with Aboria then
you will need to define the HAVE_VTK
and HAVE_EIGEN
compiler definitions, as done using the above CMakeLists.txt
Finally, configure and compile getting_started.cpp
, then run
it like so
$ cmake . $ make $ ./getting_started
You now should have a file aboria00000.vtu
in
your directory, which you can open and view using any application that supports
the VTK unstructured grid format (such as Paraview)
Aboria interfaces with the Eigen library to provide matrix-free linear operators, linear solvers and preconditioners. See aboria.evaluating_and_solving_kernel_op for more details.
Assuming you are using CMake as per the instructions above, you can include
Eigen in the build process by inserting the following into your CMakeLists.txt
# optional if you already have a `FindEigen3.cmake` on your system set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Aboria/cmake" ${CMAKE_MODULE_PATH}) # end optional find_package(Eigen3 REQUIRED) list(APPEND INCLUDES ${EIGEN3_INCLUDE_DIR}) add_definitions(-DHAVE_EIGEN)
The first line sets the CMAKE_MODULE_PATH
to search in the Aboria
cmake
directory for additional .cmake
files. This
is only necessary if you don't already have a FindEigen3.cmake
module or config file on your system and wish to use the one bundled with
Aboria.
The most important line for using the Eigen functionality within Aboria is
the add_definitions
instruction, which adds the HAVE_EIGEN
compiler definition. This definition is used to "turn on" all Eigen
functionality within Aboria.
Aboria uses The Visualisation Toolkit
to allow it to write out or read in particle data as a vtkUnstructuredGrid
.
The example CMakeLists.txt
above shows how you can add VTK to
the build process. The important lines are:
find_package(VTK REQUIRED) add_definitions(-DHAVE_VTK) list(APPEND LIBRARIES ${VTK_LIBRARIES}) list(APPEND INCLUDES ${VTK_INCLUDE_DIRS})
Aboria uses H2Lib for storing,
evaluating and solving hierarchical matrices. You can use the bundled FindH2Lib.cmake
to find H2Lib on your system. Note that you will need to download and compile
H2Lib first, according to their instructions. You will also need to enable
OpenMP, see below for more details on how to do this.
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Aboria/cmake" ${CMAKE_MODULE_PATH}) set(H2Lib_ROOT $ENV{HOME}/git/H2Lib) find_package(H2Lib REQUIRED) list(APPEND LIBRARIES ${H2Lib_LIBRARIES}) list(APPEND INCLUDES ${H2Lib_INCLUDE_DIRS}) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${H2Lib_LINKER_FLAGS}") add_definitions(-DHAVE_H2LIB)
Aboria can be run using multiple cores using OpenMP. The majority of parallel regions in Aboria are implemented using the OpenMP backend of Thrust, not raw OpenMP, so to get the best parallel performance Thrust should also be used.
To add OpenMP and Thrust to the build process, add the following to your
CMakeLists.txt
# OpenMP find_package(OpenMP REQUIRED) add_definitions(-DHAVE_OPENMP) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") # Thrust find_package(Thrust REQUIRED) add_definitions(-DHAVE_THRUST)
The parallel STL-like algorithms provided with Thrust are used to provide the majority of parallism in Aboria. It is possible to use the native CUDA backend of Thrust to run code on the GPU.
Caution | |
---|---|
This mode is experimental, and has not been thoroughly tested. It is also quite slow, so any pull requests to fix this are most welcome! |
There are a few restrictions on the code that you can write while using the
CUDA backend, and these are detailed in aboria.parallelism_in_aboria.cuda
(basically if you are already familiar with Thrust you should be comfortable
using the CUDA backend for Aboria). For now, just copy the following into
a getting_started.cu
file
#include "Aboria.h" using namespace Aboria; ABORIA_VARIABLE(cu_velocity, vdouble2, "velocity") int main() { typedef Particles<std::tuple<cu_velocity>, 2, thrust::device_vector, CellListOrdered> cu_container_t; typedef typename cu_container_t::position cu_position; /* * create a particle set with size N */ cu_container_t cu_particles(N); /* * set a random position */ thrust::tabulate(get<cu_position>(cu_particles).begin(), get<cu_position>(cu_particles).end(), [] __device__(const int i) { thrust::default_random_engine gen; thrust::uniform_real_distribution<float> uni(0, 1); gen.discard(i); return vdouble2(uni(gen), uni(gen)); }); /* * init velocity */ thrust::fill(get<cu_velocity>(cu_particles).begin(), get<cu_velocity>(cu_particles).end(), vdouble2(0, 0)); /* * write particle container to a vtk * unstructured grid file */ vtkWriteGrid("aboria", 0, particles.get_grid(true)); }
To enable the CUDA backend and compile the above source with the CUDA compiler
nvcc
, add the following to
your CMakeLists.txt
find_package(CUDA REQUIRED) set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} --expt-relaxed-constexpr --expt-extended-lambda -std=c++14") set(SOURCE_CU getting_started.cu ) cuda_add_executable(getting_started_cu ${SOURCE_CU}) target_link_libraries(getting_started_cu ${LIBRARIES})
For completness, here is a possible CMakeLists.txt
file
combining all the options shown above
cmake_minimum_required(VERSION 2.8) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Aboria/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") # Boost find_package(Boost 1.50.0 REQUIRED serialization) list(APPEND LIBRARIES ${Boost_LIBRARIES}) list(APPEND INCLUDES ${Boost_INCLUDE_DIRS}) # VTK find_package(VTK REQUIRED) if (VTK_FOUND) add_definitions(-DHAVE_VTK) endif(VTK_FOUND) list(APPEND LIBRARIES ${VTK_LIBRARIES}) list(APPEND INCLUDES ${VTK_INCLUDE_DIRS}) # H2Lib set(H2Lib_ROOT $ENV{HOME}/git/H2Lib) find_package(H2Lib REQUIRED) list(APPEND LIBRARIES ${H2Lib_LIBRARIES}) list(APPEND INCLUDES ${H2Lib_INCLUDE_DIRS}) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${H2Lib_LINKER_FLAGS}") add_definitions(-DHAVE_H2LIB) # OpenMP find_package(OpenMP REQUIRED) add_definitions(-DHAVE_OPENMP) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") # CUDA find_package(CUDA REQUIRED) set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} --expt-relaxed-constexpr --expt-extended-lambda -std=c++14") # Thrust find_package(Thrust REQUIRED) add_definitions(-DHAVE_THRUST) # Aboria set(Aboria_LOG_LEVEL 1 CACHE STRING "Logging level (1 = least, 3 = most)") add_definitions(-DABORIA_LOG_LEVEL=${Aboria_LOG_LEVEL}) list(APPEND INCLUDES Aboria/src) list(APPEND INCLUDES Aboria/third-party) include_directories(src ${INCLUDES}) set(SOURCE getting_started.cpp ) add_executable(getting_started ${SOURCE}) target_link_libraries(getting_started ${LIBRARIES}) set(SOURCE_CU getting_started.cu ) cuda_add_executable(getting_started_cu ${SOURCE_CU}) target_link_libraries(getting_started_cu ${LIBRARIES})