Swarm-NG  1.1
Beginner tutorial for using the API

You can write your own scenarios for integrating ensembles and use parts and pieces of the Swarm-NG library for your C++ application.

In this tutorial we go through a simple C++ program to show you how you can use Swarm-NG library. You can find the source file at src/tutorials/tutorial_simple.cpp

We start at the first line of the program. You need to include needed headers to use the library.

Some standard C++ libraries

#include <iostream>

Include Swarm library headers. You may need to add other headers if you want to use More advanced feautures. But for simple ensemble creation and integration the following line should be enough

#include "swarm/swarm.h"

We define a shortcut; because we need to use cudaThreadSynchronize() after every GPU call to make sure that we are in-sync with GPU.

#define SYNC cudaThreadSynchronize()

All the Swarm-NG classes are enclodes in swarm namespace, a C++ tradition. (std is the standard library)

using namespace swarm;
using namespace std;

We define parameters for integration as constants so we can change them later. We set the destination time for 5 revolutions. Each revolution is 2 * pi radians.

const double destination_time = 5 * 2 * M_PI ;

Swarm uses the configuration data structure to pass most of parameters to creation functions Here we put all of our configuration items in a 2D string array.

const char * config_pairs[5][2] = {
{ "integrator" , "hermite" }
,{ "time_step", "0.001" }
,{ "log_writer", "null" }
,{ "nsys" , "4000" }
,{ "nbod" , "3" }
};

The easy way to create a config object is from a 2D array containing pairs of strings. You can also use swarm::config::load to load a configuration from a file. We use this config object to configure all parts of swarm. Note that not every function reads all the configuration items. For example, generate_ensemble only reads "nsys" and "nbod".

config cfg( config_pairs );

Since our program is short, we can put everything in the main function.

int main(int argc, char* argv[]){

First we create our reference ensemble. We use the automatic generation using generate_ensemble function This function creates a very stable ensemble of systems for us.

We have to make a copy of initial conditions. We would like to compare the results to initial conditions after integration

defaultEnsemble ens = ref.clone();

Initialize Swarm library. Basically, it initializes CUDA system and default logging system.

Select and create the integrator. While you can create an integrator by calling its constructor directly. It is recommended to use integrator::create since it gives you more flexibility at runtime. The create function looks in the swarm library and finds the integrator you requested from the list of available plugins.

Pintegrator integ = integrator::create(cfg);

Now we set-up the integrator for integrating.

First set the ensemble. For a GPU integrator, the GPU memory will be allocated.

integ->set_ensemble(ens);

Now set the destination time where we want to stop the integration.

integ->set_destination_time ( destination_time );

Need to synchronize because integrator::set_ensemble may upload data to GPU.

SYNC;

Now that everything is set-up, it is safe to pull the trigger and call the integrate method on integrator. Note that since we didn't set a logger for the integrator, it will use the default logging system.

integ->integrate();

Need to synchronize because integrate is a GPU call.

SYNC;

Once the integration done, we need to examine the data. The easiest check is to see if the systems have preserved energy.

find_max_energy_conservation_error is a utility function that compares two ensemble of systems. We compare our working ensemble ens to the unchanged ensemble ref.

double max_deltaE = find_max_energy_conservation_error(ens, ref );
std::cout << "Max Energy Conservation Error = " << max_deltaE << std::endl;

This concludes the program, at this point you will need to clean up the data and ensembles. But most of Swarm-NG objects are stored in reference-counter pointers and will be automatically deallocated by C++ runtime library.

return 0;
}

If you want to do more with Swarm-NG, you may consider looking into following classes

  • swarm::ensemble This is an abstarct class for ensembles, there are trivial methods to access the data in the ensemble. You can examine and change the ensemble the way you want.
  • swarm::defaultEnsemble The concrete class which contains memory management for ensembles. Use defaultEnsemble::create to create new ensembles. The arrays will be automatically allocated and de-allocated based on reference counting.
  • swarm::snapshot::load_text Use this utility function to load an ensemble from a text file.
  • swarm::snapshot::save_text Use this utility function to save an ensemble to a text file.
  • swarm::log::manager Most users won't need it because the default log manager is used by all integrators. But if you need multiple log streams, you need to create your own log manager and use it in integrators by integrator::set_log_manager method.

To find the complete listing of this tutorial look at src/tutorials/tutorial_simple.cpp in the source code repository.