======== Examples ======== C++ Examples ------------ There are three major classes in exafmm-t: - ``Body``: The class for bodies (particles). - ``Node``: The class for nodes in the octree. - ``Fmm``: The FMM class. The choice of template parameter ``T`` depends on the data type of the potential: ``T`` should be set to ``real_t`` for real-valued kernels (ex. Laplace and modified Helmholtz), and set to ``complex_t`` for complex-valued kernels (ex. Helmholtz). exafmm-t uses double precision by default, i.e., ``real_t`` and ``complex_t`` are mapped to ``double`` and ``std::complex`` respectively. If you want to use single precision, you should still use ``real_t`` and ``complex_t`` in your code, and add ``-DFLOAT`` to your compiler flags which predefines the macro ``FLOAT`` as true. All exafmm-t's types, classes and functions are in ``exafmm_t`` namespace. API documentation can be found in the last section. Let's solve a Laplace N-body problem as an example, we first need to create ``sources`` and ``targets``. Here we create 100,000 sources and targets that are randomly distributed in a cube from -1 to 1. Their type ``Bodies`` is a STL vector of ``Body``. .. code-block:: cpp using exafmm_t::real_t; std::random_device rd; std::mt19937 gen(rd()); // random number generator std::uniform_real_distribution<> dist(-1.0, 1.0); int ntargets = 100000; int nsources = 100000; exafmm_t::Bodies sources(nsources); for (int i=0; i targets(ntargets); for (int i=0; i leafs, nonleafs; exafmm_t::Nodes nodes = exafmm_t::build_tree(sources, targets, leafs, nonleafs, fmm); exafmm_t::balance_tree(nodes, sources, targets, leafs, nonleafs, fmm); Next, we can build lists and pre-compute invariant matrices. .. code-block:: cpp exafmm_t::init_rel_coord(); // compute all possible relative positions of nodes for each FMM operator exafmm_t::set_colleagues(nodes); // find colleague nodes exafmm_t::build_list(nodes, fmm); // create list for each FMM operator fmm.M2L_setup(nonleafs); // an extra setup for M2L operator Finally, we can use FMM to evaluate potentials and gradients .. code-block:: cpp fmm.upward_pass(nodes, leafs); fmm.downward_pass(nodes, leafs); After the downward pass, the calculated potentials and gradients are stored in the leaf nodes of the tree. You can compute the error in L2 norm by comparing with direct summation: .. code-block:: cpp std::vector error = fmm.verify(leafs); std::cout << "potential error: " << error[0] << "\n" << "gradient error: " << error[1] << "\n"; Other examples can be found in ``examples/cpp`` folder. Python Examples --------------- For simplicity, the name of our Python package is just ``exafmm``. It has a separate module for each kernel: ``exafmm.laplace``, ``exafmm.helmholtz`` and ``exafmm.modified_helmholtz``. Compare with C++ interface, exafmm-t's Python interface only exposes high-level APIs. Now, the steps for tree construction, list construction and pre-computation are merged into one function called ``setup()``. Also, the evaluation now only requires to call one function ``evalute()``. Below are Python examples on Jupyter notebooks. - `Laplace `__ - `Helmholtz `__ - `Modified Helmholtz `__