Numerous programming aids and conventions have become established during the development of Starlab. While we do not impose any particular style, we describe here a general format which we have found useful. As an example, here is a simple program (based on and equivalent to the Starlab to_com tool) that reads in a dyn snapshot from stdin (by inheritance, it also will work with _dyn_, hdyn, etc. data), shifts to the center-of-mass frame, and writes the result to stdout. For simplicity, we assume a flat (i.e. single-level) tree. An annotated version (see the "//--" comments) of the program follows:
//// Sample Starlab tool: Bring all positions and velocities
//// to the center-of-mass frame.
////
//// Options: -c add a comment to the output snapshot [false]
//-- initial "////" lines
//-- serve as documentation
//-- for the program
#include "dyn.h" //-- tool will operate
//-- on dyn data
local void shift_to_com(dyn *b) //-- local is a Starlab
//-- synonym for static
{
// Compute the center of mass.
real total_mass = 0; //-- "real" is double
vec com_pos = 0; //-- "vec" is an array
vec com_vel = 0; //-- of 3 reals, with all
//-- arithmetic operations
//-- properly defined
for_all_daughters(dyn, b, d) { //-- Starlab macro to
//-- loop over all dyn
//-- daughters d of base
//-- node b; also have:
//-- for_all_nodes
//-- for_all_leaves
total_mass += d->get_mass(); //-- real member function
//-- get_mass() accesses
//-- dyn mass
com_pos += d->get_mass() //-- similarly for vector
* d->get_pos(); //-- member functions
com_vel += d->get_mass() //-- get_pos() and get_vel()
* d->get_vel();
}
com_pos /= total_mass;
com_vel /= total_mass;
// Shift all positions and velocities.
for_all_daughters(dyn, b, d) {
d->inc_pos(-com_pos); //-- equivalently, could use
d->inc_vel(-com_vel); //--
} //-- d->set_pos(d->get_pos()
//-- - com_pos);
//--
//-- etc.
// Add an entry to the root log story. //-- conventional to
//-- document such changes
char tmp[128];
sprintf(tmp, " modified system center of mass at time %f",
b->get_system_time());
b->log_comment(tmp); //-- places the string in
//-- the log story of the
//-- system root node
putvq(b->get_log_story(), //-- places a line of the
"old_com_pos", com_pos); //-- form
//--
//-- old_com_pos = x y z
//--
//-- in the root log story
}
main(int argc, char *argv[])
{
check_help(); //-- if "--help" appears on
//-- the command line, print
//-- verbatim any line in
//-- this file beginning
//-- with "////"
// Parse the command line.
extern char *poptarg;
int c;
char* param_string = "c:"; //-- list of legal command-
//-- line arguments; a colon
//-- (":") indicates that a
//-- value must be supplied
//-- on the command line
bool c_flag = false;
char *comment;
while ((c = pgetopt(argc, argv, param_string)) != -1)
switch(c) {
case 'c': c_flag = TRUE; //-- poptarg points to the
comment = poptarg; //-- relevant item on the
break; //-- argument list
case '?': params_to_usage(cerr, argv[0], param_string);
get_help();
exit(1);
}
dyn *b; //-- pointer to the root node
while (b = get_dyn(cin)) { //-- read the next input
//-- snapshot from stdin
if (c_flag) b->log_comment(comment); //-- conventional to
b->log_history(argc, argv); //-- document program use
shift_to_com(b); //-- do the work!
put_dyn(b, cout); //-- write snapshot to stdout
rmtree(b); //-- recursively delete the
//-- tree structure
}
}
(This example has quite a few extra bells and whistles. A minimal
``stripped-down'' version is given here.)
In order to build your own Starlab tool, you will need to link it with the Starlab header files and libraries. As of version 4.0, the simplest way to do this is to use make with the following lines in your Makefile:
CXXFLAGS = -I$(STARLAB_INSTALL_PATH)/include/starlab -DHAVE_CONFIG_H
LDLIBS = -L$(STARLAB_INSTALL_PATH)/lib/starlab \
-lhdyn -l_dyn_ -ldyn -lsstar -lnode -lstd -lm
Then, to build program from program.C or
program.cc, just say
make program
and the rest is automatic. You may have to experiment with the
libraries depending on your application. Some of those listed above
may not be necessary -- for example, you won't need the star
libraries for pure dynamics, you won't need -lhdyn for
dyn applications, etc.