/* read state of an individual constraint */ int dom_read_constraint (DOM *dom, PBF *bf, CON *con) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } /* read constraint */ for (; bf; bf = bf->next) { int ncon; if (PBF_Label (bf, "CONS")) { PBF_Int (bf, &ncon, 1); for (int n = 0; n < ncon; n ++) { CON *obj = read_constraint (dom, iover, bf); if (con->id == obj->id) { *con = *obj; MEM_Free (&dom->conmem, obj); /* not needed */ return 1; } else MEM_Free (&dom->conmem, obj); /* skip and continue */ } } } return 0; }
/* map rigid onto FEM state */ int dom_rigid_to_fem (DOM *dom, PBF *bf, SET *subset) { for (; bf; bf = bf->next) { if (PBF_Label (bf, "DOM")) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } ASSERT_TEXT (iover >= 3, "Output files are too old for RIGID_TO_FEM to work"); /* read body states */ if (subset) { #if POSIX for (SET *item = SET_First (subset); item; item = SET_Next (item)) { regex_t xp; char *pattern = item->data; int error = regcomp (&xp, pattern, 0); if (error != 0) { char *message = get_regerror (error, &xp); fprintf (stderr, "-->\n"); fprintf (stderr, "Regular expression ERROR --> %s\n", message); fprintf (stderr, "<--\n"); regfree (&xp); free (message); return 0; } for (BODY *bod = dom->bod; bod; bod = bod->next) { if (bod->label && regexec (&xp, bod->label, 0, NULL, 0) == 0) { if (PBF_Label (bf, bod->label)) { double conf [12], velo [6], energy [4]; int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); if (bod->kind == FEM && rkind == RIG) { PBF_Double (bf, conf, 12); PBF_Double (bf, velo, 6); PBF_Double (bf, energy, 4); BODY_From_Rigid (bod, conf, conf+9, velo, velo+3); } else { ASSERT_TEXT (((bod->kind == RIG || bod->kind == OBS) && (rkind == RIG || rkind == OBS)) || bod->kind == (unsigned)rkind, "Body kind mismatch when reading state"); ASSERT_TEXT (BODY_Conf_Size (bod) == rconf, "Body configuration size mismatch when reading state"); ASSERT_TEXT (bod->dofs == rdofs, "Body dofs size mismatch when reading state"); BODY_Read_State (bod, bf, 0); /* use 0 state to skip reading of rkind, rnconf, rdofs */ } } } } regfree (&xp); } #else ASSERT_TEXT (0, "Regular expressions require POSIX support --> recompile Solfec with POSIX=yes"); return 0; #endif } else { ASSERT (PBF_Label (bf, "BODS"), ERR_FILE_FORMAT); int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { double conf [12], velo [6], energy [4]; unsigned int id; BODY *bod; int rank; PBF_Uint (bf, &id, 1); bod = MAP_Find (dom->idb, (void*) (long) id, NULL); if (bod) /* update state of existing bodies only */ { int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); if (bod->kind == FEM && rkind == RIG) { PBF_Double (bf, conf, 12); PBF_Double (bf, velo, 6); PBF_Double (bf, energy, 4); if (bf->parallel == PBF_ON) { PBF_Int (bf, &rank, 1); } BODY_From_Rigid (bod, conf, conf+9, velo, velo+3); } else { ASSERT_TEXT (((bod->kind == RIG || bod->kind == OBS) && (rkind == RIG || rkind == OBS)) || bod->kind == (unsigned)rkind, "Body kind mismatch when reading state"); ASSERT_TEXT (BODY_Conf_Size (bod) == rconf, "Body configuration size mismatch when reading state"); ASSERT_TEXT (bod->dofs == rdofs, "Body dofs size mismatch when reading state"); BODY_Read_State (bod, bf, 0); /* use 0 state to skip reading of rkind, rnconf, rdofs */ } } else /* mock read */ { int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); double *conf; double *velo; double energy[10]; int rank; ERRMEM (conf = malloc (sizeof(double) * rconf)); ERRMEM (velo = malloc (sizeof(double) * rdofs)); PBF_Double (bf, conf, rconf); PBF_Double (bf, velo, rdofs); PBF_Double (bf, energy, BODY_ENERGY_SIZE(rkind)); if (bf->parallel == PBF_ON) { PBF_Int (bf, &rank, 1); } free (conf); free (velo); } } } } } return 1; }
/* initialize domain state */ int dom_init_state (DOM *dom, PBF *bf, SET *subset) { for (; bf; bf = bf->next) { if (PBF_Label (bf, "DOM")) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } ASSERT_TEXT (iover >= 3, "Output files are too old for INITIALISE_STATE to work"); /* read body states */ if (subset) { #if POSIX for (SET *item = SET_First (subset); item; item = SET_Next (item)) { regex_t xp; char *pattern = item->data; int error = regcomp (&xp, pattern, 0); if (error != 0) { char *message = get_regerror (error, &xp); fprintf (stderr, "-->\n"); fprintf (stderr, "Regular expression ERROR --> %s\n", message); fprintf (stderr, "<--\n"); regfree (&xp); free (message); return 0; } for (BODY *bod = dom->bod; bod; bod = bod->next) { if (bod->label && regexec (&xp, bod->label, 0, NULL, 0) == 0) { if (PBF_Label (bf, bod->label)) { BODY_Read_State (bod, bf, iover); } } } regfree (&xp); } #else ASSERT_TEXT (0, "Regular expressions require POSIX support --> recompile Solfec with POSIX=yes"); return 0; #endif } else { ASSERT (PBF_Label (bf, "BODS"), ERR_FILE_FORMAT); int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { unsigned int id; BODY *bod; PBF_Uint (bf, &id, 1); bod = MAP_Find (dom->idb, (void*) (long) id, NULL); if (bod) /* update state of existing bodies only */ { BODY_Read_State (bod, bf, iover); } else /* mock read */ { int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); double *conf; double *velo; double energy[10]; int rank; ERRMEM (conf = malloc (sizeof(double) * rconf)); ERRMEM (velo = malloc (sizeof(double) * rdofs)); PBF_Double (bf, conf, rconf); PBF_Double (bf, velo, rdofs); PBF_Double (bf, energy, BODY_ENERGY_SIZE(rkind)); if (bf->parallel == PBF_ON) { PBF_Int (bf, &rank, 1); } free (conf); free (velo); } } } } } return 1; }
/* read state of an individual body */ int dom_read_body (DOM *dom, PBF *bf, BODY *bod) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } if (bod->label) { for (; bf; bf = bf->next) { if (PBF_Label (bf, bod->label)) { BODY_Read_State (bod, bf, iover); return 1; } } } else { for (; bf; bf = bf->next) { if (PBF_Label (bf, "BODS")) { int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { unsigned int id; BODY *obj; PBF_Uint (bf, &id, 1); ASSERT_DEBUG_EXT (obj = MAP_Find (dom->idb, (void*) (long) id, NULL), "Body id invalid"); if (bod->id == obj->id) { BODY_Read_State (bod, bf, iover); return 1; } else /* skip body and continue */ { BODY fake; ERRMEM (fake.conf = malloc (sizeof (double [BODY_Conf_Size (obj)]))); ERRMEM (fake.velo = malloc (sizeof (double [obj->dofs]))); fake.shape = NULL; BODY_Read_State (&fake, bf, iover); free (fake.conf); free (fake.velo); } } } } } return 0; }
/* read domain state */ void dom_read_state (DOM *dom, PBF *bf) { BODY *bod, *next; int ncon; /* clear contacts */ MAP_Free (&dom->mapmem, &dom->idc); MEM_Release (&dom->conmem); dom->con = NULL; dom->ncon = 0; /* read all bodies if needed */ if (!dom->allbodiesread) read_new_bodies (dom, bf); /* mark all bodies as absent */ for (bod = dom->bod; bod; bod = bod->next) bod->flags |= BODY_ABSENT; SET *usedlabel = NULL; for (; bf; bf = bf->next) { if (PBF_Label (bf, "DOM")) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } /* read time step */ ASSERT (PBF_Label (bf, "STEP"), ERR_FILE_FORMAT); PBF_Double (bf, &dom->step, 1); /* read constraints merit */ ASSERT (PBF_Label (bf, "MERIT"), ERR_FILE_FORMAT); PBF_Double (bf, &dom->merit, 1); /* read body states */ ASSERT (PBF_Label (bf, "BODS"), ERR_FILE_FORMAT); int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { unsigned int id; PBF_Uint (bf, &id, 1); bod = MAP_Find (dom->idb, (void*) (long) id, NULL); if (bod == NULL) /* pick from all bodies set */ { ASSERT_DEBUG_EXT (bod = MAP_Find (dom->allbodies, (void*) (long) id, NULL), "Body id invalid"); if (bod->label) { MAP *node = MAP_Find_Node (dom->lab, bod->label, (MAP_Compare)strcmp); if (node) { node->data = bod; /* body fregments can inherit labels */ SET_Insert (NULL, &usedlabel, bod->label, (SET_Compare)strcmp); } else MAP_Insert (&dom->mapmem, &dom->lab, bod->label, bod, (MAP_Compare) strcmp); } MAP_Insert (&dom->mapmem, &dom->idb, (void*) (long) bod->id, bod, NULL); bod->next = dom->bod; if (dom->bod) dom->bod->prev = bod; dom->bod = bod; bod->dom = dom; dom->nbod ++; } BODY_Read_State (bod, bf, iover); bod->flags &= ~BODY_ABSENT; } /* read constraints */ ASSERT (PBF_Label (bf, "CONS"), ERR_FILE_FORMAT); PBF_Int (bf, &ncon, 1); for (int n = 0; n < ncon; n ++) { CON *con; con = read_constraint (dom, iover, bf); MAP_Insert (&dom->mapmem, &dom->idc, (void*) (long) con->id, con, NULL); con->next = dom->con; if (dom->con) dom->con->prev = con; dom->con = con; } dom->ncon += ncon; } } /* remove absent bodies */ for (bod = dom->bod; bod; bod = next) { next = bod->next; if (bod->flags & BODY_ABSENT) { if (bod->label && !SET_Contains (usedlabel, bod->label, (SET_Compare)strcmp)) MAP_Delete (&dom->mapmem, &dom->lab, bod->label, (MAP_Compare) strcmp); MAP_Delete (&dom->mapmem, &dom->idb, (void*) (long) bod->id, NULL); if (bod->next) bod->next->prev = bod->prev; if (bod->prev) bod->prev->next = bod->next; else dom->bod = bod->next; dom->nbod --; } } SET_Free (NULL, &usedlabel); /* attach constraints to bodies */ dom_attach_constraints (dom); }
/* write domain state */ void dom_write_state (DOM *dom, PBF *bf, SET *subset) { /* mark domain output */ PBF_Label (bf, "DOM"); #if IOVER >= 3 /* write iover */ PBF_Label (bf, "IOVER"); int iover = ABS (dom->solfec->iover); PBF_Int (bf, &iover, 1); #endif /* write time step */ PBF_Label (bf, "STEP"); PBF_Double (bf, &dom->step, 1); /* write constraints merit */ PBF_Label (bf, "MERIT"); PBF_Double (bf, &dom->merit, 1); /* write complete data of newly created bodies and empty the newly created bodies set */ write_new_bodies (dom); /* writing is done to a separate file */ SET_Free (&dom->setmem, &dom->newb); /* write regular bodies (this also includes states of newly created ones) */ PBF_Label (bf, "BODS"); if (subset) { int nbod = SET_Size (subset); PBF_Int (bf, &nbod, 1); } else PBF_Int (bf, &dom->nbod, 1); for (BODY *bod = dom->bod; bod; bod = bod->next) { if (subset && !SET_Find (subset, (void*) (long) bod->id, NULL)) continue; PBF_Uint (bf, &bod->id, 1); if (bod->label) PBF_Label (bf, bod->label); /* label body record for fast access */ BODY_Write_State (bod, bf); } /* write constraints */ PBF_Label (bf, "CONS"); if (subset) { int ncon = 0; for (CON *con = dom->con; con; con = con->next) { if (subset) { if (!SET_Find (subset, (void*) (long) con->master->id, NULL)) continue; if (con->slave && !SET_Find (subset, (void*) (long) con->slave->id, NULL)) continue; } ncon ++; } PBF_Int (bf, &ncon, 1); } else PBF_Int (bf, &dom->ncon, 1); for (CON *con = dom->con; con; con = con->next) { if (subset) { if (!SET_Find (subset, (void*) (long) con->master->id, NULL)) continue; if (con->slave && !SET_Find (subset, (void*) (long) con->slave->id, NULL)) continue; } write_constraint (con, bf); } }
static int read (PBF *bf, int n) { char *pstr = NULL; double d; float f; unsigned long ul; long l; unsigned int ui; int i; unsigned short us; short s; unsigned char uc; char c; char _str [512]; double _d = (double)n; float _f = (float)n; unsigned long _ul = (unsigned long)n; long _l = (long)n; unsigned int _ui = (unsigned int)n; int _i = n; unsigned short _us = (unsigned short) (n % 32767); short _s = (short) (n % 32767); unsigned char _uc = (unsigned char) (n % 127); char _c = (char) (n % 127); sprintf (_str, "CURRENT NUMBER IS %d", n); PBF_Time (bf, &d); if (d != (double)n) return 0; PBF_String (bf, &pstr); PBF_Double (bf, &d, 1); PBF_Float (bf, &f, 1); PBF_Ulong (bf, &ul, 1); PBF_Long (bf, &l, 1); PBF_Uint (bf, &ui, 1); PBF_Int (bf, &i, 1); PBF_Ushort (bf, &us, 1); PBF_Short (bf, &s, 1); PBF_Uchar (bf, &uc, 1); PBF_Char (bf, &c, 1); if (strcmp (pstr, _str) != 0 || d != _d || f != _f || ul != _ul || l != _l || ui != _ui || i != _i || us != _us || s != _s || uc != _uc || c != _c) return 0; free (pstr); pstr = NULL; d = 0.; f = 0.; ul = 0; l = 0; ui = 0; i = 0; us = 0; s = 0; uc = 0; c = 0; PBF_Label (bf, "STRING"); PBF_String (bf, &pstr); PBF_Label (bf, "DOUBLE"); PBF_Double (bf, &d, 1); PBF_Label (bf, "FLOAT"); PBF_Float (bf, &f, 1); PBF_Label (bf, "ULONG"); PBF_Ulong (bf, &ul, 1); PBF_Label (bf, "LONG"); PBF_Long (bf, &l, 1); PBF_Label (bf, "UINT"); PBF_Uint (bf, &ui, 1); PBF_Label (bf, "INT"); PBF_Int (bf, &i, 1); PBF_Label (bf, "USHORT"); PBF_Ushort (bf, &us, 1); PBF_Label (bf, "SHORT"); PBF_Short (bf, &s, 1); PBF_Label (bf, "UCHAR"); PBF_Uchar (bf, &uc, 1); PBF_Label (bf, "CHAR"); PBF_Char (bf, &c, 1); if (strcmp (pstr, _str) != 0 || d != _d || f != _f || ul != _ul || l != _l || ui != _ui || i != _i || us != _us || s != _s || uc != _uc || c != _c) return 0; free (pstr); return 1; }
static void write (PBF *bf, int n) { char str [512], *pstr = str; double d = (double)n; float f = (float)n; unsigned long ul = (unsigned long)n; long l = (long)n; unsigned int ui = (unsigned int)n; int i = n; unsigned short us = (unsigned short) (n % 32767); short s = (short) (n % 32767); unsigned char uc = (unsigned char) (n % 127); char c = (char) (n % 127); sprintf (str, "CURRENT NUMBER IS %d", n); /* output time */ PBF_Time (bf, &d); /* write unlabled data */ PBF_String (bf, &pstr); PBF_Double (bf, &d, 1); PBF_Float (bf, &f, 1); PBF_Ulong (bf, &ul, 1); PBF_Long (bf, &l, 1); PBF_Uint (bf, &ui, 1); PBF_Int (bf, &i, 1); PBF_Ushort (bf, &us, 1); PBF_Short (bf, &s, 1); PBF_Uchar (bf, &uc, 1); PBF_Char (bf, &c, 1); /* write labeled data */ PBF_Label (bf, "STRING"); PBF_String (bf, &pstr); PBF_Label (bf, "DOUBLE"); PBF_Double (bf, &d, 1); PBF_Label (bf, "FLOAT"); PBF_Float (bf, &f, 1); PBF_Label (bf, "ULONG"); PBF_Ulong (bf, &ul, 1); PBF_Label (bf, "LONG"); PBF_Long (bf, &l, 1); PBF_Label (bf, "UINT"); PBF_Uint (bf, &ui, 1); PBF_Label (bf, "INT"); PBF_Int (bf, &i, 1); PBF_Label (bf, "USHORT"); PBF_Ushort (bf, &us, 1); PBF_Label (bf, "SHORT"); PBF_Short (bf, &s, 1); PBF_Label (bf, "UCHAR"); PBF_Uchar (bf, &uc, 1); PBF_Label (bf, "CHAR"); PBF_Char (bf, &c, 1); }
int main (int argc, char **argv) { char *s, str [512]; int n, nmax; double d; PBF *bf; if (argc == 1) { printf ("pbftest [NUMBER OF SAMPLES] [COMPRESSION FLAG]\n"); return 0; } if (argc >= 2 && isdigit (argv [1][0])) nmax = atoi (argv [1]); else nmax = 10; bf = PBF_Write ("pbftest.state"); if (argc >= 3) { if (atoi (argv [2]) == 1) { bf->compression = PBF_ON; /* enable compression */ } } for (n = 1; n <= nmax; n ++) write (bf, n); PBF_Close (bf); bf = PBF_Read ("pbftest.state"); for (n = 1; n <= nmax; n ++) { if (!read (bf, n)) { fprintf (stderr, "FAILED (reading all)\n"); return 1; } PBF_Forward (bf, 1); } /* read every third double */ PBF_Seek (bf, 0); for (n = 1; n <= nmax; n += 3) { PBF_Label (bf, "DOUBLE"); PBF_Double (bf, &d, 1); if (d != (double) n) { fprintf (stderr, "FAILED (forward reading every 3rd labeled double)\n"); return 1; } PBF_Forward (bf, 3); } /* read every fifth string */ PBF_Seek (bf, 0); for (n = 1; n <= nmax; n += 5) { PBF_Label (bf, "STRING"); s = NULL; PBF_String (bf, &s); sprintf (str, "CURRENT NUMBER IS %d", n); if (strcmp (s, str) != 0) { fprintf (stderr, "FAILED (forward reading every 5th labeled string)\n"); return 1; } PBF_Forward (bf, 5); free (s); } /* do the same backwards */ PBF_Seek (bf, nmax); for (n = nmax; n >= 1; n -= 3) { PBF_Label (bf, "DOUBLE"); PBF_Double (bf, &d, 1); if (d != (double) n) { fprintf (stderr, "FAILED (backward reading every 3rd labeled double)\n"); return 1; } PBF_Backward (bf, 3); } PBF_Seek (bf, nmax); for (n = nmax; n >= 1; n -= 5) { PBF_Label (bf, "STRING"); s = NULL; PBF_String (bf, &s); sprintf (str, "CURRENT NUMBER IS %d", n); if (strcmp (s, str) != 0) { fprintf (stderr, "FAILED (forward reading every 5th labeled string)\n"); return 1; } PBF_Backward (bf, 5); free (s); } PBF_Close (bf); printf ("PASSED\n"); return 0; }