#include #include #include #include #include "mdutil.h" #include "simfront.h" #undef NELEMS #define NELEMS(x) (sizeof(x)/sizeof((x)[0])) #undef MIN #define MIN(a,b) ( ((a)<(b)) ? (a) : (b) ) /* static constant variable */ static const char *Title[] = { "bond", "angle", "dihedral", "improper", "elec", "vdw", "bound", "kin", "pot", "total", "temp", }; /* prototypes for internal functions */ static MD_Int output_energy(void *info, MD_Callback_Data *cbdata, MD_Int len, MD_Int stepnum, MD_Int numer, MD_Int denom); #define WIDTH 19 #define STRWIDTH "19" #define REDUCFMT " %18.13g" int setup_callbacks(SimFront *sf) { MD_Sim *sim = sf->sim; MD_String *reduclabel; CallbackInfo *cbinfo = &(sf->cbinfo); MD_Callback_Data cbdata[1]; MD_Int idreduc, idreduclabel, len; MD_String sbuf; /* this is a length 64 array of char */ int i, j, k, cnt; const char *cs; idreduc = MD_lookup(sim, "Reduction"); idreduclabel = MD_lookup(sim, "ReductionLabel"); len = MD_getlen(sim, idreduc); reduclabel = (MD_String *) calloc(len, sizeof(MD_String)); MD_getdata(sim, idreduclabel, reduclabel, len, 0); MD_wait(sim); sprintf(cbinfo->reductitle, "%8s", "stepnum"); cnt = 8; strcpy(cbinfo->reducfmt, "%8d"); for (i = 0; i < len && cnt+WIDTH < NELEMS(cbinfo->reductitle); i++) { /* look through known titles */ for (j = 0; j < NELEMS(Title); j++) { k = MIN(MIN(strlen(reduclabel[i]), strlen(Title[j])), 8); if (mdutil_strncasecmp(reduclabel[i], Title[j], k) == 0) { strncpy(sbuf, Title[j], 8); sbuf[8] = '\0'; break; } } if (j == NELEMS(Title)) { /* * we didn't have a partial match with any of our titles -- * so try to obtain an abbrev for ith label by taking first * letter of each word in label -- * if result is length 1, then just use up to first 8 letters */ cs = reduclabel[i]; while (isspace(cs[0])) cs++; k = 0; sbuf[k++] = cs[0]; while ((cs = strchr(cs, ' ')) != NULL && k < 8) { if (cs[1] != ' ') { sbuf[k++] = cs[1]; cs++; } } sbuf[k] = '\0'; if (k == 1) { strncpy(sbuf, reduclabel[i], 8); sbuf[8] = '\0'; } } sprintf(cbinfo->reductitle + cnt, "%" STRWIDTH "s", sbuf); cnt += WIDTH; strcat(cbinfo->reducfmt, REDUCFMT); } strcat(cbinfo->reducfmt, "\n"); cbinfo->numcols = i; cbinfo->titlefreq = 20; cbdata[0].nelems = cbinfo->numcols; cbdata[0].first = 0; cbdata[0].attr.idnum = idreduc; cbdata[0].attr.access = MD_DATA_CBREAD; if (MD_set_callback(sim, output_energy, cbdata, 1, sf->energyfreq)) { ERRMSG(sf, MD_errmsg(sim)); return -1; } MD_setinfo(sim, cbinfo); return 0; } MD_Int output_energy(void *info, MD_Callback_Data *cbdata, MD_Int len, MD_Int stepnum, MD_Int numer, MD_Int denom) { /* trust MDAPI to pass us correct values */ CallbackInfo *cbinfo = (CallbackInfo *) info; double *reduc = (double *) (cbdata[0].data); int k; char buf[STRING_SIZE]; char *pbuf = buf; if (stepnum % cbinfo->titlefreq == 0) { printf("#%s\n", cbinfo->reductitle); } sprintf(pbuf, "%9d", stepnum); pbuf += 9; for (k = 0; k < cbinfo->numcols; k++) { sprintf(pbuf, REDUCFMT, reduc[k]); pbuf += WIDTH; } printf("%s\n", buf); /* printf("step %d:\n", stepnum); for (k = 0; k < cbdata[0].nelems; k++) { printf(" %s = %g\n", reduclabel[k], reduc[k]); } */ return 0; }