This documentation is mainly for using the library than for exteding it. However there are some class diagrams and class documentations to get some deeper insight to ISAAC nevertheless.
For hints how to install the library please have a look the INSTALL.MD documentation. This also explains the requirements to use the ISAAC library.
After you managed to add ISAAC to your build process (easiest with using CMake) first you need to include ISAAC with
ISAAC is a template libary, which compiles supports for your fields (called "sources" in ISAAC) direct into its render kernel. This has the benefit, that the access of your simulation data is high optimized. However you can't add sources later, but add as many as you want and deactivate them at runtime if not needed. ISAAC is very metaprogramming based. That means, that you need to define your fields as classes and to add them to a metaprogramming list, which can be evaluated at compile time. It should not be a barrir if you never worked with C++ metaprogramming before. Most of the commands used in the interface are easy to understand resp. to copy and paste.
For every source an own class needs to be defined. This class has to implement this following things:
static const size_t feature_dim
: containing the feature dimension of the source. For a vector field this would be e.g. most probably 3, for a scalar field 1. static const bool has_guard
determines, whether the source has a guard for access of data outside the later defined local dimensions. static const bool persistent
determines, whether ths source is persistent or needs to be copied after calling the update function. ISAAC_HOST_INLINE void update(bool enabled)
. The definition has to look exactly like this. This function is called right before the rendering and before update is called for the next source the data will be copied for non persistent sources. enabled
tells you, whether the source will be drawn at all. It is up to you to not update arrays in that case. Non persistent sources will be not accessed at all in that case. ISAAC_HOST_INLINE static std::string getName()
has to return the name of the source. []
operator, which looks like this: nIndex
in the ISAAC data format isaac_float_dim
, which is an struct like this: value
has the members .x
, .y
, .z
and/or .w
depending on the feature dimension of your source. Everything else in the class is up to you, but keep in mind, it may be copied from time to time, so be careful with memory in constructors and destructors.
For a working example of such classes have a look at the example.cpp. If you are using CUDA™, you can ignore all ISAAC_ALPAKA
ifdefs and only look at the CUDA™ else branch. I will continue explaining using the CUDA™ example code. If you are using Alpaka you should understand the Alpaka specific differences yourself.
Now you need a boost::fusion::list
with all your classes like
sources
is needed for the initialization of ISAAC, which is happening now with the creation of an instance of isaac::IsaacVisualization.
with the template parameters
SimDim
is an integral type containing the dimension of the simulation, e.g. boost::mpl::int_<3>
. SourceList
is the type we defined earlier containing a boost fusion list of source classes. std::vector<size_t>
is the type used for storing the dimension of the global and local volume and the position of the second in the first. 1024
is the size of the transfer function used for every source. std::vector<float>
is a user defined type of scaling. isaac::DefaultController
is a trait for setting up the projection, may be changed for stereoscopy. isaac::DefaultCompositor
is a trait for combining or postprocessing the rendered image(s), may be changed for stereoscopy. and the contructor parameters
name
: The name of the vizualisation. 0
: The rank, which will communicate with the ISAAC server. server
: the url of the server. port
: the port of the server. framebuffer_size
: A vector containing the width and height of the rendered image. global_size
: The size of the whole volume. local_size
: The size of the local subvolume. position
: The position of the local subvolume in the global volume. sources
: The just created runtime instance of the SourceList. scaling
: An optional scaling of the simulation data. Now it is possible to define and describe some metadata the client shall see. It doesn't need to be defined at this point, but every here defined datum will be shown in the list of available simulations. visualization->getJsonMetaRoot()
returns an instance of json_t*
, a json root , where you can add more members. See the example and the Jansson documentation for more details.
After defining the metadata we can now connect to the ISAAC server with visualization->init()
. If 0 is returned the connection is established.
Everytime you want to send a rendered view of your data (e.g. after ever time step of your simulation) call visualization->doVisualization(META_MASTER);
META_MASTER means
, that only the master rank (in most cases rank 0) will send meta data. If you choose META_MERGE
the meta data of every rank is merged via MPI before. To add meta data just use visualization->getJsonMetaRoot()
again before calling the isaac::IsaacVisualization::doVisualization method. After this function call the returned json root from getJsonMetaRoot
is empty again.
doVisualization
itself returns a json_t*
root, too. Every data put into "metadata"
from the client will be forwarded to every application rank. You have to call json_decref
to the result of this function! Even if you don't want to use the meta data, call it at least this way:
Otherwise you will open a memory leak.
At the end of the simulation just delete the visualization object. The connection will close and the simulation will disappear for every client of the ISAAC server.