Skip to content
Snippets Groups Projects
kira_parti.cc 4.22 KiB
Newer Older
slevy's avatar
slevy committed
#ifdef USE_KIRA

#include "worldline.h"

// #define CAVE 1		// NewN: use potentially-shared-memory malloc
#include "shmem.h"
#include "specks.h"
#include "partiviewc.h"

#include "kira_parti.h"		// declare following as extern "C"


extern struct specklist *get_parti( struct stuff *st, double realtime );

typedef worldbundle *worldbundleptr;
struct worldstuff {
    int nh;
    worldbundleptr *wh;
    int ih;			// current worldbundle index
    real tmin, tmax;
    real tcur;			// current time
    real treq;			// requested time
    struct specklist *sl;
};

int open_parti(struct stuff *st, char *filename, int verbose)
{
    ifstream s(filename);
    if (!s) {
	msg("Data file %s not found.", filename);
	return 0;
    }

    worldbundle *wb;
    struct worldstuff *ww = new worldstuff;
    ww->wh = new worldbundleptr[1024];

    ww->nh = 0;
    while (ww->nh < 1024 && (wb = read_bundle(s, verbose)))
	ww->wh[ww->nh++] = wb;

    if (ww->nh == 0) {
	msg("Data file %s not in worldbundle format.", filename);
	return 0;
    }

    ww->ih = 0;
    ww->tmin = ww->wh[0]->get_t_min();
    ww->tmax = ww->wh[ww->nh-1]->get_t_max();
    ww->sl = NULL;
    ww->tcur = ww->treq = -1.0;		// invalid

    st->dyndata = 1;
    st->dyndatafunc = get_parti;
    st->dyndatadata = ww;

    s.close();
    return 1;
}

double get_parti_time( struct stuff *st ) {
    if(st->dyndatadata == NULL)
	return 0.0;
    return ((struct worldstuff *)(st->dyndatadata))->tcur;
}

void set_parti_time( struct stuff *st, double reqtime ) {
    if(st->dyndatadata == NULL)
	return;
    // otherwise please seek to requested time ...
}

int get_parti_time_range( struct stuff *st, double *tmin, double *tmax )
{
    struct worldstuff *ww = (struct worldstuff *)st->dyndatadata;
    if(ww == NULL) {
	*tmin = 0, *tmax = 1;
	return 0;
    }

    *tmin = ww->tmin;
    *tmax = ww->tmax;
    return 1;
}

void convert_relative_to_absolute(dyn* b)
{
    if (b->get_parent()) b->inc_pos(b->get_parent()->get_pos());
    for_all_daughters(dyn, b, bb) convert_relative_to_absolute(bb);
}

struct specklist *to_parti(dyn *root, struct stuff *st, struct specklist *sl)
{
    if(sl == NULL) {
	// Use NewN to allocate these in (potentially) shared memory,
	// rather than new which will allocate in local malloc pool.
	// Needed for virdir/cave version.
        sl = NewN( struct specklist, 1 );
	memset(sl, 0, sizeof(*sl));
	sl->bytesperspeck = SMALLSPECKSIZE(3);
	sl->specks = NewNSpeck(sl, 2*root->n_leaves());
	sl->scaledby = 1;
    }
    int nspecks = 0;
    struct speck *sp = sl->specks;

    // fields:
    //  [0] id
    //  [1] mass
    //  [2] number in clump

    convert_relative_to_absolute(root);
    for_all_nodes(dyn, root, b) {
	if (b != root) {
	    sp->p.x[0] = b->get_pos()[0];
	    sp->p.x[1] = b->get_pos()[1];
	    sp->p.x[2] = b->get_pos()[2];

	    // Field 2 lists the number of stars in the current clump
	    // (1 for single stars, >1 for multiples, <0 for CM nodes).

	    if (b->is_leaf()) {
		sp->val[0] = b->get_index();
		sp->val[2] = b->get_top_level_node()->n_leaves();
	    } else {
		sp->val[0] = -1;
		sp->val[2] = -b->get_top_level_node()->n_leaves();
	    }

	    // Field 1 is mass.

	    sp->val[1] = b->get_mass();

	    // Offset unperturbed binaries by 100 in field 2.

	    if (b->is_low_level_node()) {
		dyn *bb = b;
		while (bb->get_elder_sister())
		    bb = bb->get_elder_sister();
		if (bb->get_kepler()) sp->val[2] += 100;
	    }
	    nspecks++;
	    sp = NextSpeck(sp, sl, 1);
	}
    }
    sl->nspecks = nspecks;
    return sl;
}

struct specklist *get_parti( struct stuff *st, double realtime )
{
    struct worldstuff *ww = (struct worldstuff *)(st->dyndatadata);

    if (!ww)
	return NULL;


    ww->treq = realtime;

    if (realtime < ww->tmin) realtime = ww->tmin;
    if (realtime > ww->tmax) realtime = ww->tmax;

    if (ww->tcur == realtime)
	return ww->sl;

    int ih = ww->ih;
    int nh = ww->nh;

    worldbundle *wb = ww->wh[ih];
    for(; realtime > wb->get_t_max() && ih < nh-1; ih++, wb = ww->wh[ih])
	;
    for(; realtime < wb->get_t_min() && ih > 0; ih--, wb = ww->wh[ih])
	;

    dyn *root = create_interpolated_tree(wb, realtime);
    ww->sl = to_parti(root, st, ww->sl);
    rmtree(root);

    ww->ih = ih;
    ww->tcur = realtime;

    return ww->sl;
}

#endif /*USE_KIRA*/