[gmx-developers] g_decorr and Multi-I/O
Mark Abraham
Mark.Abraham at anu.edu.au
Thu Nov 15 03:49:28 CET 2007
Hi,
I'm planning to implement Lyman & Zuckerman's method for determining a
trajectory "decorrelation time" (recently published in J. Phys. Chem. B
2007, 111, 12876-12882). I thought I'd make an initial stab at the
Multi-I/O developer project
(http://wiki.gromacs.org/index.php/Category:Development) while I was at
it. This aims to port the kind of functionality present in trjcat and
eneconv, i.e. accepting multiple trajectory files as input.
As a model, so far I've been looking at trjcat. The first complication
here is that the demuxing functionality built into trjcat has nothing to
do with the "normal" function. The clue here is that after the normal
initial file processing, there's an "if(bDeMux)" in trjcat.c that
controls the rest of the execution. So, I think this means there should
be a trjdemux utility. :-)
Anyway, back on point, there are two ways you could do this kind of
Multi-I/O thing : either
* read all of the relevant frames of the trajectory into memory (caveat
-b, -e and -dt) and then process, or
* loop over files and frames in them, accounting for -b, -e and -dt on
the fly, and using a callback function on each frame to actually do the
required work.
(You could implement the former as a special case of the latter, of course.)
I favour the second approach, but the routine that does the looping will
necessarily be ignorant of what the callback will be doing with the
frames, so you may need to pass data through the looping routine to the
callback. This kind of thing can be done in two ways.
1) The callback function takes a (void *) argument which it typecasts
back to a (struct *) to get the data it needs. This argument will have
to be passed to the looping routine, so it can pass it on. This probably
means creating a new struct for most callbacks, and ugly debugging
problems if you ever untypecast mismatching objects. It does mean you
can have libraries of callback functions, though. This sort of thing
gets much more elegant if one was to move to C++ at some hypothetical
time in the future.
2) The callback function is declared in the scope that already has the
data it needs, viz
typedef int t_trxread_callback();
int do_multi_trxread(t_trxread_callback callback);
int my_analysis_function() {
int local_var;
int my_analysis_callback() {
fprintf(stderr, "local_var is %d\n", local_var);
return 1;
}
do_multi_trxread(my_analysis_callback);
}
I'm not sure right now whether this means that the call to
do_multi_trxread also has to come from that scope, but it would usually
be convenient to do so. It does make it impossible to re-use callback
functions with recreating a new scope, however.
You could use both approaches - have a (void *) argument in the callback
function type, which you can pass as NULL to do_multi_trxread if your
callback either needs no data or is getting that data through its scope.
My preference is to encourage use of the first approach, but for some
one-off dirty jobs you might prefer the second in practice.
Does anybody have any feedback for me on the above design choices?
Mark
More information about the gromacs.org_gmx-developers
mailing list