1 | /****************************************************************************/ |
---|
2 | /* TREEIO.C: I/O routines for hierarchical N-body code. Public routines: */ |
---|
3 | /* inputdata(), startoutput(), output(), savestate(), restorestate(). */ |
---|
4 | /* Copyright (c) 2001 by Joshua E. Barnes, Honolulu, Hawai`i. */ |
---|
5 | /****************************************************************************/ |
---|
6 | |
---|
7 | #include "stdinc.h" |
---|
8 | #include "mathfns.h" |
---|
9 | #include "vectmath.h" |
---|
10 | #include "getparam.h" |
---|
11 | #include "treecode.h" |
---|
12 | |
---|
13 | #include <sys/types.h> |
---|
14 | #include <sys/stat.h> |
---|
15 | #include <strings.h> |
---|
16 | |
---|
17 | /* |
---|
18 | * Prototypes for local routines. |
---|
19 | */ |
---|
20 | |
---|
21 | local void outputdata(void); /* write N-body data */ |
---|
22 | local void diagnostics(void); /* eval N-body diagnostics */ |
---|
23 | local void in_int(stream, int *); /* input integer value */ |
---|
24 | local void in_real(stream, real *); /* input real value */ |
---|
25 | local void in_vector(stream, vector); /* input vector of reals */ |
---|
26 | local void out_int(stream, int); /* output integer value */ |
---|
27 | local void out_real(stream, real); /* output real value */ |
---|
28 | local void out_vector(stream, vector); /* output vector of reals */ |
---|
29 | |
---|
30 | /* |
---|
31 | * Diagnositc output variables. |
---|
32 | */ |
---|
33 | |
---|
34 | local real mtot; /* total mass of system */ |
---|
35 | local real etot[3]; /* Etot, KE, PE of system */ |
---|
36 | local matrix keten; /* kinetic energy tensor */ |
---|
37 | local matrix peten; /* potential energy tensor */ |
---|
38 | local vector cmpos; /* center of mass position */ |
---|
39 | local vector cmvel; /* center of mass velocity */ |
---|
40 | local vector amvec; /* angular momentum vector */ |
---|
41 | |
---|
42 | #define IFMT "%d " /* output format for ints */ |
---|
43 | #define RFMT "%f " /* output format for reals */ |
---|
44 | |
---|
45 | |
---|
46 | /* |
---|
47 | * INPUTDATA: read initial conditions from input file. |
---|
48 | */ |
---|
49 | |
---|
50 | void inputdata(void) |
---|
51 | { |
---|
52 | stream instr; |
---|
53 | int ndim; |
---|
54 | bodyptr p; |
---|
55 | |
---|
56 | instr = stropen(infile, "r"); /* open input stream */ |
---|
57 | in_int(instr, &nbody); /* read number of bodies */ |
---|
58 | if (nbody < 1) |
---|
59 | error("inputdata: nbody = %d is absurd\n", nbody); |
---|
60 | in_int(instr, &ndim); /* read number of dims */ |
---|
61 | if (ndim != NDIM) |
---|
62 | error("inputdata: ndim = %d; expected %d\n", ndim, NDIM); |
---|
63 | in_real(instr, &tnow); /* read starting time */ |
---|
64 | bodytab = (bodyptr) allocate(nbody * sizeof(body)); |
---|
65 | /* allocate body array */ |
---|
66 | for (p = bodytab; p < bodytab+nbody; p++) /* loop over all bodies */ |
---|
67 | in_real(instr, &Mass(p)); /* read mass of each */ |
---|
68 | for (p = bodytab; p < bodytab+nbody; p++) |
---|
69 | in_vector(instr, Pos(p)); /* read position of each */ |
---|
70 | for (p = bodytab; p < bodytab+nbody; p++) |
---|
71 | in_vector(instr, Vel(p)); /* read velocity of each */ |
---|
72 | fclose(instr); /* close input stream */ |
---|
73 | if (scanopt(options, "reset-time")) /* reset starting time? */ |
---|
74 | tnow = 0.0; /* then set it to zero */ |
---|
75 | for (p = bodytab; p < bodytab+nbody; p++) /* loop over new bodies */ |
---|
76 | Type(p) = BODY; /* initialize type field */ |
---|
77 | } |
---|
78 | void inputdata_2(void) |
---|
79 | { |
---|
80 | stream instr; |
---|
81 | int ndim; |
---|
82 | bodyptr p; |
---|
83 | |
---|
84 | |
---|
85 | instr = stropen(infile, "r"); /* open input stream */ |
---|
86 | in_int(instr, &nbody); /* read number of bodies */ |
---|
87 | if (nbody < 1) |
---|
88 | error("inputdata: nbody = %d is absurd\n", nbody); |
---|
89 | bodytab = (bodyptr) allocate(nbody * sizeof(body)); |
---|
90 | /* allocate body array */ |
---|
91 | in_real(instr, &tnow); |
---|
92 | for (p = bodytab; p < bodytab+nbody; p++) /* loop over all bodies */ |
---|
93 | { |
---|
94 | in_real(instr, &Mass(p)); /* read mass of each */ |
---|
95 | in_vector(instr, Pos(p)); /* read position of each */ |
---|
96 | in_vector(instr, Vel(p)); /* read velocity of each */ |
---|
97 | } |
---|
98 | fclose(instr); /* close input stream */ |
---|
99 | if (scanopt(options, "reset-time")) /* reset starting time? */ |
---|
100 | tnow = 0.0; /* then set it to zero */ |
---|
101 | for (p = bodytab; p < bodytab+nbody; p++) /* loop over new bodies */ |
---|
102 | Type(p) = BODY; /* initialize type field */ |
---|
103 | } |
---|
104 | /* |
---|
105 | * STARTOUTPUT: begin output to log file. |
---|
106 | */ |
---|
107 | |
---|
108 | void startoutput(void) |
---|
109 | { |
---|
110 | printf("\n%s\n", headline); /* print headline, params */ |
---|
111 | #if defined(USEFREQ) |
---|
112 | printf("\n%8s%10s%10s", "nbody", "freq", "eps"); |
---|
113 | #else |
---|
114 | printf("\n%8s%10s%10s", "nbody", "dtime", "eps"); |
---|
115 | #endif |
---|
116 | #if !defined(QUICKSCAN) |
---|
117 | printf("%10s", "theta"); |
---|
118 | #endif |
---|
119 | #if defined(USEFREQ) |
---|
120 | printf("%10s%10s%10s\n", "usequad", "freqout", "tstop"); |
---|
121 | printf("%8d%10.2f%10.4f", nbody, freq, eps); |
---|
122 | #else |
---|
123 | printf("%10s%10s%10s\n", "usequad", "dtout", "tstop"); |
---|
124 | printf("%8d%10.5f%10.4f", nbody, dtime, eps); |
---|
125 | #endif |
---|
126 | #if !defined(QUICKSCAN) |
---|
127 | printf("%10.2f", theta); |
---|
128 | #endif |
---|
129 | #if defined(USEFREQ) |
---|
130 | printf("%10s%10.2f%10.4f\n", usequad ? "true" : "false", freqout, tstop); |
---|
131 | #else |
---|
132 | printf("%10s%10.5f%10.4f\n", usequad ? "true" : "false", dtout, tstop); |
---|
133 | #endif |
---|
134 | if (! strnull(options)) /* print options, if any */ |
---|
135 | printf("\n\toptions: %s\n", options); |
---|
136 | if (! strnull(savefile)) /* was state file given? */ |
---|
137 | savestate(savefile); /* save initial data */ |
---|
138 | } |
---|
139 | |
---|
140 | /* |
---|
141 | * FORCEREPORT: print staristics on tree construction and force calculation. |
---|
142 | */ |
---|
143 | |
---|
144 | void forcereport(void) |
---|
145 | { |
---|
146 | printf("\n\t%8s%8s%8s%8s%10s%10s%8s\n", |
---|
147 | "rsize", "tdepth", "ftree", |
---|
148 | "actmax", "nbbtot", "nbctot", "CPUfc"); |
---|
149 | printf("\t%8.1f%8d%8.3f%8d%10d%10d%8.3f\n", |
---|
150 | rsize, tdepth, (nbody + ncell - 1) / ((real) ncell), |
---|
151 | actmax, nbbcalc, nbccalc, cpuforce); |
---|
152 | } |
---|
153 | |
---|
154 | /* |
---|
155 | * OUTPUT: compute diagnostics and output body data. |
---|
156 | */ |
---|
157 | |
---|
158 | void output(void) |
---|
159 | { |
---|
160 | real cmabs, amabs, teff; |
---|
161 | |
---|
162 | diagnostics(); /* compute std diagnostics */ |
---|
163 | ABSV(cmabs, cmvel); /* find magnitude of cm vel */ |
---|
164 | ABSV(amabs, amvec); /* find magnitude of J vect */ |
---|
165 | printf("\n %8s%8s%8s%8s%8s%8s%8s%8s\n", |
---|
166 | "time", "|T+U|", "T", "-U", "-T/U", "|Vcom|", "|Jtot|", "CPUtot"); |
---|
167 | printf(" %8.3f%8.5f%8.5f%8.5f%8.5f%8.5f%8.5f%8.3f\n", |
---|
168 | tnow, ABS(etot[0]), etot[1], -etot[2], -etot[1]/etot[2], |
---|
169 | cmabs, amabs, cputime()); |
---|
170 | #if defined(USEFREQ) |
---|
171 | teff = tnow + (freq > 0 ? 0.125/freq : 0); /* anticipate slightly... */ |
---|
172 | #else |
---|
173 | teff = tnow + dtime/8; /* anticipate slightly... */ |
---|
174 | #endif |
---|
175 | if (! strnull(outfile) && teff >= tout) /* time for data output? */ |
---|
176 | //outputdata(); |
---|
177 | {} |
---|
178 | if (! strnull(savefile)) /* was state file given? */ |
---|
179 | savestate(savefile); /* save data for restart */ |
---|
180 | } |
---|
181 | |
---|
182 | /* |
---|
183 | * OUTPUTDATA: output body data. |
---|
184 | */ |
---|
185 | |
---|
186 | /*void outputdata(void) |
---|
187 | { |
---|
188 | char namebuf[256]; |
---|
189 | struct stat buf; |
---|
190 | stream outstr; |
---|
191 | bodyptr p; |
---|
192 | |
---|
193 | sprintf(namebuf, outfile, nstep); // construct output name |
---|
194 | if (stat(namebuf, &buf) != 0) // no output file exists? |
---|
195 | outstr = stropen(namebuf, "w"); // create & open for output |
---|
196 | else // else file already exists |
---|
197 | outstr = stropen(namebuf, "a"); // reopen and append output |
---|
198 | out_int(outstr, nbody); // write number of bodies |
---|
199 | out_int(outstr, NDIM); // number of dimensions |
---|
200 | out_real(outstr, tnow); // and current time value |
---|
201 | for (p = bodytab; p < bodytab+nbody; p++) // loop over all bodies |
---|
202 | out_real(outstr, Mass(p)); // output mass of each |
---|
203 | for (p = bodytab; p < bodytab+nbody; p++) |
---|
204 | out_vector(outstr, Pos(p)); // output positions |
---|
205 | for (p = bodytab; p < bodytab+nbody; p++) |
---|
206 | out_vector(outstr, Vel(p)); // output velocities |
---|
207 | if (scanopt(options, "out-phi")) // potentials requested? |
---|
208 | for (p = bodytab; p < bodytab+nbody; p++) |
---|
209 | out_real(outstr, Phi(p)); // output potentials |
---|
210 | if (scanopt(options, "out-acc")) // accelerations requested? |
---|
211 | for (p = bodytab; p < bodytab+nbody; p++) |
---|
212 | out_vector(outstr, Acc(p)); // output accelerations |
---|
213 | fclose(outstr); // close up output file |
---|
214 | printf("\n\tdata output to file %s at time %f\n", namebuf, tnow); |
---|
215 | #if defined(USEFREQ) |
---|
216 | tout += 1.0 / freqout; // schedule next output |
---|
217 | #else |
---|
218 | tout += dtout; // schedule next output |
---|
219 | #endif |
---|
220 | } |
---|
221 | */ |
---|
222 | |
---|
223 | void outputdata(void) |
---|
224 | { |
---|
225 | char namebuf[256]; |
---|
226 | struct stat buf; |
---|
227 | stream outstr; |
---|
228 | bodyptr p; |
---|
229 | int tnow_int; |
---|
230 | |
---|
231 | sprintf(namebuf, outfile, nstep); // construct output name |
---|
232 | if (stat(namebuf, &buf) != 0) // no output file exists? |
---|
233 | outstr = stropen(namebuf, "w"); // create & open for output |
---|
234 | else // else file already exists |
---|
235 | outstr = stropen(namebuf, "a"); // reopen and append output |
---|
236 | tnow_int = tnow; |
---|
237 | out_int(outstr, nbody); // write number of bodies |
---|
238 | out_real(outstr, tnow); |
---|
239 | //out_int(outstr, tnow_int); // and current time value |
---|
240 | for (p = bodytab; p < bodytab+nbody; p++) // loop over all bodies |
---|
241 | { |
---|
242 | //out_real(outstr, Mass(p)); // output mass of each |
---|
243 | fprintf(outstr, RFMT, Mass(p)); |
---|
244 | out_vector(outstr, Pos(p)); // output positions |
---|
245 | out_vector(outstr, Vel(p)); // output velocities |
---|
246 | fprintf(outstr,"\n"); |
---|
247 | } |
---|
248 | //fprintf(outstr,"\n"); |
---|
249 | fclose(outstr); // close up output file |
---|
250 | printf("\n\tdata output to file %s at time %f\n", namebuf, tnow); |
---|
251 | #if defined(USEFREQ) |
---|
252 | tout += 1.0 / freqout; // schedule next output |
---|
253 | #else |
---|
254 | tout += dtout; // schedule next output |
---|
255 | #endif |
---|
256 | } |
---|
257 | |
---|
258 | /* |
---|
259 | * DIAGNOSTICS: compute set of dynamical diagnostics. |
---|
260 | */ |
---|
261 | |
---|
262 | local void diagnostics(void) |
---|
263 | { |
---|
264 | register bodyptr p; |
---|
265 | real velsq; |
---|
266 | vector tmpv; |
---|
267 | matrix tmpt; |
---|
268 | |
---|
269 | mtot = 0.0; /* zero total mass */ |
---|
270 | etot[1] = etot[2] = 0.0; /* zero total KE and PE */ |
---|
271 | CLRM(keten); /* zero ke tensor */ |
---|
272 | CLRM(peten); /* zero pe tensor */ |
---|
273 | CLRV(amvec); /* zero am vector */ |
---|
274 | CLRV(cmpos); /* zero c. of m. position */ |
---|
275 | CLRV(cmvel); /* zero c. of m. velocity */ |
---|
276 | for (p = bodytab; p < bodytab+nbody; p++) { /* loop over all particles */ |
---|
277 | mtot += Mass(p); /* sum particle masses */ |
---|
278 | DOTVP(velsq, Vel(p), Vel(p)); /* square vel vector */ |
---|
279 | etot[1] += 0.5 * Mass(p) * velsq; /* sum current KE */ |
---|
280 | etot[2] += 0.5 * Mass(p) * Phi(p); /* and current PE */ |
---|
281 | MULVS(tmpv, Vel(p), 0.5 * Mass(p)); /* sum 0.5 m v_i v_j */ |
---|
282 | OUTVP(tmpt, tmpv, Vel(p)); |
---|
283 | ADDM(keten, keten, tmpt); |
---|
284 | MULVS(tmpv, Pos(p), Mass(p)); /* sum m r_i a_j */ |
---|
285 | OUTVP(tmpt, tmpv, Acc(p)); |
---|
286 | ADDM(peten, peten, tmpt); |
---|
287 | CROSSVP(tmpv, Vel(p), Pos(p)); /* sum angular momentum */ |
---|
288 | MULVS(tmpv, tmpv, Mass(p)); |
---|
289 | ADDV(amvec, amvec, tmpv); |
---|
290 | MULVS(tmpv, Pos(p), Mass(p)); /* sum cm position */ |
---|
291 | ADDV(cmpos, cmpos, tmpv); |
---|
292 | MULVS(tmpv, Vel(p), Mass(p)); /* sum cm momentum */ |
---|
293 | ADDV(cmvel, cmvel, tmpv); |
---|
294 | } |
---|
295 | etot[0] = etot[1] + etot[2]; /* sum KE and PE */ |
---|
296 | DIVVS(cmpos, cmpos, mtot); /* normalize cm coords */ |
---|
297 | DIVVS(cmvel, cmvel, mtot); |
---|
298 | } |
---|
299 | |
---|
300 | /* |
---|
301 | * IN_INT, IN_REAL, IN_VECTOR: low level input routines. |
---|
302 | */ |
---|
303 | |
---|
304 | local void in_int(stream str, int *iptr) |
---|
305 | { |
---|
306 | #if !defined(BINARYIO) |
---|
307 | if (fscanf(str, "%d", iptr) != 1) |
---|
308 | error("in_int: input conversion error\n"); |
---|
309 | #else |
---|
310 | if (fread((void *) iptr, sizeof(int), 1, str) != 1) |
---|
311 | error("in_int: fread failed\n"); |
---|
312 | #endif |
---|
313 | } |
---|
314 | |
---|
315 | local void in_real(stream str, real *rptr) |
---|
316 | { |
---|
317 | double tmp; |
---|
318 | |
---|
319 | #if !defined(BINARYIO) |
---|
320 | if (fscanf(str, "%lf", &tmp) != 1) |
---|
321 | error("in_real: input conversion error\n"); |
---|
322 | *rptr = tmp; |
---|
323 | #else |
---|
324 | if (fread((void *) rptr, sizeof(real), 1, str) != 1) |
---|
325 | error("in_real: fread failed\n"); |
---|
326 | #endif |
---|
327 | } |
---|
328 | |
---|
329 | local void in_vector(stream str, vector vec) |
---|
330 | { |
---|
331 | double tmpx, tmpy, tmpz; |
---|
332 | |
---|
333 | #if !defined(BINARYIO) |
---|
334 | if (fscanf(str, "%lf%lf%lf", &tmpx, &tmpy, &tmpz) != 3) |
---|
335 | error("in_vector: input conversion error\n"); |
---|
336 | vec[0] = tmpx; |
---|
337 | vec[1] = tmpy; |
---|
338 | vec[2] = tmpz; |
---|
339 | #else |
---|
340 | if (fread((void *) vec, sizeof(real), NDIM, str) != NDIM) |
---|
341 | error("in_vector: fread failed\n"); |
---|
342 | #endif |
---|
343 | } |
---|
344 | |
---|
345 | /* |
---|
346 | * OUT_INT, OUT_REAL, OUT_VECTOR: low level output routines. */ |
---|
347 | |
---|
348 | |
---|
349 | local void out_int(stream str, int ival) |
---|
350 | { |
---|
351 | #if !defined(BINARYIO) |
---|
352 | if (fprintf(str, IFMT "\n", ival) < 0) |
---|
353 | error("out_int: fprintf failed\n"); |
---|
354 | #else |
---|
355 | if (fwrite((void *) &ival, sizeof(int), 1, str) != 1) |
---|
356 | error("out_int: fwrite failed\n"); |
---|
357 | #endif |
---|
358 | } |
---|
359 | |
---|
360 | local void out_real(stream str, real rval) |
---|
361 | { |
---|
362 | #if !defined(BINARYIO) |
---|
363 | if (fprintf(str, RFMT "\n", rval) < 0) |
---|
364 | error("out_real: fprintf failed\n"); |
---|
365 | #else |
---|
366 | if (fwrite((void *) &rval, sizeof(real), 1, str) != 1) |
---|
367 | error("out_real: fwrite failed\n"); |
---|
368 | #endif |
---|
369 | } |
---|
370 | |
---|
371 | local void out_vector(stream str, vector vec) |
---|
372 | { |
---|
373 | #if !defined(BINARYIO) |
---|
374 | if (fprintf(str, RFMT RFMT RFMT, vec[0], vec[1], vec[2]) < 0) |
---|
375 | error("out_vector: fprintf failed\n"); |
---|
376 | #else |
---|
377 | if (fwrite((void *) vec, sizeof(real), NDIM, str) != NDIM) |
---|
378 | error("out_vector: fwrite failed\n"); |
---|
379 | #endif |
---|
380 | } |
---|
381 | |
---|
382 | /* |
---|
383 | * SAVESTATE: write current state to disk file. |
---|
384 | */ |
---|
385 | |
---|
386 | #define safewrite(ptr,len,str) \ |
---|
387 | if (fwrite((void *) ptr, len, 1, str) != 1) \ |
---|
388 | error("savestate: fwrite failed\n") |
---|
389 | |
---|
390 | void savestate(string pattern) |
---|
391 | { |
---|
392 | char namebuf[256]; |
---|
393 | stream str; |
---|
394 | int nchars; |
---|
395 | |
---|
396 | sprintf(namebuf, pattern, nstep & 1); /* construct alternate name */ |
---|
397 | str = stropen(namebuf, "w!"); |
---|
398 | nchars = strlen(getargv0()) + 1; |
---|
399 | safewrite(&nchars, sizeof(int), str); |
---|
400 | safewrite(getargv0(), nchars * sizeof(char), str); |
---|
401 | nchars = strlen(getversion()) + 1; |
---|
402 | safewrite(&nchars, sizeof(int), str); |
---|
403 | safewrite(getversion(), nchars * sizeof(char), str); |
---|
404 | #if defined(USEFREQ) |
---|
405 | safewrite(&freq, sizeof(real), str); |
---|
406 | #else |
---|
407 | safewrite(&dtime, sizeof(real), str); |
---|
408 | #endif |
---|
409 | #if !defined(QUICKSCAN) |
---|
410 | safewrite(&theta, sizeof(real), str); |
---|
411 | #endif |
---|
412 | safewrite(&usequad, sizeof(bool), str); |
---|
413 | safewrite(&eps, sizeof(real), str); |
---|
414 | nchars = strlen(options) + 1; |
---|
415 | safewrite(&nchars, sizeof(int), str); |
---|
416 | safewrite(options, nchars * sizeof(char), str); |
---|
417 | safewrite(&tstop, sizeof(real), str); |
---|
418 | #if defined(USEFREQ) |
---|
419 | safewrite(&freqout, sizeof(real), str); |
---|
420 | #else |
---|
421 | safewrite(&dtout, sizeof(real), str); |
---|
422 | #endif |
---|
423 | safewrite(&tnow, sizeof(real), str); |
---|
424 | safewrite(&tout, sizeof(real), str); |
---|
425 | safewrite(&nstep, sizeof(int), str); |
---|
426 | safewrite(&rsize, sizeof(real), str); |
---|
427 | safewrite(&nbody, sizeof(int), str); |
---|
428 | safewrite(bodytab, nbody * sizeof(body), str); |
---|
429 | fclose(str); |
---|
430 | } |
---|
431 | |
---|
432 | /* |
---|
433 | * RESTORESTATE: restore state from disk file. |
---|
434 | */ |
---|
435 | |
---|
436 | #define saferead(ptr,len,str) \ |
---|
437 | if (fread((void *) ptr, len, 1, str) != 1) \ |
---|
438 | error("restorestate: fread failed\n") |
---|
439 | |
---|
440 | void restorestate(string file) |
---|
441 | { |
---|
442 | stream str; |
---|
443 | int nchars; |
---|
444 | string program, version; |
---|
445 | |
---|
446 | str = stropen(file, "r"); |
---|
447 | saferead(&nchars, sizeof(int), str); |
---|
448 | program = (string) allocate(nchars * sizeof(char)); |
---|
449 | saferead(program, nchars * sizeof(char), str); |
---|
450 | saferead(&nchars, sizeof(int), str); |
---|
451 | version = (string) allocate(nchars * sizeof(char)); |
---|
452 | saferead(version, nchars * sizeof(char), str); |
---|
453 | if (! streq(program, getargv0()) || /* check program, version */ |
---|
454 | ! streq(version, getversion())) |
---|
455 | printf("warning: state file may be outdated\n\n"); |
---|
456 | #if defined(USEFREQ) |
---|
457 | saferead(&freq, sizeof(real), str); |
---|
458 | #else |
---|
459 | saferead(&dtime, sizeof(real), str); |
---|
460 | #endif |
---|
461 | #if !defined(QUICKSCAN) |
---|
462 | saferead(&theta, sizeof(real), str); |
---|
463 | #endif |
---|
464 | saferead(&usequad, sizeof(bool), str); |
---|
465 | saferead(&eps, sizeof(real), str); |
---|
466 | saferead(&nchars, sizeof(int), str); |
---|
467 | options = (string) allocate(nchars * sizeof(char)); |
---|
468 | saferead(options, nchars * sizeof(char), str); |
---|
469 | saferead(&tstop, sizeof(real), str); |
---|
470 | #if defined(USEFREQ) |
---|
471 | saferead(&freqout, sizeof(real), str); |
---|
472 | #else |
---|
473 | saferead(&dtout, sizeof(real), str); |
---|
474 | #endif |
---|
475 | saferead(&tnow, sizeof(real), str); |
---|
476 | saferead(&tout, sizeof(real), str); |
---|
477 | saferead(&nstep, sizeof(int), str); |
---|
478 | saferead(&rsize, sizeof(real), str); |
---|
479 | saferead(&nbody, sizeof(int), str); |
---|
480 | bodytab = (bodyptr) allocate(nbody * sizeof(body)); |
---|
481 | saferead(bodytab, nbody * sizeof(body), str); |
---|
482 | fclose(str); |
---|
483 | } |
---|