Bug fix in the TNG library to improve reading.
[gromacs.git] / src / external / tng_io / src / lib / tng_io.c
blobb6c6f22227e791677bc752ec05d48e5f88a5debe
1 /* This code is part of the tng binary trajectory format.
3 * VERSION 1.5
5 * Written by Magnus Lundborg
6 * Copyright (c) 2012-2013, The GROMACS development team.
7 * Check out http://www.gromacs.org for more information.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the Revised BSD License.
14 #ifdef USE_STD_INTTYPES_H
15 #include <inttypes.h>
16 #endif
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include <math.h>
23 #ifdef USE_ZLIB
24 #include <zlib.h>
25 #endif
27 #include "../../include/tng_io.h"
28 #include "../../include/md5.h"
29 #include "../../include/compression/tng_compress.h"
32 struct tng_bond {
33 /** One of the atoms of the bond */
34 int64_t from_atom_id;
35 /** The other atom of the bond */
36 int64_t to_atom_id;
39 struct tng_atom {
40 /** The residue containing this atom */
41 tng_residue_t residue;
42 /** A unique (per molecule) ID number of the atom */
43 int64_t id;
44 /** The atom_type (depending on the forcefield) */
45 char *atom_type;
46 /** The name of the atom */
47 char *name;
50 struct tng_residue {
51 /** The chain containing this residue */
52 tng_chain_t chain;
53 /** A unique (per chain) ID number of the residue */
54 int64_t id;
55 /** The name of the residue */
56 char *name;
57 /** The number of atoms in the residue */
58 int64_t n_atoms;
59 /** A list of atoms in the residue */
60 int64_t atoms_offset;
63 struct tng_chain {
64 /** The molecule containing this chain */
65 tng_molecule_t molecule;
66 /** A unique (per molecule) ID number of the chain */
67 int64_t id;
68 /** The name of the chain */
69 char *name;
70 /** The number of residues in the chain */
71 int64_t n_residues;
72 /** A list of residues in the chain */
73 tng_residue_t residues;
76 struct tng_molecule {
77 /** A unique ID number of the molecule */
78 int64_t id;
79 /** Quaternary structure of the molecule.
80 * 1 => monomeric
81 * 2 => dimeric
82 * 3 => trimeric
83 * etc */
84 int64_t quaternary_str;
85 /** The number of chains in the molecule */
86 int64_t n_chains;
87 /** The number of residues in the molecule */
88 int64_t n_residues;
89 /** The number of atoms in the molecule */
90 int64_t n_atoms;
91 /** The number of bonds in the molecule. If the bonds are not specified this
92 * value can be 0. */
93 int64_t n_bonds;
94 /** The name of the molecule */
95 char *name;
96 /** A list of chains in the molecule */
97 tng_chain_t chains;
98 /** A list of residues in the molecule */
99 tng_residue_t residues;
100 /** A list of the atoms in the molecule */
101 tng_atom_t atoms;
102 /** A list of the bonds in the molecule */
103 tng_bond_t bonds;
106 struct tng_gen_block {
107 /** The size of the block header in bytes */
108 int64_t header_contents_size;
109 /** The size of the block contents in bytes */
110 int64_t block_contents_size;
111 /** The ID of the block to determine its type */
112 int64_t id;
113 /** The MD5 hash of the block to verify integrity */
114 char md5_hash[TNG_MD5_HASH_LEN];
115 /** The name of the block */
116 char *name;
117 /** The library version used to write the block */
118 int64_t block_version;
119 int64_t alt_hash_type;
120 int64_t alt_hash_len;
121 char *alt_hash;
122 int64_t signature_type;
123 int64_t signature_len;
124 char *signature;
125 /** The full block header contents */
126 char *header_contents;
127 /** The full block contents */
128 char *block_contents;
131 struct tng_particle_mapping {
132 /** The index number of the first particle in this mapping block */
133 int64_t num_first_particle;
134 /** The number of particles list in this mapping block */
135 int64_t n_particles;
136 /** the mapping of index numbers to the real particle numbers in the
137 * trajectory. real_particle_numbers[0] is the real particle number
138 * (as it is numbered in the molecular system) of the first particle
139 * in the data blocks covered by this particle mapping block */
140 int64_t *real_particle_numbers;
143 struct tng_trajectory_frame_set {
144 /** The number of different particle mapping blocks present. */
145 int64_t n_mapping_blocks;
146 /** The atom mappings of this frame set */
147 struct tng_particle_mapping *mappings;
148 /** The first frame of this frame set */
149 int64_t first_frame;
150 /** The number of frames in this frame set */
151 int64_t n_frames;
152 /** The number of written frames in this frame set (used when writing one
153 * frame at a time). */
154 int64_t n_written_frames;
155 /** The number of frames not yet written to file in this frame set
156 * (used from the utility functions to finish the writing properly. */
157 int64_t n_unwritten_frames;
160 /** A list of the number of each molecule type - only used when using
161 * variable number of atoms */
162 int64_t *molecule_cnt_list;
163 /** The number of particles/atoms - only used when using variable number
164 * of atoms */
165 int64_t n_particles;
166 /** The file position of the next frame set */
167 int64_t next_frame_set_file_pos;
168 /** The file position of the previous frame set */
169 int64_t prev_frame_set_file_pos;
170 /** The file position of the frame set one long stride step ahead */
171 int64_t medium_stride_next_frame_set_file_pos;
172 /** The file position of the frame set one long stride step behind */
173 int64_t medium_stride_prev_frame_set_file_pos;
174 /** The file position of the frame set one long stride step ahead */
175 int64_t long_stride_next_frame_set_file_pos;
176 /** The file position of the frame set one long stride step behind */
177 int64_t long_stride_prev_frame_set_file_pos;
178 /** Time stamp (in seconds) of first frame in frame set */
179 double first_frame_time;
181 /* The data blocks in a frame set are trajectory data blocks */
182 /** The number of trajectory data blocks of particle dependent data */
183 int n_particle_data_blocks;
184 /** A list of data blocks containing particle dependent data */
185 struct tng_particle_data *tr_particle_data;
186 /** The number of trajectory data blocks independent of particles */
187 int n_data_blocks;
188 /** A list of data blocks containing particle indepdendent data */
189 struct tng_non_particle_data *tr_data;
192 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
193 struct tng_particle_data {
194 /** The block ID of the data block containing this particle data.
195 * This is used to determine the kind of data that is stored */
196 int64_t block_id;
197 /** The name of the data block. This is used to determine the kind of
198 * data that is stored */
199 char *block_name;
200 /** The type of data stored. */
201 char datatype;
202 /** The frame number of the first data value */
203 int64_t first_frame_with_data;
204 /** The number of frames in this frame set */
205 int64_t n_frames;
206 /** The number of values stored per frame */
207 int64_t n_values_per_frame;
208 /** The number of frames between each data point - e.g. when
209 * storing sparse data. */
210 int64_t stride_length;
211 /** ID of the CODEC used for compression 0 == no compression. */
212 int64_t codec_id;
213 /** If reading one frame at a time this is the last read frame */
214 int64_t last_retrieved_frame;
215 /** The multiplier used for getting integer values for compression */
216 double compression_multiplier;
217 /** A 1-dimensional array of values of length
218 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
219 void *values;
220 /** If storing character data store it in a 3-dimensional array */
221 char ****strings;
224 struct tng_non_particle_data {
225 /** The ID of the data block */
226 int64_t block_id;
227 /** The name of the data block. This is used to determine the kind of
228 * data that is stored */
229 char *block_name;
230 /** The type of data stored. */
231 char datatype;
232 /** The first frame number of the first data value */
233 int64_t first_frame_with_data;
234 /** The number of frames in this data block */
235 int64_t n_frames;
236 /** The number of values stored per frame */
237 int64_t n_values_per_frame;
238 /** The number of frames between each data value, e.g. if storing data
239 * that is not saved every frame. */
240 int64_t stride_length;
241 /** ID of the CODEC used for compression. 0 == no compression. */
242 int64_t codec_id;
243 /** If reading one frame at a time this is the last read frame */
244 int64_t last_retrieved_frame;
245 /** Compressed data is stored as integers. This compression multiplier is
246 * the multiplication factor to convert from integer to float/double */
247 double compression_multiplier;
248 /** A 1-dimensional array of values of length
249 * [sizeof (datatype)] * n_frames * n_values_per_frame */
250 void *values;
251 /** If storing character data store it in a 3-dimensional array */
252 char ***strings;
257 struct tng_trajectory {
258 /** The path of the input trajectory file */
259 char *input_file_path;
260 /** A handle to the input file */
261 FILE *input_file;
262 /** The length of the input file */
263 long input_file_len;
264 /** The path of the output trajectory file */
265 char *output_file_path;
266 /** A handle to the output file */
267 FILE *output_file;
268 /** Function to swap 32 bit values to and from the endianness of the
269 * input file */
270 tng_function_status (*input_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
271 /** Function to swap 64 bit values to and from the endianness of the
272 * input file */
273 tng_function_status (*input_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
274 /** Function to swap 32 bit values to and from the endianness of the
275 * input file */
276 tng_function_status (*output_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
277 /** Function to swap 64 bit values to and from the endianness of the
278 * input file */
279 tng_function_status (*output_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
280 /** The endianness of 32 bit values of the current computer */
281 char endianness_32;
282 /** The endianness of 64 bit values of the current computer */
283 char endianness_64;
285 /** The name of the program producing this trajectory */
286 char *first_program_name;
287 /** The forcefield used in the simulations */
288 char *forcefield_name;
289 /** The name of the user running the simulations */
290 char *first_user_name;
291 /** The name of the computer on which the simulations were performed */
292 char *first_computer_name;
293 /** The PGP signature of the user creating the file. */
294 char *first_pgp_signature;
295 /** The name of the program used when making last modifications to the
296 * file */
297 char *last_program_name;
298 /** The name of the user making the last modifications to the file */
299 char *last_user_name;
300 /** The name of the computer on which the last modifications were made */
301 char *last_computer_name;
302 /** The PGP signature of the user making the last modifications to the
303 * file. */
304 char *last_pgp_signature;
305 /** The time (n seconds since 1970) when the file was created */
306 int64_t time;
307 /** The exponential of the value of the distance unit used. The default
308 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
309 * the measurements are in Ã… the distance_unit_exponential = -10. */
310 int64_t distance_unit_exponential;
312 /** A flag indicating if the number of atoms can vary throughout the
313 * simulation, e.g. using a grand canonical ensemble */
314 char var_num_atoms_flag;
315 /** The number of frames in a frame set. It is allowed to have frame sets
316 * with fewer frames, but this will help searching for specific frames */
317 int64_t frame_set_n_frames;
318 /** The number of frame sets in a medium stride step */
319 int64_t medium_stride_length;
320 /** The number of frame sets in a long stride step */
321 int64_t long_stride_length;
322 /** The current (can change from one frame set to another) time length
323 * (in seconds) of one frame */
324 double time_per_frame;
326 /** The number of different kinds of molecules in the trajectory */
327 int64_t n_molecules;
328 /** A list of molecules in the trajectory */
329 tng_molecule_t molecules;
330 /** A list of the count of each molecule - if using variable number of
331 * particles this will be specified in each frame set */
332 int64_t *molecule_cnt_list;
333 /** The total number of particles/atoms. If using variable number of
334 * particles this will be specified in each frame set */
335 int64_t n_particles;
337 /** The pos in the src file of the first frame set */
338 int64_t first_trajectory_frame_set_input_file_pos;
339 /** The pos in the dest file of the first frame set */
340 int64_t first_trajectory_frame_set_output_file_pos;
341 /** The pos in the src file of the last frame set */
342 int64_t last_trajectory_frame_set_input_file_pos;
343 /** The pos in the dest file of the last frame set */
344 int64_t last_trajectory_frame_set_output_file_pos;
345 /** The currently active frame set */
346 struct tng_trajectory_frame_set current_trajectory_frame_set;
347 /** The pos in the src file of the current frame set */
348 long current_trajectory_frame_set_input_file_pos;
349 /** The pos in the dest file of the current frame set */
350 long current_trajectory_frame_set_output_file_pos;
351 /** The number of frame sets in the trajectory N.B. Not saved in file and
352 * cannot be trusted to be up-to-date */
353 int64_t n_trajectory_frame_sets;
355 /** The number of trajectory blocks in the file */
356 int64_t n_trajectory_blocks;
358 /* These data blocks are non-trajectory data blocks */
359 /** The number of non-frame dependent particle dependent data blocks */
360 int n_particle_data_blocks;
361 /** A list of data blocks containing particle dependent data */
362 struct tng_particle_data *non_tr_particle_data;
364 /** The number of frame and particle independent data blocks */
365 int n_data_blocks;
366 /** A list of frame and particle indepdendent data blocks */
367 struct tng_non_particle_data *non_tr_data;
369 /** TNG compression algorithm for compressing positions */
370 int *compress_algo_pos;
371 /** TNG compression algorithm for compressing velocities */
372 int *compress_algo_vel;
373 /** The precision used for lossy compression */
374 double compression_precision;
377 #ifndef USE_WINDOWS
378 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
379 #define USE_WINDOWS
380 #endif /* win32... */
381 #endif /* not defined USE_WINDOWS */
383 #ifdef USE_WINDOWS
384 #define TNG_INLINE __inline
385 #define TNG_SNPRINTF _snprintf
386 #else
387 #define TNG_INLINE inline
388 #define TNG_SNPRINTF snprintf
389 #endif
391 static TNG_INLINE int tng_min_i(int a, int b)
393 return (a < b ? a : b);
397 static TNG_INLINE int tng_max_i(int a, int b)
399 return (a > b ? a : b);
402 static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
404 return (a < b ? a : b);
407 static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
409 return (a > b ? a : b);
413 static TNG_INLINE float tng_min_f(float a, float b)
415 return (a < b ? a : b);
418 static TNG_INLINE float tng_max_f(float a, float b)
420 return (a > b ? a : b);
423 static TNG_INLINE double tng_min_d(double a, double b)
425 return (a < b ? a : b);
428 static TNG_INLINE double tng_max_d(double a, double b)
430 return (a > b ? a : b);
434 /** This function swaps the byte order of a 32 bit numerical variable
435 * to big endian.
436 * It does not only work with integer, but e.g. floats need casting.
437 * If the byte order is already big endian no change is needed.
438 * @param tng_data is a trajectory data container.
439 * @param v is a pointer to a 32 bit numerical value (float or integer).
440 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
441 * byte order is not recognised.
443 static tng_function_status tng_swap_byte_order_big_endian_32
444 (const tng_trajectory_t tng_data, int32_t *v)
446 switch(tng_data->endianness_32)
448 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
449 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
450 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
451 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
452 ((*v & 0x000000FF) << 24); /* Move last byte to first */
454 return(TNG_SUCCESS);
456 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
457 *v = ((*v & 0xFFFF0000) >> 16) |
458 ((*v & 0x0000FFFF) << 16);
460 return(TNG_SUCCESS);
462 case TNG_BIG_ENDIAN_32: /* Already correct */
463 return(TNG_SUCCESS);
465 default:
466 return(TNG_FAILURE);
470 /** This function swaps the byte order of a 64 bit numerical variable
471 * to big endian.
472 * It does not only work with integer, but e.g. floats need casting.
473 * The byte order swapping routine can convert four different byte
474 * orders to big endian.
475 * If the byte order is already big endian no change is needed.
476 * @param tng_data is a trajectory data container.
477 * @param v is a pointer to a 64 bit numerical value (double or integer).
478 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
479 * byte order is not recognised.
481 static tng_function_status tng_swap_byte_order_big_endian_64
482 (const tng_trajectory_t tng_data, int64_t *v)
484 switch(tng_data->endianness_64)
486 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
487 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
488 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
489 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
490 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
491 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
492 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
493 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
494 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
496 return(TNG_SUCCESS);
498 case TNG_QUAD_SWAP_64: /* Byte quad swap */
499 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
500 ((*v & 0x00000000FFFFFFFFLL) << 32);
502 return(TNG_SUCCESS);
504 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
505 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
506 ((*v & 0x0000FFFF0000FFFFLL) << 16);
508 return(TNG_SUCCESS);
510 case TNG_BYTE_SWAP_64: /* Byte swap */
511 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
512 ((*v & 0x00FF00FF00FF00FFLL) << 8);
514 return(TNG_SUCCESS);
516 case TNG_BIG_ENDIAN_64: /* Already correct */
517 return(TNG_SUCCESS);
519 default:
520 return(TNG_FAILURE);
524 /** This function swaps the byte order of a 32 bit numerical variable
525 * to little endian.
526 * It does not only work with integer, but e.g. floats need casting.
527 * If the byte order is already little endian no change is needed.
528 * @param tng_data is a trajectory data container.
529 * @param v is a pointer to a 32 bit numerical value (float or integer).
530 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
531 * byte order is not recognised.
533 static tng_function_status tng_swap_byte_order_little_endian_32
534 (const tng_trajectory_t tng_data, int32_t *v)
536 switch(tng_data->endianness_32)
538 case TNG_LITTLE_ENDIAN_32: /* Already correct */
539 return(TNG_SUCCESS);
541 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
542 *v = ((*v & 0xFF00FF00) >> 8) |
543 ((*v & 0x00FF00FF) << 8);
545 return(TNG_SUCCESS);
547 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
548 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
549 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
550 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
551 ((*v & 0x000000FF) << 24); /* Move last byte to first */
553 return(TNG_SUCCESS);
555 default:
556 return(TNG_FAILURE);
560 /** This function swaps the byte order of a 64 bit numerical variable
561 * to little endian.
562 * It does not only work with integer, but e.g. floats need casting.
563 * The byte order swapping routine can convert four different byte
564 * orders to little endian.
565 * If the byte order is already little endian no change is needed.
566 * @param tng_data is a trajectory data container.
567 * @param v is a pointer to a 64 bit numerical value (double or integer).
568 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
569 * byte order is not recognised.
571 static tng_function_status tng_swap_byte_order_little_endian_64
572 (const tng_trajectory_t tng_data, int64_t *v)
574 switch(tng_data->endianness_64)
576 case TNG_LITTLE_ENDIAN_64: /* Already correct */
577 return(TNG_SUCCESS);
579 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
580 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
581 ((*v & 0x00FF000000FF0000LL) >> 8) |
582 ((*v & 0x0000FF000000FF00LL) << 8) |
583 ((*v & 0x000000FF000000FFLL) << 24);
585 return(TNG_SUCCESS);
587 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
588 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
589 ((*v & 0x00FF00FF00000000LL) >> 24) |
590 ((*v & 0x00000000FF00FF00LL) << 24) |
591 ((*v & 0x0000000000FF00FFLL) << 40);
593 return(TNG_SUCCESS);
595 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
596 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
597 ((*v & 0x0000FFFF00000000LL) >> 16) |
598 ((*v & 0x00000000FFFF0000LL) << 16) |
599 ((*v & 0x000000000000FFFFLL) << 48);
601 return(TNG_SUCCESS);
603 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
604 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
605 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
606 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
607 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
608 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
609 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
610 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
611 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
613 return(TNG_SUCCESS);
615 default:
616 return(TNG_FAILURE);
619 /** Generate the md5 hash of a block.
620 * The hash is created based on the actual block contents.
621 * @param block is a general block container.
622 * @return TNG_SUCCESS (0) if successful.
624 static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
626 md5_state_t md5_state;
628 md5_init(&md5_state);
629 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
630 (int)block->block_contents_size);
631 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
633 return(TNG_SUCCESS);
636 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
637 * calculated from the current contents.
638 * If the current md5 hash is not set skip the comparison.
639 * @param block is a general block container.
640 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
641 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
642 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
643 * set.
645 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
646 tng_bool *results)
648 md5_state_t md5_state;
649 char hash[TNG_MD5_HASH_LEN];
651 TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
653 *results = TNG_TRUE;
654 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
656 return(TNG_FAILURE);
658 md5_init(&md5_state);
659 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
660 (int)block->block_contents_size);
661 md5_finish(&md5_state, (md5_byte_t *)hash);
663 if(strncmp(block->md5_hash, hash, 16) != 0)
665 *results = TNG_FALSE;
668 return(TNG_SUCCESS);
671 /** Open the input file if it is not already opened.
672 * @param tng_data is a trajectory data container.
673 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
674 * error has occured.
676 static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
678 if(!tng_data->input_file)
680 if(!tng_data->input_file_path)
682 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
683 __FILE__, __LINE__);
684 return(TNG_CRITICAL);
686 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
687 if(!tng_data->input_file)
689 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
690 tng_data->input_file_path, __FILE__, __LINE__);
691 return(TNG_CRITICAL);
694 return(TNG_SUCCESS);
697 /** Open the output file if it is not already opened
698 * @param tng_data is a trajectory data container.
699 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
700 * error has occured.
702 static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
704 if(!tng_data->output_file)
706 if(!tng_data->output_file_path)
708 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
709 __FILE__, __LINE__);
710 return(TNG_CRITICAL);
713 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
715 if(!tng_data->output_file)
717 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
718 tng_data->output_file_path, __FILE__, __LINE__);
719 return(TNG_CRITICAL);
722 return(TNG_SUCCESS);
725 /** Setup a file block container.
726 * @param block_p a pointer to memory to initialise as a file block container.
727 * @details Memory is allocated during initialisation.
728 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
729 * error has occured.
731 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
733 tng_gen_block_t block;
735 *block_p = malloc(sizeof(struct tng_gen_block));
736 if(!*block_p)
738 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
739 sizeof(struct tng_gen_block), __FILE__, __LINE__);
740 return(TNG_CRITICAL);
743 block = *block_p;
745 block->id = -1;
746 /* Reset the md5_hash */
747 memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
748 block->name = 0;
749 block->block_version = TNG_VERSION;
750 block->header_contents = 0;
751 block->header_contents_size = 0;
752 block->block_contents = 0;
753 block->block_contents_size = 0;
755 return(TNG_SUCCESS);
759 * @brief Clean up a file block container.
760 * @param block_p a pointer to the file block container to destroy.
761 * @details All allocated memory in the data structure is freed, as well as
762 * block_p itself.
763 * @return TNG_SUCCESS (0) if successful.
765 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
767 tng_gen_block_t block = *block_p;
769 if(!*block_p)
771 return(TNG_SUCCESS);
774 /* fprintf(stderr, "TNG library: Destroying block\n"); */
775 if(block->name)
777 free(block->name);
778 block->name = 0;
780 if(block->header_contents)
782 free(block->header_contents);
783 block->header_contents = 0;
785 if(block->block_contents)
787 free(block->block_contents);
788 block->block_contents = 0;
791 free(*block_p);
792 *block_p = 0;
794 return(TNG_SUCCESS);
797 /** Read the header of a data block, regardless of its type
798 * @param tng_data is a trajectory data container.
799 * @param block is a general block container.
800 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
801 * error has occured.
803 static tng_function_status tng_block_header_read
804 (tng_trajectory_t tng_data, tng_gen_block_t block)
806 int len, offset = 0;
808 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
810 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
812 return(TNG_CRITICAL);
815 /* First read the header size to be able to read the whole header. */
816 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
817 1, tng_data->input_file) == 0)
819 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
820 __FILE__, __LINE__);
821 return(TNG_CRITICAL);
824 /* If this was the size of the general info block check the endianness */
825 if(ftell(tng_data->input_file) < 9)
827 /* File is little endian */
828 if ( *((const char*)&block->header_contents_size) != 0x00 &&
829 *((const char*)(&block->header_contents_size) + 7) == 0x00)
831 /* If the architecture endianness is little endian no byte swap
832 * will be needed. Otherwise use the functions to swap to little
833 * endian */
834 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
836 tng_data->input_endianness_swap_func_32 = 0;
838 else
840 tng_data->input_endianness_swap_func_32 =
841 &tng_swap_byte_order_little_endian_32;
843 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
845 tng_data->input_endianness_swap_func_64 = 0;
847 else
849 tng_data->input_endianness_swap_func_64 =
850 &tng_swap_byte_order_little_endian_64;
853 /* File is big endian */
854 else
856 /* If the architecture endianness is big endian no byte swap
857 * will be needed. Otherwise use the functions to swap to big
858 * endian */
859 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
861 tng_data->input_endianness_swap_func_32 = 0;
863 else
865 tng_data->input_endianness_swap_func_32 =
866 &tng_swap_byte_order_big_endian_32;
868 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
870 tng_data->input_endianness_swap_func_64 = 0;
872 else
874 tng_data->input_endianness_swap_func_64 =
875 &tng_swap_byte_order_big_endian_64;
880 if(tng_data->input_endianness_swap_func_64)
882 if(tng_data->input_endianness_swap_func_64(tng_data,
883 &block->header_contents_size)
884 != TNG_SUCCESS)
886 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
887 __FILE__, __LINE__);
891 /* Move the reading position to the beginning of the header. */
892 fseek(tng_data->input_file, -(long)sizeof(block->header_contents_size),
893 SEEK_CUR);
895 /* If there is already memory allocated for the contents free it (we do not
896 * know if the size is correct). */
897 if(block->header_contents)
899 free(block->header_contents);
902 block->header_contents = malloc(block->header_contents_size);
903 if(!block->header_contents)
905 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
906 block->header_contents_size, __FILE__, __LINE__);
907 return(TNG_CRITICAL);
910 /* Read the whole header into header_contents. This way it can be saved
911 * even if it cannot be interpreted
912 * for one reason or another. */
913 if(fread(block->header_contents, block->header_contents_size, 1,
914 tng_data->input_file) == 0)
916 fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
917 return(TNG_CRITICAL);
920 /* The header contents size has already been read. Skip ahead. */
921 offset = sizeof(block->header_contents_size);
924 /* Copy the respective parameters from the header contents block */
925 memcpy(&block->block_contents_size, block->header_contents+offset,
926 sizeof(block->block_contents_size));
927 if(tng_data->input_endianness_swap_func_64)
929 if(tng_data->input_endianness_swap_func_64(tng_data,
930 &block->block_contents_size)
931 != TNG_SUCCESS)
933 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
934 __FILE__, __LINE__);
938 offset += sizeof(block->block_contents_size);
940 memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
941 if(tng_data->input_endianness_swap_func_64)
943 if(tng_data->input_endianness_swap_func_64(tng_data,
944 &block->id)
945 != TNG_SUCCESS)
947 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
948 __FILE__, __LINE__);
952 offset += sizeof(block->id);
954 memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
955 offset += TNG_MD5_HASH_LEN;
957 if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
959 free(block->name);
960 block->name = 0;
962 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
963 if(!block->name)
965 block->name = malloc(len);
966 if(!block->name)
968 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
969 __FILE__, __LINE__);
970 return(TNG_CRITICAL);
972 strncpy(block->name, block->header_contents+offset, len);
974 offset += len;
976 memcpy(&block->block_version, block->header_contents+offset,
977 sizeof(block->block_version));
978 if(tng_data->input_endianness_swap_func_64)
980 if(tng_data->input_endianness_swap_func_64(tng_data,
981 &block->block_version)
982 != TNG_SUCCESS)
984 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
985 __FILE__, __LINE__);
989 return(TNG_SUCCESS);
992 /** Write a whole block, both header and contents, regardless of it type
993 * @param tng_data is a trajectory data container.
994 * @param block is a general block container.
995 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
996 * has occurred or TNG_CRITICAL (2) if a major error has occured.
998 /* Disabled until it is used.*/
1000 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1001 // tng_gen_block_t block)
1002 // {
1003 // if(!block->header_contents)
1004 // {
1005 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1006 // return(TNG_FAILURE);
1007 // }
1008 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1009 // tng_data->output_file) != 1)
1010 // {
1011 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1012 // __FILE__, __LINE__);
1013 // return(TNG_CRITICAL);
1014 // }
1016 // if(!block->block_contents)
1017 // {
1018 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1019 // __FILE__, __LINE__);
1020 // return(TNG_FAILURE);
1021 // }
1022 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1023 // tng_data->output_file) != 1)
1024 // {
1025 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1026 // __FILE__, __LINE__);
1027 // return(TNG_CRITICAL);
1028 // }
1029 // return(TNG_SUCCESS);
1030 // }
1033 static tng_function_status tng_reread_frame_set_at_file_pos
1034 (tng_trajectory_t tng_data,
1035 const int64_t pos)
1037 tng_gen_block_t block;
1038 tng_function_status stat;
1040 tng_block_init(&block);
1042 fseek(tng_data->input_file, pos, SEEK_SET);
1043 if(pos > 0)
1045 stat = tng_block_header_read(tng_data, block);
1046 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1048 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
1049 __FILE__, __LINE__);
1050 tng_block_destroy(&block);
1051 return(TNG_FAILURE);
1054 if(tng_block_read_next(tng_data, block,
1055 TNG_SKIP_HASH) != TNG_SUCCESS)
1057 tng_block_destroy(&block);
1058 return(TNG_CRITICAL);
1062 tng_block_destroy(&block);
1064 return(TNG_SUCCESS);
1067 /** Write the header of a data block, regardless of its type
1068 * @param tng_data is a trajectory data container.
1069 * @param block is a general block container.
1070 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1071 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1072 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1073 * error has occured.
1075 static tng_function_status tng_block_header_write
1076 (tng_trajectory_t tng_data,
1077 tng_gen_block_t block,
1078 const char hash_mode)
1080 int name_len, offset = 0;
1082 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1084 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1086 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1087 __FILE__, __LINE__);
1088 return(TNG_CRITICAL);
1091 if(!block->name)
1093 block->name = malloc(1);
1094 if(!block->name)
1096 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1097 __FILE__, __LINE__);
1098 return(TNG_CRITICAL);
1100 block->name[0] = 0;
1103 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1105 if(hash_mode == TNG_USE_HASH)
1107 tng_block_md5_hash_generate(block);
1110 /* Calculate the size of the header to write */
1111 block->header_contents_size = sizeof(block->header_contents_size) +
1112 sizeof(block->block_contents_size) +
1113 sizeof(block->id) +
1114 sizeof(block->block_version) +
1115 TNG_MD5_HASH_LEN +
1116 name_len;
1118 if(block->header_contents)
1120 free(block->header_contents);
1123 block->header_contents = malloc(block->header_contents_size);
1124 if(!block->header_contents)
1126 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1127 block->header_contents_size, __FILE__, __LINE__);
1128 return(TNG_CRITICAL);
1131 /* First copy all data into the header_contents block and finally write
1132 * the whole block at once. */
1133 memcpy(block->header_contents, &block->header_contents_size,
1134 sizeof(block->header_contents_size));
1135 if(tng_data->output_endianness_swap_func_64)
1137 if(tng_data->output_endianness_swap_func_64(tng_data,
1138 (int64_t *)block->header_contents+offset)
1139 != TNG_SUCCESS)
1141 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1142 __FILE__, __LINE__);
1145 offset += sizeof(block->header_contents_size);
1147 memcpy(block->header_contents+offset, &block->block_contents_size,
1148 sizeof(block->block_contents_size));
1149 if(tng_data->output_endianness_swap_func_64)
1151 if(tng_data->output_endianness_swap_func_64(tng_data,
1152 (int64_t *)block->header_contents+offset)
1153 != TNG_SUCCESS)
1155 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1156 __FILE__, __LINE__);
1159 offset += sizeof(block->block_contents_size);
1161 memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
1162 if(tng_data->output_endianness_swap_func_64)
1164 if(tng_data->output_endianness_swap_func_64(tng_data,
1165 (int64_t *)block->header_contents+offset)
1166 != TNG_SUCCESS)
1168 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1169 __FILE__, __LINE__);
1172 offset += sizeof(block->id);
1174 memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
1175 offset += TNG_MD5_HASH_LEN;
1177 strncpy(block->header_contents+offset, block->name, name_len);
1178 offset += name_len;
1180 memcpy(block->header_contents+offset, &block->block_version,
1181 sizeof(block->block_version));
1182 if(tng_data->output_endianness_swap_func_64)
1184 if(tng_data->output_endianness_swap_func_64(tng_data,
1185 (int64_t *)block->header_contents+offset)
1186 != TNG_SUCCESS)
1188 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1189 __FILE__, __LINE__);
1193 if(fwrite(block->header_contents, block->header_contents_size,
1194 1, tng_data->output_file) != 1)
1196 fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
1197 return(TNG_CRITICAL);
1199 return(TNG_SUCCESS);
1202 /** Read a general info block. This is the first block of a TNG file.
1203 * Populate the fields in tng_data.
1204 * @param tng_data is a trajectory data container.
1205 * @param block is a general block container.
1206 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1207 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
1208 * compared to the md5 hash of the read contents to ensure valid data.
1209 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1210 * error has occured.
1212 static tng_function_status tng_general_info_block_read
1213 (tng_trajectory_t tng_data, tng_gen_block_t block,
1214 const char hash_mode)
1216 int len, offset = 0;
1217 tng_bool same_hash;
1219 void *temp;
1221 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
1223 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1225 return(TNG_CRITICAL);
1228 temp = realloc(block->block_contents, block->block_contents_size);
1229 if(!temp)
1231 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1232 block->block_contents_size, __FILE__, __LINE__);
1233 free(block->block_contents);
1234 block->block_contents = 0;
1235 return(TNG_CRITICAL);
1237 block->block_contents = temp;
1239 /* Read the whole block into block_contents to be able to write it to disk
1240 * even if it cannot be interpreted. */
1241 if(fread(block->block_contents, block->block_contents_size, 1,
1242 tng_data->input_file) == 0)
1244 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1245 return(TNG_CRITICAL);
1248 /* FIXME: Does not check if the size of the contents matches the expected
1249 * size or if the contents can be read. */
1251 if(hash_mode == TNG_USE_HASH)
1253 tng_md5_hash_match_verify(block, &same_hash);
1254 if(same_hash != TNG_TRUE)
1256 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
1257 "%s: %d\n",
1258 __FILE__, __LINE__);
1259 /* return(TNG_FAILURE); */
1263 len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
1264 temp = realloc(tng_data->first_program_name, len);
1265 if(!temp)
1267 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1268 __FILE__, __LINE__);
1269 free(tng_data->first_program_name);
1270 tng_data->first_program_name = 0;
1271 return(TNG_CRITICAL);
1273 tng_data->first_program_name = temp;
1274 strncpy(tng_data->first_program_name, block->block_contents, len);
1275 offset += len;
1277 len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
1278 temp = realloc(tng_data->last_program_name, len);
1279 if(!temp)
1281 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1282 __FILE__, __LINE__);
1283 free(tng_data->last_program_name);
1284 tng_data->last_program_name = 0;
1285 return(TNG_CRITICAL);
1287 tng_data->last_program_name = temp;
1288 strncpy(tng_data->last_program_name, block->block_contents + offset, len);
1289 offset += len;
1291 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1292 temp = realloc(tng_data->first_user_name, len);
1293 if(!temp)
1295 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1296 __FILE__, __LINE__);
1297 free(tng_data->first_user_name);
1298 tng_data->first_user_name = 0;
1299 return(TNG_CRITICAL);
1301 tng_data->first_user_name = temp;
1302 strncpy(tng_data->first_user_name, block->block_contents+offset, len);
1303 offset += len;
1305 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1306 temp = realloc(tng_data->last_user_name, len);
1307 if(!temp)
1309 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1310 __FILE__, __LINE__);
1311 free(tng_data->last_user_name);
1312 tng_data->last_user_name = 0;
1313 return(TNG_CRITICAL);
1315 tng_data->last_user_name = temp;
1316 strncpy(tng_data->last_user_name, block->block_contents+offset, len);
1317 offset += len;
1319 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1320 temp = realloc(tng_data->first_computer_name, len);
1321 if(!temp)
1323 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1324 __FILE__, __LINE__);
1325 free(tng_data->first_computer_name);
1326 tng_data->first_computer_name = 0;
1327 return(TNG_CRITICAL);
1329 tng_data->first_computer_name = temp;
1330 strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
1331 offset += len;
1333 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1334 temp = realloc(tng_data->last_computer_name, len);
1335 if(!temp)
1337 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1338 __FILE__, __LINE__);
1339 free(tng_data->last_computer_name);
1340 tng_data->last_computer_name = 0;
1341 return(TNG_CRITICAL);
1343 tng_data->last_computer_name = temp;
1344 strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
1345 offset += len;
1347 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1348 temp = realloc(tng_data->first_pgp_signature, len);
1349 if(!temp)
1351 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1352 __FILE__, __LINE__);
1353 free(tng_data->first_pgp_signature);
1354 tng_data->first_pgp_signature = 0;
1355 return(TNG_CRITICAL);
1357 tng_data->first_pgp_signature = temp;
1358 strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
1359 offset += len;
1361 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1362 temp = realloc(tng_data->last_pgp_signature, len);
1363 if(!temp)
1365 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1366 __FILE__, __LINE__);
1367 free(tng_data->last_pgp_signature);
1368 tng_data->last_pgp_signature = 0;
1369 return(TNG_CRITICAL);
1371 tng_data->last_pgp_signature = temp;
1372 strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
1373 offset += len;
1375 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1376 temp = realloc(tng_data->forcefield_name, len);
1377 if(!temp)
1379 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1380 __FILE__, __LINE__);
1381 free(tng_data->forcefield_name);
1382 tng_data->forcefield_name = 0;
1383 return(TNG_CRITICAL);
1385 tng_data->forcefield_name = temp;
1386 strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
1387 offset += len;
1389 memcpy(&tng_data->time, block->block_contents+offset,
1390 sizeof(tng_data->time));
1391 if(tng_data->input_endianness_swap_func_64)
1393 if(tng_data->input_endianness_swap_func_64(tng_data,
1394 &tng_data->time)
1395 != TNG_SUCCESS)
1397 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1398 __FILE__, __LINE__);
1401 offset += sizeof(tng_data->time);
1403 memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
1404 sizeof(tng_data->var_num_atoms_flag));
1405 offset += sizeof(tng_data->var_num_atoms_flag);
1407 memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
1408 sizeof(tng_data->frame_set_n_frames));
1409 if(tng_data->input_endianness_swap_func_64)
1411 if(tng_data->input_endianness_swap_func_64(tng_data,
1412 &tng_data->frame_set_n_frames)
1413 != TNG_SUCCESS)
1415 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1416 __FILE__, __LINE__);
1419 offset += sizeof(tng_data->frame_set_n_frames);
1421 memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
1422 block->block_contents+offset,
1423 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
1424 if(tng_data->input_endianness_swap_func_64)
1426 if(tng_data->input_endianness_swap_func_64(tng_data,
1427 &tng_data->first_trajectory_frame_set_input_file_pos)
1428 != TNG_SUCCESS)
1430 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1431 __FILE__, __LINE__);
1434 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
1436 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
1437 tng_data->first_trajectory_frame_set_input_file_pos;
1440 memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
1441 block->block_contents+offset,
1442 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
1443 if(tng_data->input_endianness_swap_func_64)
1445 if(tng_data->input_endianness_swap_func_64(tng_data,
1446 &tng_data->last_trajectory_frame_set_input_file_pos)
1447 != TNG_SUCCESS)
1449 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1450 __FILE__, __LINE__);
1453 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
1455 memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
1456 sizeof(tng_data->medium_stride_length));
1457 if(tng_data->input_endianness_swap_func_64)
1459 if(tng_data->input_endianness_swap_func_64(tng_data,
1460 &tng_data->medium_stride_length)
1461 != TNG_SUCCESS)
1463 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1464 __FILE__, __LINE__);
1467 offset += sizeof(tng_data->medium_stride_length);
1469 memcpy(&tng_data->long_stride_length, block->block_contents+offset,
1470 sizeof(tng_data->long_stride_length));
1471 if(tng_data->input_endianness_swap_func_64)
1473 if(tng_data->input_endianness_swap_func_64(tng_data,
1474 &tng_data->long_stride_length)
1475 != TNG_SUCCESS)
1477 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1478 __FILE__, __LINE__);
1481 offset += sizeof(tng_data->long_stride_length);
1483 if(block->block_version >= 3)
1485 memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
1486 sizeof(tng_data->distance_unit_exponential));
1487 if(tng_data->input_endianness_swap_func_64)
1489 if(tng_data->input_endianness_swap_func_64(tng_data,
1490 &tng_data->distance_unit_exponential)
1491 != TNG_SUCCESS)
1493 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1494 __FILE__, __LINE__);
1499 return(TNG_SUCCESS);
1502 /** Write a general info block. This is the first block of a TNG file.
1503 * @param tng_data is a trajectory data container.
1504 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1505 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1506 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1507 * error has occured.
1509 static tng_function_status tng_general_info_block_write
1510 (tng_trajectory_t tng_data,
1511 const char hash_mode)
1513 int first_program_name_len, first_user_name_len;
1514 int first_computer_name_len, first_pgp_signature_len;
1515 int last_program_name_len, last_user_name_len;
1516 int last_computer_name_len, last_pgp_signature_len;
1517 int forcefield_name_len, name_len;
1518 int offset = 0;
1519 tng_gen_block_t block;
1521 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1523 return(TNG_CRITICAL);
1526 fseek(tng_data->output_file, 0, SEEK_SET);
1528 /* If the strings are unallocated allocate memory for just string
1529 * termination */
1530 if(!tng_data->first_program_name)
1532 tng_data->first_program_name = malloc(1);
1533 if(!tng_data->first_program_name)
1535 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1536 __FILE__, __LINE__);
1537 return(TNG_CRITICAL);
1539 tng_data->first_program_name[0] = 0;
1541 if(!tng_data->last_program_name)
1543 tng_data->last_program_name = malloc(1);
1544 if(!tng_data->last_program_name)
1546 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1547 __FILE__, __LINE__);
1548 return(TNG_CRITICAL);
1550 tng_data->last_program_name[0] = 0;
1552 if(!tng_data->first_user_name)
1554 tng_data->first_user_name = malloc(1);
1555 if(!tng_data->first_user_name)
1557 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1558 __FILE__, __LINE__);
1559 return(TNG_CRITICAL);
1561 tng_data->first_user_name[0] = 0;
1563 if(!tng_data->last_user_name)
1565 tng_data->last_user_name = malloc(1);
1566 if(!tng_data->last_user_name)
1568 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1569 __FILE__, __LINE__);
1570 return(TNG_CRITICAL);
1572 tng_data->last_user_name[0] = 0;
1574 if(!tng_data->first_computer_name)
1576 tng_data->first_computer_name = malloc(1);
1577 if(!tng_data->first_computer_name)
1579 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1580 __FILE__, __LINE__);
1581 return(TNG_CRITICAL);
1583 tng_data->first_computer_name[0] = 0;
1585 if(!tng_data->last_computer_name)
1587 tng_data->last_computer_name = malloc(1);
1588 if(!tng_data->last_computer_name)
1590 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1591 __FILE__, __LINE__);
1592 return(TNG_CRITICAL);
1594 tng_data->last_computer_name[0] = 0;
1596 if(!tng_data->first_pgp_signature)
1598 tng_data->first_pgp_signature = malloc(1);
1599 if(!tng_data->first_pgp_signature)
1601 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1602 __FILE__, __LINE__);
1603 return(TNG_CRITICAL);
1605 tng_data->first_pgp_signature[0] = 0;
1607 if(!tng_data->last_pgp_signature)
1609 tng_data->last_pgp_signature = malloc(1);
1610 if(!tng_data->last_pgp_signature)
1612 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1613 __FILE__, __LINE__);
1614 return(TNG_CRITICAL);
1616 tng_data->last_pgp_signature[0] = 0;
1618 if(!tng_data->forcefield_name)
1620 tng_data->forcefield_name = malloc(1);
1621 if(!tng_data->forcefield_name)
1623 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1624 __FILE__, __LINE__);
1625 return(TNG_CRITICAL);
1627 tng_data->forcefield_name[0] = 0;
1630 tng_block_init(&block);
1632 name_len = (int)strlen("GENERAL INFO");
1634 block->name = malloc(name_len + 1);
1635 if(!block->name)
1637 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
1638 name_len+1, __FILE__, __LINE__);
1639 tng_block_destroy(&block);
1640 return(TNG_CRITICAL);
1643 strcpy(block->name, "GENERAL INFO");
1644 block->id = TNG_GENERAL_INFO;
1646 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
1647 TNG_MAX_STR_LEN);
1648 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
1649 TNG_MAX_STR_LEN);
1650 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
1651 TNG_MAX_STR_LEN);
1652 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
1653 TNG_MAX_STR_LEN);
1654 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
1655 TNG_MAX_STR_LEN);
1656 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
1657 TNG_MAX_STR_LEN);
1658 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
1659 TNG_MAX_STR_LEN);
1660 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
1661 TNG_MAX_STR_LEN);
1662 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
1663 TNG_MAX_STR_LEN);
1665 block->block_contents_size = sizeof(tng_data->time) +
1666 sizeof(tng_data->var_num_atoms_flag) +
1667 sizeof(tng_data->frame_set_n_frames) +
1668 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
1669 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
1670 sizeof(tng_data->medium_stride_length) +
1671 sizeof(tng_data->long_stride_length) +
1672 sizeof(tng_data->distance_unit_exponential) +
1673 first_program_name_len +
1674 last_program_name_len +
1675 first_user_name_len +
1676 last_user_name_len +
1677 first_computer_name_len +
1678 last_computer_name_len +
1679 first_pgp_signature_len +
1680 last_pgp_signature_len +
1681 forcefield_name_len;
1683 if(block->block_contents)
1685 free(block->block_contents);
1687 block->block_contents = malloc(block->block_contents_size);
1688 if(!block->block_contents)
1690 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1691 block->block_contents_size, __FILE__, __LINE__);
1692 tng_block_destroy(&block);
1693 return(TNG_CRITICAL);
1696 strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
1697 offset += first_program_name_len;
1699 strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
1700 offset += last_program_name_len;
1702 strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
1703 offset += first_user_name_len;
1705 strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
1706 offset += last_user_name_len;
1708 strncpy(block->block_contents+offset, tng_data->first_computer_name,
1709 first_computer_name_len);
1710 offset += first_computer_name_len;
1712 strncpy(block->block_contents+offset, tng_data->last_computer_name,
1713 last_computer_name_len);
1714 offset += last_computer_name_len;
1716 strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
1717 first_pgp_signature_len);
1718 offset += first_pgp_signature_len;
1720 strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
1721 last_pgp_signature_len);
1722 offset += last_pgp_signature_len;
1724 strncpy(block->block_contents+offset, tng_data->forcefield_name,
1725 forcefield_name_len);
1726 offset += forcefield_name_len;
1728 memcpy(block->block_contents+offset, &tng_data->time,
1729 sizeof(tng_data->time));
1730 if(tng_data->output_endianness_swap_func_64)
1732 if(tng_data->output_endianness_swap_func_64(tng_data,
1733 (int64_t *)block->header_contents+offset)
1734 != TNG_SUCCESS)
1736 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1737 __FILE__, __LINE__);
1740 offset += sizeof(tng_data->time);
1742 memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
1743 sizeof(tng_data->var_num_atoms_flag));
1744 offset += sizeof(tng_data->var_num_atoms_flag);
1746 memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
1747 sizeof(tng_data->frame_set_n_frames));
1748 if(tng_data->output_endianness_swap_func_64)
1750 if(tng_data->output_endianness_swap_func_64(tng_data,
1751 (int64_t *)block->header_contents+offset)
1752 != TNG_SUCCESS)
1754 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1755 __FILE__, __LINE__);
1758 offset += sizeof(tng_data->frame_set_n_frames);
1760 memcpy(block->block_contents+offset,
1761 &tng_data->first_trajectory_frame_set_input_file_pos,
1762 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
1763 if(tng_data->output_endianness_swap_func_64)
1765 if(tng_data->output_endianness_swap_func_64(tng_data,
1766 (int64_t *)block->header_contents+offset)
1767 != TNG_SUCCESS)
1769 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1770 __FILE__, __LINE__);
1773 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
1775 memcpy(block->block_contents+offset,
1776 &tng_data->last_trajectory_frame_set_input_file_pos,
1777 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
1778 if(tng_data->output_endianness_swap_func_64)
1780 if(tng_data->output_endianness_swap_func_64(tng_data,
1781 (int64_t *)block->header_contents+offset)
1782 != TNG_SUCCESS)
1784 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1785 __FILE__, __LINE__);
1788 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
1790 memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
1791 sizeof(tng_data->medium_stride_length));
1792 if(tng_data->output_endianness_swap_func_64)
1794 if(tng_data->output_endianness_swap_func_64(tng_data,
1795 (int64_t *)block->header_contents+offset)
1796 != TNG_SUCCESS)
1798 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1799 __FILE__, __LINE__);
1802 offset += sizeof(tng_data->medium_stride_length);
1804 memcpy(block->block_contents+offset, &tng_data->long_stride_length,
1805 sizeof(tng_data->long_stride_length));
1806 if(tng_data->output_endianness_swap_func_64)
1808 if(tng_data->output_endianness_swap_func_64(tng_data,
1809 (int64_t *)block->header_contents+offset)
1810 != TNG_SUCCESS)
1812 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1813 __FILE__, __LINE__);
1816 offset += sizeof(tng_data->long_stride_length);
1818 memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
1819 sizeof(tng_data->distance_unit_exponential));
1820 if(tng_data->output_endianness_swap_func_64)
1822 if(tng_data->output_endianness_swap_func_64(tng_data,
1823 (int64_t *)block->header_contents+offset)
1824 != TNG_SUCCESS)
1826 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1827 __FILE__, __LINE__);
1831 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
1833 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
1834 tng_data->output_file_path, __FILE__, __LINE__);
1835 tng_block_destroy(&block);
1836 return(TNG_CRITICAL);
1839 if(fwrite(block->block_contents, block->block_contents_size, 1,
1840 tng_data->output_file) != 1)
1842 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
1843 tng_block_destroy(&block);
1844 return(TNG_CRITICAL);
1847 tng_block_destroy(&block);
1849 return(TNG_SUCCESS);
1852 /** Read the chain data of a molecules block.
1853 * @param tng_data is a trajectory data container.
1854 * @param block is a general block container.
1855 * @param chain is the chain data container.
1856 * @param offset is the offset of the block input and is updated when reading.
1857 * @return TNG_SUCCESS(0) is successful.
1859 static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
1860 tng_gen_block_t block,
1861 tng_chain_t chain,
1862 int *offset)
1864 int len;
1866 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1868 memcpy(&chain->id, block->block_contents+*offset,
1869 sizeof(chain->id));
1870 if(tng_data->input_endianness_swap_func_64)
1872 if(tng_data->input_endianness_swap_func_64(tng_data,
1873 &chain->id)
1874 != TNG_SUCCESS)
1876 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1877 __FILE__, __LINE__);
1880 *offset += sizeof(chain->id);
1882 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
1883 TNG_MAX_STR_LEN);
1884 chain->name = malloc(len);
1885 strncpy(chain->name,
1886 block->block_contents+*offset, len);
1887 *offset += len;
1889 memcpy(&chain->n_residues, block->block_contents+*offset,
1890 sizeof(chain->n_residues));
1891 if(tng_data->input_endianness_swap_func_64)
1893 if(tng_data->input_endianness_swap_func_64(tng_data,
1894 &chain->n_residues)
1895 != TNG_SUCCESS)
1897 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1898 __FILE__, __LINE__);
1901 *offset += sizeof(chain->n_residues);
1903 return(TNG_SUCCESS);
1906 /** Write the chain data of a molecules block.
1907 * @param tng_data is a trajectory data container.
1908 * @param block is a general block container.
1909 * @param chain is the chain data container.
1910 * @param offset is the offset of the block output and is updated when writing.
1911 * @return TNG_SUCCESS(0) is successful.
1913 static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
1914 tng_gen_block_t block,
1915 tng_chain_t chain,
1916 int *offset)
1918 int len;
1920 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1922 memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
1923 if(tng_data->output_endianness_swap_func_64)
1925 if(tng_data->output_endianness_swap_func_64(tng_data,
1926 (int64_t *)block->header_contents+*offset)
1927 != TNG_SUCCESS)
1929 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1930 __FILE__, __LINE__);
1933 *offset += sizeof(chain->id);
1935 len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
1936 strncpy(block->block_contents + *offset, chain->name, len);
1937 *offset += len;
1939 memcpy(block->block_contents+*offset, &chain->n_residues,
1940 sizeof(chain->n_residues));
1941 if(tng_data->output_endianness_swap_func_64)
1943 if(tng_data->output_endianness_swap_func_64(tng_data,
1944 (int64_t *)block->header_contents+*offset)
1945 != TNG_SUCCESS)
1947 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1948 __FILE__, __LINE__);
1951 *offset += sizeof(chain->n_residues);
1953 return(TNG_SUCCESS);
1956 /** Read the residue data of a molecules block.
1957 * @param tng_data is a trajectory data container.
1958 * @param block is a general block container.
1959 * @param residue is the residue data container.
1960 * @param offset is the offset of the block input and is updated when reading.
1961 * @return TNG_SUCCESS(0) is successful.
1963 static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
1964 tng_gen_block_t block,
1965 tng_residue_t residue,
1966 int *offset)
1968 int len;
1970 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1972 memcpy(&residue->id, block->block_contents+*offset,
1973 sizeof(residue->id));
1974 if(tng_data->input_endianness_swap_func_64)
1976 if(tng_data->input_endianness_swap_func_64(tng_data,
1977 &residue->id)
1978 != TNG_SUCCESS)
1980 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1981 __FILE__, __LINE__);
1984 *offset += sizeof(residue->id);
1986 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
1987 TNG_MAX_STR_LEN);
1988 residue->name = malloc(len);
1989 strncpy(residue->name,
1990 block->block_contents+*offset, len);
1991 *offset += len;
1993 memcpy(&residue->n_atoms, block->block_contents+*offset,
1994 sizeof(residue->n_atoms));
1995 if(tng_data->input_endianness_swap_func_64)
1997 if(tng_data->input_endianness_swap_func_64(tng_data,
1998 &residue->n_atoms)
1999 != TNG_SUCCESS)
2001 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2002 __FILE__, __LINE__);
2005 *offset += sizeof(residue->n_atoms);
2007 return(TNG_SUCCESS);
2010 /** Write the residue data of a molecules block.
2011 * @param tng_data is a trajectory data container.
2012 * @param block is a general block container.
2013 * @param residue is the residue data container.
2014 * @param offset is the offset of the block output and is updated when writing.
2015 * @return TNG_SUCCESS(0) is successful.
2017 static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
2018 tng_gen_block_t block,
2019 tng_residue_t residue,
2020 int *offset)
2022 int len;
2024 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2026 memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
2027 if(tng_data->output_endianness_swap_func_64)
2029 if(tng_data->output_endianness_swap_func_64(tng_data,
2030 (int64_t *)block->header_contents+*offset)
2031 != TNG_SUCCESS)
2033 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2034 __FILE__, __LINE__);
2037 *offset += sizeof(residue->id);
2039 len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2040 strncpy(block->block_contents + *offset, residue->name, len);
2041 *offset += len;
2043 memcpy(block->block_contents+*offset, &residue->n_atoms,
2044 sizeof(residue->n_atoms));
2045 if(tng_data->output_endianness_swap_func_64)
2047 if(tng_data->output_endianness_swap_func_64(tng_data,
2048 (int64_t *)block->header_contents+*offset)
2049 != TNG_SUCCESS)
2051 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2052 __FILE__, __LINE__);
2055 *offset += sizeof(residue->n_atoms);
2057 return(TNG_SUCCESS);
2060 /** Read the atom data of a molecules block.
2061 * @param tng_data is a trajectory data container.
2062 * @param block is a general block container.
2063 * @param atom is the atom data container.
2064 * @param offset is the offset of the block input and is updated when reading.
2065 * @return TNG_SUCCESS(0) is successful.
2067 static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
2068 tng_gen_block_t block,
2069 tng_atom_t atom,
2070 int *offset)
2072 int len;
2074 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2076 memcpy(&atom->id, block->block_contents+*offset,
2077 sizeof(atom->id));
2078 if(tng_data->input_endianness_swap_func_64)
2080 if(tng_data->input_endianness_swap_func_64(tng_data,
2081 &atom->id)
2082 != TNG_SUCCESS)
2084 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2085 __FILE__, __LINE__);
2088 *offset += sizeof(atom->id);
2090 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2091 TNG_MAX_STR_LEN);
2092 atom->name = malloc(len);
2093 strncpy(atom->name,
2094 block->block_contents+*offset, len);
2095 *offset += len;
2097 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2098 TNG_MAX_STR_LEN);
2099 atom->atom_type = malloc(len);
2100 strncpy(atom->atom_type,
2101 block->block_contents+*offset, len);
2102 *offset += len;
2104 return(TNG_SUCCESS);
2107 /** Write the atom data of a molecules block.
2108 * @param tng_data is a trajectory data container.
2109 * @param block is a general block container.
2110 * @param atom is the atom data container.
2111 * @param offset is the offset of the block output and is updated when writing.
2112 * @return TNG_SUCCESS(0) is successful.
2114 static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
2115 tng_gen_block_t block,
2116 tng_atom_t atom,
2117 int *offset)
2119 int len;
2121 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2123 memcpy(block->block_contents+*offset, &atom->id,
2124 sizeof(atom->id));
2125 if(tng_data->output_endianness_swap_func_64)
2127 if(tng_data->output_endianness_swap_func_64(tng_data,
2128 (int64_t *)block->header_contents+*offset)
2129 != TNG_SUCCESS)
2131 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2132 __FILE__, __LINE__);
2135 *offset += sizeof(atom->id);
2137 len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2138 strncpy(block->block_contents + *offset, atom->name, len);
2139 *offset += len;
2141 len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2142 strncpy(block->block_contents + *offset, atom->atom_type, len);
2143 *offset += len;
2145 return(TNG_SUCCESS);
2148 /** Read a molecules block. Contains chain, residue and atom data
2149 * @param tng_data is a trajectory data container.
2150 * @param block is a general block container.
2151 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2152 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2153 * compared to the md5 hash of the read contents to ensure valid data.
2154 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2155 * error has occured.
2157 static tng_function_status tng_molecules_block_read
2158 (tng_trajectory_t tng_data,
2159 tng_gen_block_t block,
2160 const char hash_mode)
2162 int64_t i, j, k, l;
2163 int len, offset = 0;
2164 tng_molecule_t molecule;
2165 tng_chain_t chain;
2166 tng_residue_t residue;
2167 tng_atom_t atom;
2168 tng_bond_t bond;
2169 tng_bool same_hash;
2171 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2173 return(TNG_CRITICAL);
2176 if(block->block_contents)
2178 free(block->block_contents);
2181 block->block_contents = malloc(block->block_contents_size);
2182 if(!block->block_contents)
2184 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2185 block->block_contents_size, __FILE__, __LINE__);
2186 return(TNG_CRITICAL);
2189 /* Read the whole block into block_contents to be able to write it to disk
2190 * even if it cannot be interpreted. */
2191 if(fread(block->block_contents, block->block_contents_size, 1,
2192 tng_data->input_file) == 0)
2194 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
2197 /* FIXME: Does not check if the size of the contents matches the expected
2198 * size or if the contents can be read. */
2200 if(hash_mode == TNG_USE_HASH)
2202 tng_md5_hash_match_verify(block, &same_hash);
2203 if(same_hash != TNG_TRUE)
2205 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
2206 "%s: %d\n",
2207 __FILE__, __LINE__);
2211 if(tng_data->molecules)
2213 for(i=tng_data->n_molecules; i--;)
2215 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
2217 free(tng_data->molecules);
2218 tng_data->molecules = 0;
2219 tng_data->n_molecules = 0;
2222 memcpy(&tng_data->n_molecules, block->block_contents,
2223 sizeof(tng_data->n_molecules));
2224 if(tng_data->input_endianness_swap_func_64)
2226 if(tng_data->input_endianness_swap_func_64(tng_data,
2227 &tng_data->n_molecules)
2228 != TNG_SUCCESS)
2230 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2231 __FILE__, __LINE__);
2234 offset += sizeof(tng_data->n_molecules);
2236 if(tng_data->molecules)
2238 free(tng_data->molecules);
2241 tng_data->n_particles = 0;
2243 tng_data->molecules = malloc(tng_data->n_molecules *
2244 sizeof(struct tng_molecule));
2245 if(!tng_data->molecules)
2247 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2248 tng_data->n_molecules * sizeof(struct tng_molecule),
2249 __FILE__, __LINE__);
2250 return(TNG_CRITICAL);
2253 if(!tng_data->var_num_atoms_flag)
2255 if(tng_data->molecule_cnt_list)
2257 free(tng_data->molecule_cnt_list);
2259 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
2260 tng_data->n_molecules);
2261 if(!tng_data->molecule_cnt_list)
2263 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2264 tng_data->n_molecules * sizeof(struct tng_molecule),
2265 __FILE__, __LINE__);
2266 return(TNG_CRITICAL);
2270 /* Read each molecule from file */
2271 for(i=0; i < tng_data->n_molecules; i++)
2273 molecule = &tng_data->molecules[i];
2275 memcpy(&molecule->id, block->block_contents+offset,
2276 sizeof(molecule->id));
2277 if(tng_data->input_endianness_swap_func_64)
2279 if(tng_data->input_endianness_swap_func_64(tng_data,
2280 &molecule->id)
2281 != TNG_SUCCESS)
2283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2284 __FILE__, __LINE__);
2287 offset += sizeof(molecule->id);
2289 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
2290 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2291 molecule->name = malloc(len);
2292 strncpy(molecule->name, block->block_contents+offset, len);
2293 offset += len;
2295 memcpy(&molecule->quaternary_str, block->block_contents+offset,
2296 sizeof(molecule->quaternary_str));
2297 if(tng_data->input_endianness_swap_func_64)
2299 if(tng_data->input_endianness_swap_func_64(tng_data,
2300 &molecule->quaternary_str)
2301 != TNG_SUCCESS)
2303 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2304 __FILE__, __LINE__);
2307 offset += sizeof(molecule->quaternary_str);
2309 if(!tng_data->var_num_atoms_flag)
2311 memcpy(&tng_data->molecule_cnt_list[i],
2312 block->block_contents+offset,
2313 sizeof(int64_t));
2314 if(tng_data->input_endianness_swap_func_64)
2316 if(tng_data->input_endianness_swap_func_64(tng_data,
2317 &tng_data->molecule_cnt_list[i])
2318 != TNG_SUCCESS)
2320 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2321 __FILE__, __LINE__);
2324 offset += sizeof(int64_t);
2328 memcpy(&molecule->n_chains, block->block_contents+offset,
2329 sizeof(molecule->n_chains));
2330 if(tng_data->input_endianness_swap_func_64)
2332 if(tng_data->input_endianness_swap_func_64(tng_data,
2333 &molecule->n_chains)
2334 != TNG_SUCCESS)
2336 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2337 __FILE__, __LINE__);
2340 offset += sizeof(molecule->n_chains);
2342 memcpy(&molecule->n_residues, block->block_contents+offset,
2343 sizeof(molecule->n_residues));
2344 if(tng_data->input_endianness_swap_func_64)
2346 if(tng_data->input_endianness_swap_func_64(tng_data,
2347 &molecule->n_residues)
2348 != TNG_SUCCESS)
2350 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2351 __FILE__, __LINE__);
2354 offset += sizeof(molecule->n_residues);
2356 memcpy(&molecule->n_atoms, block->block_contents+offset,
2357 sizeof(molecule->n_atoms));
2358 if(tng_data->input_endianness_swap_func_64)
2360 if(tng_data->input_endianness_swap_func_64(tng_data,
2361 &molecule->n_atoms)
2362 != TNG_SUCCESS)
2364 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2365 __FILE__, __LINE__);
2368 offset += sizeof(molecule->n_atoms);
2370 tng_data->n_particles += molecule->n_atoms *
2371 tng_data->molecule_cnt_list[i];
2373 if(molecule->n_chains > 0)
2375 molecule->chains = malloc(molecule->n_chains *
2376 sizeof(struct tng_chain));
2377 if(!molecule->chains)
2379 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2380 molecule->n_chains * sizeof(struct tng_chain),
2381 __FILE__, __LINE__);
2382 return(TNG_CRITICAL);
2385 chain = molecule->chains;
2387 else
2389 chain = 0;
2392 if(molecule->n_residues > 0)
2394 molecule->residues = malloc(molecule->n_residues *
2395 sizeof(struct tng_residue));
2396 if(!molecule->residues)
2398 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2399 molecule->n_residues * sizeof(struct tng_residue),
2400 __FILE__, __LINE__);
2401 if(molecule->chains)
2403 free(molecule->chains);
2404 molecule->chains = 0;
2406 return(TNG_CRITICAL);
2409 residue = molecule->residues;
2411 else
2413 residue = 0;
2416 molecule->atoms = malloc(molecule->n_atoms *
2417 sizeof(struct tng_atom));
2418 if(!molecule->atoms)
2420 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2421 molecule->n_atoms * sizeof(struct tng_atom),
2422 __FILE__, __LINE__);
2423 if(molecule->chains)
2425 free(molecule->chains);
2426 molecule->chains = 0;
2428 if(molecule->residues)
2430 free(molecule->residues);
2431 molecule->residues = 0;
2433 return(TNG_CRITICAL);
2436 atom = molecule->atoms;
2438 if(molecule->n_chains > 0)
2440 /* Read the chains of the molecule */
2441 for(j=molecule->n_chains; j--;)
2443 chain->molecule = molecule;
2445 tng_chain_data_read(tng_data, block, chain, &offset);
2447 chain->residues = molecule->residues;
2448 residue = chain->residues;
2450 /* Read the residues of the chain */
2451 for(k=chain->n_residues; k--;)
2453 residue->chain = chain;
2455 tng_residue_data_read(tng_data, block, residue, &offset);
2457 residue->atoms_offset = atom - molecule->atoms;
2458 /* Read the atoms of the residue */
2459 for(l=residue->n_atoms; l--;)
2461 atom->residue = residue;
2463 tng_atom_data_read(tng_data, block, atom, &offset);
2465 atom++;
2467 residue++;
2469 chain++;
2472 else
2474 if(molecule->n_residues > 0)
2476 for(k=molecule->n_residues; k--;)
2478 residue->chain = 0;
2480 tng_residue_data_read(tng_data, block, residue, &offset);
2482 residue->atoms_offset = atom - molecule->atoms;
2483 /* Read the atoms of the residue */
2484 for(l=residue->n_atoms; l--;)
2486 atom->residue = residue;
2488 tng_atom_data_read(tng_data, block, atom, &offset);
2490 atom++;
2492 residue++;
2495 else
2497 for(l=molecule->n_atoms; l--;)
2499 atom->residue = 0;
2501 tng_atom_data_read(tng_data, block, atom, &offset);
2503 atom++;
2508 memcpy(&molecule->n_bonds, block->block_contents+offset,
2509 sizeof(molecule->n_bonds));
2510 if(tng_data->input_endianness_swap_func_64)
2512 if(tng_data->input_endianness_swap_func_64(tng_data,
2513 &molecule->n_bonds)
2514 != TNG_SUCCESS)
2516 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2517 __FILE__, __LINE__);
2520 offset += sizeof(molecule->n_bonds);
2522 if(molecule->n_bonds > 0)
2524 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
2525 sizeof(struct tng_bond));
2526 if(!molecule->bonds)
2528 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2529 molecule->n_bonds * sizeof(struct tng_bond),
2530 __FILE__, __LINE__);
2531 if(molecule->chains)
2533 free(molecule->chains);
2534 molecule->chains = 0;
2536 if(molecule->residues)
2538 free(molecule->residues);
2539 molecule->residues = 0;
2541 if(molecule->atoms)
2543 free(molecule->atoms);
2544 molecule->atoms = 0;
2546 return(TNG_CRITICAL);
2549 bond = molecule->bonds;
2551 for(j=molecule->n_bonds; j--;)
2553 memcpy(&bond->from_atom_id, block->block_contents+offset,
2554 sizeof(bond->from_atom_id));
2555 if(tng_data->input_endianness_swap_func_64)
2557 if(tng_data->input_endianness_swap_func_64(tng_data,
2558 &bond->from_atom_id)
2559 != TNG_SUCCESS)
2561 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2562 __FILE__, __LINE__);
2565 offset += sizeof(bond->from_atom_id);
2567 memcpy(&bond->to_atom_id, block->block_contents+offset,
2568 sizeof(bond->to_atom_id));
2569 if(tng_data->input_endianness_swap_func_64)
2571 if(tng_data->input_endianness_swap_func_64(tng_data,
2572 &bond->to_atom_id)
2573 != TNG_SUCCESS)
2575 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2576 __FILE__, __LINE__);
2579 offset += sizeof(bond->to_atom_id);
2581 bond++;
2584 else
2586 molecule->bonds = 0;
2590 return(TNG_SUCCESS);
2593 /** Write a molecules block.
2594 * @param tng_data is a trajectory data container.
2595 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2596 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2597 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2598 * error has occured.
2600 static tng_function_status tng_molecules_block_write
2601 (tng_trajectory_t tng_data,
2602 const char hash_mode)
2604 int len = 0, name_len, offset = 0;
2605 int64_t i, j, k, l;
2606 tng_molecule_t molecule;
2607 tng_chain_t chain;
2608 tng_residue_t residue;
2609 tng_atom_t atom;
2610 tng_bond_t bond;
2611 tng_gen_block_t block;
2613 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2615 return(TNG_CRITICAL);
2618 /* First predict the size of the block */
2619 for(i = 0; i < tng_data->n_molecules; i++)
2621 molecule = &tng_data->molecules[i];
2622 if(!molecule->name)
2624 molecule->name = malloc(1);
2625 if(!molecule->name)
2627 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2628 __FILE__, __LINE__);
2629 return(TNG_CRITICAL);
2631 molecule->name[0] = 0;
2633 len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
2635 chain = molecule->chains;
2636 for(j = molecule->n_chains; j--;)
2638 len += sizeof(chain->id);
2640 if(!chain->name)
2642 chain->name = malloc(1);
2643 if(!chain->name)
2645 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2646 __FILE__, __LINE__);
2647 return(TNG_CRITICAL);
2649 chain->name[0] = 0;
2651 len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2653 len += sizeof(chain->n_residues);
2655 chain++;
2658 residue = molecule->residues;
2659 for(j = molecule->n_residues; j--;)
2661 len += sizeof(residue->id);
2663 if(!residue->name)
2665 residue->name = malloc(1);
2666 if(!residue->name)
2668 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2669 __FILE__, __LINE__);
2670 return(TNG_CRITICAL);
2672 residue->name[0] = 0;
2674 len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2676 len += sizeof(residue->n_atoms);
2678 residue++;
2681 atom = molecule->atoms;
2682 for(j = molecule->n_atoms; j--;)
2684 len += sizeof(atom->id);
2685 if(!atom->name)
2687 atom->name = malloc(1);
2688 if(!atom->name)
2690 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2691 __FILE__, __LINE__);
2692 return(TNG_CRITICAL);
2694 atom->name[0] = 0;
2696 len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2698 if(!atom->atom_type)
2700 atom->atom_type = malloc(1);
2701 if(!atom->atom_type)
2703 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2704 __FILE__, __LINE__);
2705 return(TNG_CRITICAL);
2707 atom->atom_type[0] = 0;
2709 len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2711 atom++;
2714 for(j = molecule->n_bonds; j--;)
2716 len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
2720 tng_block_init(&block);
2722 name_len = (int)strlen("MOLECULES");
2724 block->name = malloc(name_len + 1);
2725 if(!block->name)
2727 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2728 name_len+1, __FILE__, __LINE__);
2729 tng_block_destroy(&block);
2730 return(TNG_CRITICAL);
2733 strcpy(block->name, "MOLECULES");
2734 block->id = TNG_MOLECULES;
2736 block->block_contents_size = sizeof(tng_data->n_molecules) +
2737 (sizeof(molecule->id) +
2738 sizeof(molecule->quaternary_str) +
2739 sizeof(molecule->n_chains) +
2740 sizeof(molecule->n_residues) +
2741 sizeof(molecule->n_atoms) +
2742 sizeof(molecule->n_bonds)) *
2743 tng_data->n_molecules +
2744 len;
2746 if(!tng_data->var_num_atoms_flag)
2748 block->block_contents_size += tng_data->n_molecules * sizeof(int64_t);
2751 block->block_contents = malloc(block->block_contents_size);
2752 if(!block->block_contents)
2754 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2755 block->block_contents_size, __FILE__, __LINE__);
2756 tng_block_destroy(&block);
2757 return(TNG_CRITICAL);
2760 memcpy(block->block_contents+offset, &tng_data->n_molecules,
2761 sizeof(tng_data->n_molecules));
2762 if(tng_data->output_endianness_swap_func_64)
2764 if(tng_data->output_endianness_swap_func_64(tng_data,
2765 (int64_t *)block->header_contents+offset)
2766 != TNG_SUCCESS)
2768 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2769 __FILE__, __LINE__);
2772 offset += sizeof(tng_data->n_molecules);
2774 for(i = 0; i < tng_data->n_molecules; i++)
2776 molecule = &tng_data->molecules[i];
2777 memcpy(block->block_contents+offset, &molecule->id,
2778 sizeof(molecule->id));
2779 if(tng_data->output_endianness_swap_func_64)
2781 if(tng_data->output_endianness_swap_func_64(tng_data,
2782 (int64_t *)block->header_contents+offset)
2783 != TNG_SUCCESS)
2785 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2786 __FILE__, __LINE__);
2789 offset += sizeof(molecule->id);
2791 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
2792 len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
2793 strncpy(block->block_contents + offset, molecule->name, len);
2794 offset += len;
2796 memcpy(block->block_contents+offset, &molecule->quaternary_str,
2797 sizeof(molecule->quaternary_str));
2798 if(tng_data->output_endianness_swap_func_64)
2800 if(tng_data->output_endianness_swap_func_64(tng_data,
2801 (int64_t *)block->header_contents+offset)
2802 != TNG_SUCCESS)
2804 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2805 __FILE__, __LINE__);
2808 offset += sizeof(molecule->quaternary_str);
2810 if(!tng_data->var_num_atoms_flag)
2812 memcpy(block->block_contents+offset,
2813 &tng_data->molecule_cnt_list[i], sizeof(int64_t));
2814 if(tng_data->output_endianness_swap_func_64)
2816 if(tng_data->output_endianness_swap_func_64(tng_data,
2817 (int64_t *)block->header_contents+offset)
2818 != TNG_SUCCESS)
2820 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2821 __FILE__, __LINE__);
2824 offset += sizeof(int64_t);
2827 memcpy(block->block_contents+offset, &molecule->n_chains,
2828 sizeof(molecule->n_chains));
2829 if(tng_data->output_endianness_swap_func_64)
2831 if(tng_data->output_endianness_swap_func_64(tng_data,
2832 (int64_t *)block->header_contents+offset)
2833 != TNG_SUCCESS)
2835 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2836 __FILE__, __LINE__);
2839 offset += sizeof(molecule->n_chains);
2841 memcpy(block->block_contents+offset, &molecule->n_residues,
2842 sizeof(molecule->n_residues));
2843 if(tng_data->output_endianness_swap_func_64)
2845 if(tng_data->output_endianness_swap_func_64(tng_data,
2846 (int64_t *)block->header_contents+offset)
2847 != TNG_SUCCESS)
2849 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2850 __FILE__, __LINE__);
2853 offset += sizeof(molecule->n_residues);
2855 memcpy(block->block_contents+offset, &molecule->n_atoms,
2856 sizeof(molecule->n_atoms));
2857 if(tng_data->output_endianness_swap_func_64)
2859 if(tng_data->output_endianness_swap_func_64(tng_data,
2860 (int64_t *)block->header_contents+offset)
2861 != TNG_SUCCESS)
2863 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2864 __FILE__, __LINE__);
2867 offset += sizeof(molecule->n_atoms);
2869 if(molecule->n_chains > 0)
2871 chain = molecule->chains;
2872 for(j = molecule->n_chains; j--;)
2874 tng_chain_data_write(tng_data, block, chain, &offset);
2876 residue = chain->residues;
2877 for(k = chain->n_residues; k--;)
2879 tng_residue_data_write(tng_data, block, residue, &offset);
2881 atom = molecule->atoms + residue->atoms_offset;
2882 for(l = residue->n_atoms; l--;)
2884 tng_atom_data_write(tng_data, block, atom, &offset);
2886 atom++;
2888 residue++;
2890 chain++;
2893 else
2895 if(molecule->n_residues > 0)
2897 residue = molecule->residues;
2898 for(k = molecule->n_residues; k--;)
2900 tng_residue_data_write(tng_data, block, residue, &offset);
2902 atom = molecule->atoms + residue->atoms_offset;
2903 for(l = residue->n_atoms; l--;)
2905 tng_atom_data_write(tng_data, block, atom, &offset);
2907 atom++;
2909 residue++;
2912 else
2914 atom = molecule->atoms;
2915 for(l = molecule->n_atoms; l--;)
2917 tng_atom_data_write(tng_data, block, atom, &offset);
2919 atom++;
2924 memcpy(block->block_contents+offset, &molecule->n_bonds,
2925 sizeof(molecule->n_bonds));
2926 if(tng_data->output_endianness_swap_func_64)
2928 if(tng_data->output_endianness_swap_func_64(tng_data,
2929 (int64_t *)block->header_contents+offset)
2930 != TNG_SUCCESS)
2932 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2933 __FILE__, __LINE__);
2936 offset += sizeof(molecule->n_bonds);
2938 bond = molecule->bonds;
2939 for(j = molecule->n_bonds; j--;)
2941 memcpy(block->block_contents+offset, &bond->from_atom_id,
2942 sizeof(bond->from_atom_id));
2943 if(tng_data->output_endianness_swap_func_64)
2945 if(tng_data->output_endianness_swap_func_64(tng_data,
2946 (int64_t *)block->header_contents+offset)
2947 != TNG_SUCCESS)
2949 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2950 __FILE__, __LINE__);
2953 offset += sizeof(bond->from_atom_id);
2955 memcpy(block->block_contents+offset, &bond->to_atom_id,
2956 sizeof(bond->to_atom_id));
2957 if(tng_data->output_endianness_swap_func_64)
2959 if(tng_data->output_endianness_swap_func_64(tng_data,
2960 (int64_t *)block->header_contents+offset)
2961 != TNG_SUCCESS)
2963 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2964 __FILE__, __LINE__);
2967 offset += sizeof(bond->to_atom_id);
2969 bond++;
2973 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
2975 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2976 tng_data->output_file_path, __FILE__, __LINE__);
2977 tng_block_destroy(&block);
2978 return(TNG_CRITICAL);
2981 if(fwrite(block->block_contents, block->block_contents_size, 1,
2982 tng_data->output_file) != 1)
2984 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
2985 __FILE__, __LINE__);
2986 tng_block_destroy(&block);
2987 return(TNG_CRITICAL);
2990 tng_block_destroy(&block);
2992 return(TNG_SUCCESS);
2995 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
2996 * @param tng_data is a trajectory data container.
2997 * @param block is a general block container.
2998 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2999 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3000 * compared to the md5 hash of the read contents to ensure valid data.
3001 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3002 * error has occured.
3004 static tng_function_status tng_frame_set_block_read
3005 (tng_trajectory_t tng_data,
3006 tng_gen_block_t block,
3007 const char hash_mode)
3009 long file_pos;
3010 int offset = 0;
3011 int64_t i, prev_n_particles;
3012 tng_bool same_hash;
3013 tng_trajectory_frame_set_t frame_set =
3014 &tng_data->current_trajectory_frame_set;
3016 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3018 return(TNG_CRITICAL);
3021 if(block->block_contents)
3023 free(block->block_contents);
3026 block->block_contents = malloc(block->block_contents_size);
3027 if(!block->block_contents)
3029 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3030 block->block_contents_size, __FILE__, __LINE__);
3031 return(TNG_CRITICAL);
3034 /* Read the whole block into block_contents to be able to write it to
3035 * disk even if it cannot be interpreted. */
3036 if(fread(block->block_contents, block->block_contents_size, 1,
3037 tng_data->input_file) == 0)
3039 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3040 return(TNG_CRITICAL);
3043 /* FIXME: Does not check if the size of the contents matches the expected
3044 * size or if the contents can be read. */
3046 file_pos = (int64_t)ftell(tng_data->input_file) -
3047 (long)(block->block_contents_size + block->header_contents_size);
3049 if(hash_mode == TNG_USE_HASH)
3051 tng_md5_hash_match_verify(block, &same_hash);
3052 if(same_hash != TNG_TRUE)
3054 fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %ld Hashes do not match. "
3055 "%s: %d\n",
3056 file_pos, __FILE__, __LINE__);
3057 /* return(TNG_FAILURE); */
3061 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3063 tng_frame_set_particle_mapping_free(tng_data);
3065 if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
3067 tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
3069 /* FIXME: Should check the frame number instead of the file_pos, in case
3070 * frame sets are not in order */
3071 if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
3073 tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
3076 memcpy(&frame_set->first_frame, block->block_contents,
3077 sizeof(frame_set->first_frame));
3078 if(tng_data->input_endianness_swap_func_64)
3080 if(tng_data->input_endianness_swap_func_64(tng_data,
3081 &frame_set->first_frame)
3082 != TNG_SUCCESS)
3084 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3085 __FILE__, __LINE__);
3088 offset += sizeof(frame_set->first_frame);
3090 memcpy(&frame_set->n_frames, block->block_contents + offset,
3091 sizeof(frame_set->n_frames));
3092 if(tng_data->input_endianness_swap_func_64)
3094 if(tng_data->input_endianness_swap_func_64(tng_data,
3095 &frame_set->n_frames)
3096 != TNG_SUCCESS)
3098 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3099 __FILE__, __LINE__);
3102 offset += sizeof(frame_set->n_frames);
3104 if(tng_data->var_num_atoms_flag)
3106 prev_n_particles = frame_set->n_particles;
3107 frame_set->n_particles = 0;
3108 /* If the list of molecule counts has already been created assume that
3109 * it is of correct size. */
3110 if(!frame_set->molecule_cnt_list)
3112 frame_set->molecule_cnt_list =
3113 malloc(sizeof(int64_t) * tng_data->n_molecules);
3115 if(!frame_set->molecule_cnt_list)
3117 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3118 sizeof(int64_t) * tng_data->n_molecules,
3119 __FILE__, __LINE__);
3120 return(TNG_CRITICAL);
3123 for(i = 0; i < tng_data->n_molecules; i++)
3125 memcpy(&frame_set->molecule_cnt_list[i],
3126 block->block_contents + offset,
3127 sizeof(int64_t));
3128 if(tng_data->input_endianness_swap_func_64)
3130 if(tng_data->input_endianness_swap_func_64(tng_data,
3131 &frame_set->molecule_cnt_list[i])
3132 != TNG_SUCCESS)
3134 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3135 __FILE__, __LINE__);
3138 offset += sizeof(int64_t);
3139 frame_set->n_particles += tng_data->molecules[i].n_atoms *
3140 frame_set->molecule_cnt_list[i];
3142 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
3144 /* FIXME: Particle dependent data memory management */
3148 memcpy(&frame_set->next_frame_set_file_pos,
3149 block->block_contents + offset,
3150 sizeof(frame_set->next_frame_set_file_pos));
3151 if(tng_data->input_endianness_swap_func_64)
3153 if(tng_data->input_endianness_swap_func_64(tng_data,
3154 &frame_set->next_frame_set_file_pos)
3155 != TNG_SUCCESS)
3157 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3158 __FILE__, __LINE__);
3161 offset += sizeof(frame_set->next_frame_set_file_pos);
3163 memcpy(&frame_set->prev_frame_set_file_pos,
3164 block->block_contents + offset,
3165 sizeof(frame_set->prev_frame_set_file_pos));
3166 if(tng_data->input_endianness_swap_func_64)
3168 if(tng_data->input_endianness_swap_func_64(tng_data,
3169 &frame_set->prev_frame_set_file_pos)
3170 != TNG_SUCCESS)
3172 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3173 __FILE__, __LINE__);
3176 offset += sizeof(frame_set->prev_frame_set_file_pos);
3178 memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
3179 block->block_contents + offset,
3180 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
3181 if(tng_data->input_endianness_swap_func_64)
3183 if(tng_data->input_endianness_swap_func_64(tng_data,
3184 &frame_set->medium_stride_next_frame_set_file_pos)
3185 != TNG_SUCCESS)
3187 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3188 __FILE__, __LINE__);
3191 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
3193 memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
3194 block->block_contents + offset,
3195 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
3196 if(tng_data->input_endianness_swap_func_64)
3198 if(tng_data->input_endianness_swap_func_64(tng_data,
3199 &frame_set->medium_stride_prev_frame_set_file_pos)
3200 != TNG_SUCCESS)
3202 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3203 __FILE__, __LINE__);
3206 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
3208 memcpy(&frame_set->long_stride_next_frame_set_file_pos,
3209 block->block_contents + offset,
3210 sizeof(frame_set->long_stride_next_frame_set_file_pos));
3211 if(tng_data->input_endianness_swap_func_64)
3213 if(tng_data->input_endianness_swap_func_64(tng_data,
3214 &frame_set->long_stride_next_frame_set_file_pos)
3215 != TNG_SUCCESS)
3217 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3218 __FILE__, __LINE__);
3221 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
3223 memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
3224 block->block_contents + offset,
3225 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
3226 if(tng_data->input_endianness_swap_func_64)
3228 if(tng_data->input_endianness_swap_func_64(tng_data,
3229 &frame_set->long_stride_prev_frame_set_file_pos)
3230 != TNG_SUCCESS)
3232 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3233 __FILE__, __LINE__);
3236 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
3238 if(block->block_version >= 3)
3240 memcpy(&frame_set->first_frame_time,
3241 block->block_contents + offset,
3242 sizeof(frame_set->first_frame_time));
3243 if(tng_data->input_endianness_swap_func_64)
3245 if(tng_data->input_endianness_swap_func_64(tng_data,
3246 (int64_t *)&frame_set->first_frame_time)
3247 != TNG_SUCCESS)
3249 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3250 __FILE__, __LINE__);
3253 offset += sizeof(frame_set->first_frame_time);
3255 memcpy(&tng_data->time_per_frame,
3256 block->block_contents + offset,
3257 sizeof(tng_data->time_per_frame));
3258 if(tng_data->input_endianness_swap_func_64)
3260 if(tng_data->input_endianness_swap_func_64(tng_data,
3261 (int64_t *)&tng_data->time_per_frame)
3262 != TNG_SUCCESS)
3264 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3265 __FILE__, __LINE__);
3269 else
3271 frame_set->first_frame_time = -1;
3272 tng_data->time_per_frame = -1;
3275 frame_set->n_written_frames = frame_set->n_frames;
3277 return(TNG_SUCCESS);
3280 /** Write tng_data->current_trajectory_frame_set to file
3281 * @param tng_data is a trajectory data container.
3282 * @param block is a general block container.
3283 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3284 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3285 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3286 * error has occured.
3288 static tng_function_status tng_frame_set_block_write
3289 (tng_trajectory_t tng_data,
3290 tng_gen_block_t block,
3291 const char hash_mode)
3293 char *temp_name;
3294 int64_t i;
3295 int offset = 0;
3296 unsigned int name_len;
3297 tng_trajectory_frame_set_t frame_set =
3298 &tng_data->current_trajectory_frame_set;
3300 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3302 return(TNG_CRITICAL);
3305 name_len = (int)strlen("TRAJECTORY FRAME SET");
3307 if(!block->name || strlen(block->name) < name_len)
3309 temp_name = realloc(block->name, name_len + 1);
3310 if(!temp_name)
3312 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3313 name_len+1, __FILE__, __LINE__);
3314 free(block->name);
3315 block->name = 0;
3316 return(TNG_CRITICAL);
3318 block->name = temp_name;
3320 strcpy(block->name, "TRAJECTORY FRAME SET");
3321 block->id = TNG_TRAJECTORY_FRAME_SET;
3323 block->block_contents_size = sizeof(int64_t) * 8;
3324 block->block_contents_size += sizeof(double) * 2;
3326 if(tng_data->var_num_atoms_flag)
3328 block->block_contents_size += sizeof(int64_t) * tng_data->n_molecules;
3331 if(block->block_contents)
3333 free(block->block_contents);
3335 block->block_contents = malloc(block->block_contents_size);
3336 if(!block->block_contents)
3338 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3339 block->block_contents_size, __FILE__, __LINE__);
3340 return(TNG_CRITICAL);
3343 memcpy(block->block_contents, &frame_set->first_frame,
3344 sizeof(frame_set->first_frame));
3345 if(tng_data->output_endianness_swap_func_64)
3347 if(tng_data->output_endianness_swap_func_64(tng_data,
3348 (int64_t *)block->header_contents+offset)
3349 != TNG_SUCCESS)
3351 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3352 __FILE__, __LINE__);
3355 offset += sizeof(frame_set->first_frame);
3357 memcpy(block->block_contents+offset, &frame_set->n_frames,
3358 sizeof(frame_set->n_frames));
3359 if(tng_data->output_endianness_swap_func_64)
3361 if(tng_data->output_endianness_swap_func_64(tng_data,
3362 (int64_t *)block->header_contents+offset)
3363 != TNG_SUCCESS)
3365 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3366 __FILE__, __LINE__);
3369 offset += sizeof(frame_set->n_frames);
3371 if(tng_data->var_num_atoms_flag)
3373 for(i = 0; i < tng_data->n_molecules; i++)
3375 memcpy(block->block_contents+offset,
3376 &frame_set->molecule_cnt_list[i],
3377 sizeof(int64_t));
3378 if(tng_data->output_endianness_swap_func_64)
3380 if(tng_data->output_endianness_swap_func_64(tng_data,
3381 (int64_t *)block->header_contents+offset)
3382 != TNG_SUCCESS)
3384 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3385 __FILE__, __LINE__);
3388 offset += sizeof(int64_t);
3393 memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
3394 sizeof(frame_set->next_frame_set_file_pos));
3395 if(tng_data->output_endianness_swap_func_64)
3397 if(tng_data->output_endianness_swap_func_64(tng_data,
3398 (int64_t *)block->header_contents+offset)
3399 != TNG_SUCCESS)
3401 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3402 __FILE__, __LINE__);
3405 offset += sizeof(frame_set->next_frame_set_file_pos);
3407 memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
3408 sizeof(frame_set->prev_frame_set_file_pos));
3409 if(tng_data->output_endianness_swap_func_64)
3411 if(tng_data->output_endianness_swap_func_64(tng_data,
3412 (int64_t *)block->header_contents+offset)
3413 != TNG_SUCCESS)
3415 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3416 __FILE__, __LINE__);
3419 offset += sizeof(frame_set->prev_frame_set_file_pos);
3421 memcpy(block->block_contents+offset,
3422 &frame_set->medium_stride_next_frame_set_file_pos,
3423 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
3424 if(tng_data->output_endianness_swap_func_64)
3426 if(tng_data->output_endianness_swap_func_64(tng_data,
3427 (int64_t *)block->header_contents+offset)
3428 != TNG_SUCCESS)
3430 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3431 __FILE__, __LINE__);
3434 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
3436 memcpy(block->block_contents+offset,
3437 &frame_set->medium_stride_prev_frame_set_file_pos,
3438 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
3439 if(tng_data->output_endianness_swap_func_64)
3441 if(tng_data->output_endianness_swap_func_64(tng_data,
3442 (int64_t *)block->header_contents+offset)
3443 != TNG_SUCCESS)
3445 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3446 __FILE__, __LINE__);
3449 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
3451 memcpy(block->block_contents+offset,
3452 &frame_set->long_stride_next_frame_set_file_pos,
3453 sizeof(frame_set->long_stride_next_frame_set_file_pos));
3454 if(tng_data->output_endianness_swap_func_64)
3456 if(tng_data->output_endianness_swap_func_64(tng_data,
3457 (int64_t *)block->header_contents+offset)
3458 != TNG_SUCCESS)
3460 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3461 __FILE__, __LINE__);
3464 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
3466 memcpy(block->block_contents+offset,
3467 &frame_set->long_stride_prev_frame_set_file_pos,
3468 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
3469 if(tng_data->output_endianness_swap_func_64)
3471 if(tng_data->output_endianness_swap_func_64(tng_data,
3472 (int64_t *)block->header_contents+offset)
3473 != TNG_SUCCESS)
3475 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3476 __FILE__, __LINE__);
3479 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
3481 memcpy(block->block_contents+offset,
3482 &frame_set->first_frame_time,
3483 sizeof(frame_set->first_frame_time));
3484 if(tng_data->output_endianness_swap_func_64)
3486 if(tng_data->output_endianness_swap_func_64(tng_data,
3487 (int64_t *)block->header_contents+offset)
3488 != TNG_SUCCESS)
3490 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3491 __FILE__, __LINE__);
3494 offset += sizeof(frame_set->first_frame_time);
3496 memcpy(block->block_contents+offset,
3497 &tng_data->time_per_frame,
3498 sizeof(tng_data->time_per_frame));
3499 if(tng_data->output_endianness_swap_func_64)
3501 if(tng_data->output_endianness_swap_func_64(tng_data,
3502 (int64_t *)block->header_contents+offset)
3503 != TNG_SUCCESS)
3505 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3506 __FILE__, __LINE__);
3510 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3512 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3513 tng_data->output_file_path, __FILE__, __LINE__);
3514 return(TNG_CRITICAL);
3517 if(fwrite(block->block_contents, block->block_contents_size, 1,
3518 tng_data->output_file) != 1)
3520 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
3521 return(TNG_CRITICAL);
3524 return(TNG_SUCCESS);
3528 /** Read an atom mappings block (translating between real atom indexes and how
3529 * the atom info is written in this frame set).
3530 * @param tng_data is a trajectory data container.
3531 * @param block is a general block container.
3532 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3533 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3534 * compared to the md5 hash of the read contents to ensure valid data.
3535 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3536 * error has occured.
3538 static tng_function_status tng_trajectory_mapping_block_read
3539 (tng_trajectory_t tng_data,
3540 tng_gen_block_t block,
3541 const char hash_mode)
3543 int64_t i;
3544 int offset = 0;
3545 tng_bool same_hash;
3546 tng_trajectory_frame_set_t frame_set =
3547 &tng_data->current_trajectory_frame_set;
3549 tng_particle_mapping_t mapping, mappings;
3551 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3553 return(TNG_CRITICAL);
3556 if(block->block_contents)
3558 free(block->block_contents);
3561 block->block_contents = malloc(block->block_contents_size);
3562 if(!block->block_contents)
3564 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3565 block->block_contents_size, __FILE__, __LINE__);
3566 return(TNG_CRITICAL);
3569 /* Read the whole block into block_contents to be able to write it to disk
3570 * even if it cannot be interpreted. */
3571 if(fread(block->block_contents, block->block_contents_size, 1,
3572 tng_data->input_file) == 0)
3574 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3575 return(TNG_CRITICAL);
3578 /* FIXME: Does not check if the size of the contents matches the expected
3579 * size or if the contents can be read. */
3581 if(hash_mode == TNG_USE_HASH)
3583 tng_md5_hash_match_verify(block, &same_hash);
3584 if(same_hash != TNG_TRUE)
3586 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
3587 "%s: %d\n",
3588 __FILE__, __LINE__);
3589 /* return(TNG_FAILURE); */
3593 frame_set->n_mapping_blocks++;
3594 mappings = realloc(frame_set->mappings,
3595 sizeof(struct tng_particle_mapping) *
3596 frame_set->n_mapping_blocks);
3597 if(!mappings)
3599 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3600 block->block_contents_size, __FILE__, __LINE__);
3601 free(frame_set->mappings);
3602 frame_set->mappings = 0;
3603 return(TNG_CRITICAL);
3605 frame_set->mappings = mappings;
3606 mapping = &mappings[frame_set->n_mapping_blocks - 1];
3609 memcpy(&mapping->num_first_particle, block->block_contents+offset,
3610 sizeof(mapping->num_first_particle));
3611 if(tng_data->input_endianness_swap_func_64)
3613 if(tng_data->input_endianness_swap_func_64(tng_data,
3614 &mapping->num_first_particle)
3615 != TNG_SUCCESS)
3617 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3618 __FILE__, __LINE__);
3621 offset += sizeof(mapping->num_first_particle);
3623 memcpy(&mapping->n_particles, block->block_contents+offset,
3624 sizeof(mapping->n_particles));
3625 if(tng_data->input_endianness_swap_func_64)
3627 if(tng_data->input_endianness_swap_func_64(tng_data,
3628 &mapping->n_particles)
3629 != TNG_SUCCESS)
3631 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3632 __FILE__, __LINE__);
3635 offset += sizeof(mapping->n_particles);
3637 mapping->real_particle_numbers = malloc(mapping->n_particles *
3638 sizeof(int64_t));
3639 if(!mapping->real_particle_numbers)
3641 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3642 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
3643 return(TNG_CRITICAL);
3646 /* If the byte order needs to be swapped the data must be read one value at
3647 * a time and swapped */
3648 if(tng_data->input_endianness_swap_func_64)
3650 for(i = 0; i < mapping->n_particles; i++)
3652 memcpy(&mapping->real_particle_numbers[i],
3653 block->block_contents + offset,
3654 sizeof(int64_t));
3655 if(tng_data->input_endianness_swap_func_64(tng_data,
3656 &mapping->real_particle_numbers[i])
3657 != TNG_SUCCESS)
3659 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3660 __FILE__, __LINE__);
3662 offset += sizeof(int64_t);
3665 /* Otherwise the data can be read all at once */
3666 else
3668 memcpy(mapping->real_particle_numbers, block->block_contents + offset,
3669 mapping->n_particles * sizeof(int64_t));
3673 return(TNG_SUCCESS);
3676 /** Write the atom mappings of the current trajectory frame set
3677 * @param tng_data is a trajectory data container.
3678 * @param block is a general block container.
3679 * @param mapping_block_nr is the index of the mapping block to write.
3680 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3681 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3682 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
3683 * has occurred or TNG_CRITICAL (2) if a major error has occured.
3685 static tng_function_status tng_trajectory_mapping_block_write
3686 (tng_trajectory_t tng_data,
3687 tng_gen_block_t block,
3688 int mapping_block_nr,
3689 const char hash_mode)
3691 char *temp_name;
3692 int i, offset = 0;
3693 unsigned int name_len;
3694 tng_particle_mapping_t mapping =
3695 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
3697 if(mapping_block_nr >=
3698 tng_data->current_trajectory_frame_set.n_mapping_blocks)
3700 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
3701 __FILE__, __LINE__);
3702 return(TNG_FAILURE);
3705 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3707 return(TNG_CRITICAL);
3710 name_len = (int)strlen("PARTICLE MAPPING");
3712 if(!block->name || strlen(block->name) < name_len)
3714 temp_name = realloc(block->name, name_len + 1);
3715 if(!temp_name)
3717 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3718 name_len+1, __FILE__, __LINE__);
3719 free(block->name);
3720 block->name = 0;
3721 return(TNG_CRITICAL);
3723 block->name = temp_name;
3725 strcpy(block->name, "PARTICLE MAPPING");
3726 block->id = TNG_PARTICLE_MAPPING;
3728 block->block_contents_size = sizeof(int64_t) * (2 + mapping->n_particles);
3730 if(block->block_contents)
3732 free(block->block_contents);
3734 block->block_contents = malloc(block->block_contents_size);
3735 if(!block->block_contents)
3737 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3738 block->block_contents_size, __FILE__, __LINE__);
3739 return(TNG_CRITICAL);
3742 memcpy(block->block_contents, &mapping->num_first_particle,
3743 sizeof(mapping->num_first_particle));
3744 if(tng_data->output_endianness_swap_func_64)
3746 if(tng_data->output_endianness_swap_func_64(tng_data,
3747 (int64_t *)block->header_contents+offset)
3748 != TNG_SUCCESS)
3750 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3751 __FILE__, __LINE__);
3754 offset += sizeof(mapping->num_first_particle);
3756 memcpy(block->block_contents+offset, &mapping->n_particles,
3757 sizeof(mapping->n_particles));
3758 if(tng_data->output_endianness_swap_func_64)
3760 if(tng_data->output_endianness_swap_func_64(tng_data,
3761 (int64_t *)block->header_contents+offset)
3762 != TNG_SUCCESS)
3764 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3765 __FILE__, __LINE__);
3768 offset += sizeof(mapping->n_particles);
3770 if(tng_data->output_endianness_swap_func_64)
3772 for(i = 0; i < mapping->n_particles; i++)
3774 memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
3775 sizeof(int64_t));
3776 if(tng_data->output_endianness_swap_func_64(tng_data,
3777 (int64_t *)block->header_contents+offset)
3778 != TNG_SUCCESS)
3780 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3781 __FILE__, __LINE__);
3783 offset += sizeof(int64_t);
3786 else
3788 memcpy(block->block_contents+offset, mapping->real_particle_numbers,
3789 mapping->n_particles * sizeof(int64_t));
3793 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3795 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3796 tng_data->output_file_path, __FILE__, __LINE__);
3797 return(TNG_CRITICAL);
3800 if(fwrite(block->block_contents, block->block_contents_size, 1,
3801 tng_data->output_file) != 1)
3803 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
3804 return(TNG_CRITICAL);
3807 return(TNG_SUCCESS);
3810 /** Prepare a block for storing particle data
3811 * @param tng_data is a trajectory data container.
3812 * @param block_type_flag specifies if this is a trajectory block or a
3813 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
3814 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3815 * error has occured.
3817 static tng_function_status tng_particle_data_block_create
3818 (tng_trajectory_t tng_data,
3819 const char block_type_flag)
3821 tng_trajectory_frame_set_t frame_set =
3822 &tng_data->current_trajectory_frame_set;
3824 tng_particle_data_t data;
3826 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
3828 frame_set->n_particle_data_blocks++;
3829 data = realloc(frame_set->tr_particle_data,
3830 sizeof(struct tng_particle_data) *
3831 frame_set->n_particle_data_blocks);
3832 if(!data)
3834 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
3835 sizeof(struct tng_particle_data) *
3836 frame_set->n_particle_data_blocks,
3837 __FILE__, __LINE__);
3838 free(frame_set->tr_particle_data);
3839 frame_set->tr_particle_data = 0;
3840 return(TNG_CRITICAL);
3842 frame_set->tr_particle_data = data;
3844 else
3846 tng_data->n_particle_data_blocks++;
3847 data = realloc(tng_data->non_tr_particle_data,
3848 sizeof(struct tng_particle_data) *
3849 tng_data->n_particle_data_blocks);
3850 if(!data)
3852 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
3853 sizeof(struct tng_particle_data) *
3854 tng_data->n_particle_data_blocks,
3855 __FILE__, __LINE__);
3856 free(tng_data->non_tr_particle_data);
3857 tng_data->non_tr_particle_data = 0;
3858 return(TNG_CRITICAL);
3860 tng_data->non_tr_particle_data = data;
3863 return(TNG_SUCCESS);
3866 static tng_function_status tng_compress(tng_trajectory_t tng_data,
3867 tng_gen_block_t block,
3868 const int64_t n_frames,
3869 const int64_t n_particles,
3870 const char type,
3871 void *start_pos)
3873 int nalgo;
3874 int new_len;
3875 int *alt_algo = 0;
3876 char *dest, *temp;
3877 int64_t algo_find_n_frames;
3878 unsigned long offset;
3879 float f_precision;
3880 double d_precision;
3882 if(block->id != TNG_TRAJ_POSITIONS &&
3883 block->id != TNG_TRAJ_VELOCITIES)
3885 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
3886 "TNG method. %s: %d\n", __FILE__, __LINE__);
3887 return(TNG_FAILURE);
3889 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
3891 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
3892 return(TNG_FAILURE);
3895 if(n_frames <= 0 || n_particles <= 0)
3897 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
3898 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
3899 return(TNG_FAILURE);
3902 f_precision = 1/(float)tng_data->compression_precision;
3903 d_precision = 1/tng_data->compression_precision;
3905 if(block->id == TNG_TRAJ_POSITIONS)
3907 /* If there is only one frame in this frame set and there might be more
3908 * do not store the algorithm as the compression algorithm, but find
3909 * the best one without storing it */
3910 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
3912 nalgo = tng_compress_nalgo();
3913 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
3914 if(type == TNG_FLOAT_DATA)
3916 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
3917 (int)n_frames,
3918 f_precision,
3919 0, alt_algo,
3920 &new_len);
3923 else
3925 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
3926 (int)n_frames,
3927 d_precision,
3928 0, alt_algo,
3929 &new_len);
3932 else if(!tng_data->compress_algo_pos)
3934 if(n_frames > 10)
3936 algo_find_n_frames = 5;
3938 else
3940 algo_find_n_frames = n_frames;
3943 nalgo = tng_compress_nalgo();
3944 tng_data->compress_algo_pos=malloc(nalgo *
3945 sizeof *tng_data->compress_algo_pos);
3946 if(type == TNG_FLOAT_DATA)
3948 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
3949 (int)algo_find_n_frames,
3950 f_precision,
3951 0, tng_data->
3952 compress_algo_pos,
3953 &new_len);
3955 if(algo_find_n_frames < n_frames)
3957 dest = tng_compress_pos_float(start_pos, (int)n_particles,
3958 (int)n_frames,
3959 f_precision,
3960 0, tng_data->compress_algo_pos,
3961 &new_len);
3964 else
3966 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
3967 (int)algo_find_n_frames,
3968 d_precision,
3969 0, tng_data->
3970 compress_algo_pos,
3971 &new_len);
3973 if(algo_find_n_frames < n_frames)
3975 dest = tng_compress_pos(start_pos, (int)n_particles,
3976 (int)n_frames,
3977 d_precision, 0,
3978 tng_data->compress_algo_pos,
3979 &new_len);
3983 else
3985 if(type == TNG_FLOAT_DATA)
3987 dest = tng_compress_pos_float(start_pos, (int)n_particles,
3988 (int)n_frames,
3989 f_precision, 0,
3990 tng_data->compress_algo_pos, &new_len);
3992 else
3994 dest = tng_compress_pos(start_pos, (int)n_particles,
3995 (int)n_frames,
3996 d_precision, 0,
3997 tng_data->compress_algo_pos,
3998 &new_len);
4002 else if(block->id == TNG_TRAJ_VELOCITIES)
4004 /* If there is only one frame in this frame set and there might be more
4005 * do not store the algorithm as the compression algorithm, but find
4006 * the best one without storing it */
4007 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4009 nalgo = tng_compress_nalgo();
4010 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4011 if(type == TNG_FLOAT_DATA)
4013 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4014 (int)n_frames,
4015 f_precision,
4016 0, alt_algo,
4017 &new_len);
4020 else
4022 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4023 (int)n_frames,
4024 d_precision,
4025 0, alt_algo,
4026 &new_len);
4029 else if(!tng_data->compress_algo_vel)
4031 if(n_frames > 10)
4033 algo_find_n_frames = 5;
4035 else
4037 algo_find_n_frames = n_frames;
4040 nalgo = tng_compress_nalgo();
4041 tng_data->compress_algo_vel=malloc(nalgo *
4042 sizeof *tng_data->compress_algo_vel);
4044 if(type == TNG_FLOAT_DATA)
4046 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4047 (int)algo_find_n_frames,
4048 f_precision,
4049 0, tng_data->
4050 compress_algo_vel,
4051 &new_len);
4052 if(algo_find_n_frames < n_frames)
4054 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4055 (int)n_frames,
4056 f_precision,
4057 0, tng_data->compress_algo_vel,
4058 &new_len);
4061 else
4063 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4064 (int)algo_find_n_frames,
4065 d_precision,
4066 0, tng_data->
4067 compress_algo_vel,
4068 &new_len);
4069 if(algo_find_n_frames < n_frames)
4071 dest = tng_compress_vel(start_pos, (int)n_particles,
4072 (int)n_frames,
4073 d_precision,
4074 0, tng_data->compress_algo_vel,
4075 &new_len);
4079 else
4081 if(type == TNG_FLOAT_DATA)
4083 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4084 (int)n_frames,
4085 f_precision,
4086 0, tng_data->
4087 compress_algo_vel,
4088 &new_len);
4090 else
4092 dest = tng_compress_vel(start_pos, (int)n_particles,
4093 (int)n_frames,
4094 d_precision,
4095 0, tng_data->
4096 compress_algo_vel,
4097 &new_len);
4101 else
4103 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4104 return(TNG_FAILURE);
4107 offset = (unsigned long)((char *)start_pos - block->block_contents);
4109 if(alt_algo)
4111 free(alt_algo);
4114 block->block_contents_size = new_len + offset;
4116 temp = realloc(block->block_contents, block->block_contents_size);
4117 if(!temp)
4119 free(block->block_contents);
4120 block->block_contents = 0;
4121 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4122 block->block_contents_size, __FILE__, __LINE__);
4123 return(TNG_CRITICAL);
4125 block->block_contents = temp;
4126 if(dest)
4128 memcpy(temp + offset, dest, new_len);
4129 free(dest);
4131 else
4133 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
4134 return(TNG_FAILURE);
4137 return(TNG_SUCCESS);
4140 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
4141 tng_gen_block_t block,
4142 const char type,
4143 void *start_pos,
4144 const unsigned long uncompressed_len)
4146 char *temp;
4147 double *d_dest = 0;
4148 float *f_dest = 0;
4149 unsigned long offset;
4150 int result;
4151 (void)tng_data;
4153 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
4155 if(block->id != TNG_TRAJ_POSITIONS &&
4156 block->id != TNG_TRAJ_VELOCITIES)
4158 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
4159 "TNG method.\n");
4160 return(TNG_FAILURE);
4162 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4164 fprintf(stderr, "TNG library: Data type not supported.\n");
4165 return(TNG_FAILURE);
4168 if(type == TNG_FLOAT_DATA)
4170 f_dest = malloc(uncompressed_len);
4171 if(!f_dest)
4173 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4174 uncompressed_len, __FILE__, __LINE__);
4175 return(TNG_CRITICAL);
4177 result = tng_compress_uncompress_float(start_pos, f_dest);
4179 else
4181 d_dest = malloc(uncompressed_len);
4182 if(!d_dest)
4184 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4185 uncompressed_len, __FILE__, __LINE__);
4186 return(TNG_CRITICAL);
4188 result = tng_compress_uncompress(start_pos, d_dest);
4191 if(result == 1)
4193 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
4194 return(TNG_FAILURE);
4197 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
4199 block->block_contents_size = (int64_t)(uncompressed_len + offset);
4201 temp = realloc(block->block_contents, uncompressed_len + offset);
4202 if(!temp)
4204 free(block->block_contents);
4205 block->block_contents = 0;
4206 if(d_dest)
4208 free(d_dest);
4210 if(f_dest)
4212 free(f_dest);
4214 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4215 block->block_contents_size, __FILE__, __LINE__);
4216 return(TNG_CRITICAL);
4219 if(type == TNG_FLOAT_DATA)
4221 memcpy(temp + offset, f_dest, uncompressed_len);
4223 else
4225 memcpy(temp + offset, d_dest, uncompressed_len);
4228 block->block_contents = temp;
4230 if(d_dest)
4232 free(d_dest);
4234 if(f_dest)
4236 free(f_dest);
4238 return(TNG_SUCCESS);
4241 #ifdef USE_ZLIB
4242 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
4243 tng_gen_block_t block,
4244 void *start_pos, const int len)
4246 Bytef *dest;
4247 char *temp;
4248 unsigned long max_len, stat, offset;
4249 (void)tng_data;
4251 max_len = compressBound(len);
4252 dest = malloc(max_len);
4253 if(!dest)
4255 fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
4256 max_len, __FILE__, __LINE__);
4257 return(TNG_CRITICAL);
4260 stat = compress(dest, &max_len, start_pos, len);
4261 if(stat != (unsigned long)Z_OK)
4263 free(dest);
4264 if(stat == (unsigned long)Z_MEM_ERROR)
4266 fprintf(stderr, "TNG library: Not enough memory. ");
4268 else if(stat == (unsigned long)Z_BUF_ERROR)
4270 fprintf(stderr, "TNG library: Destination buffer too small. ");
4272 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
4273 return(TNG_FAILURE);
4276 offset = (char *)start_pos - block->block_contents;
4278 block->block_contents_size = max_len + offset;
4280 temp = realloc(block->block_contents, block->block_contents_size);
4281 if(!temp)
4283 free(block->block_contents);
4284 free(dest);
4285 block->block_contents = 0;
4286 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4287 block->block_contents_size, __FILE__, __LINE__);
4288 return(TNG_CRITICAL);
4291 block->block_contents = temp;
4293 memcpy(temp + offset, dest, max_len);
4295 free(dest);
4297 return(TNG_SUCCESS);
4300 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
4301 tng_gen_block_t block,
4302 void *start_pos,
4303 unsigned long uncompressed_len)
4305 Bytef *dest;
4306 char *temp;
4307 unsigned long stat;
4308 int offset;
4309 (void)tng_data;
4311 offset = (char *)start_pos - (char *)block->block_contents;
4313 dest = malloc(uncompressed_len);
4314 if(!dest)
4316 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
4317 uncompressed_len, __FILE__, __LINE__);
4318 return(TNG_CRITICAL);
4321 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
4322 block->block_contents_size - offset);
4324 if(stat != Z_OK)
4326 free(dest);
4327 if(stat == (unsigned long)Z_MEM_ERROR)
4329 fprintf(stderr, "TNG library: Not enough memory. ");
4331 else if(stat == (unsigned long)Z_BUF_ERROR)
4333 fprintf(stderr, "TNG library: Destination buffer too small. ");
4335 else if(stat == (unsigned long)Z_DATA_ERROR)
4337 fprintf(stderr, "TNG library: Data corrupt. ");
4339 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
4340 __LINE__);
4341 return(TNG_FAILURE);
4345 block->block_contents_size = uncompressed_len + offset;
4347 temp = realloc(block->block_contents, uncompressed_len + offset);
4348 if(!temp)
4350 free(block->block_contents);
4351 block->block_contents = 0;
4352 free(dest);
4353 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4354 block->block_contents_size, __FILE__, __LINE__);
4355 return(TNG_CRITICAL);
4358 memcpy(temp + offset, dest, uncompressed_len);
4360 block->block_contents = temp;
4362 free(dest);
4363 return(TNG_SUCCESS);
4365 #endif
4367 /** Allocate memory for storing particle data.
4368 * The allocated block will be refered to by data->values.
4369 * @param tng_data is a trajectory data container.
4370 * @param data is the data struct, which will contain the allocated memory in
4371 * data->values.
4372 * @param n_frames is the number of frames of data to store.
4373 * @param n_particles is the number of particles with data.
4374 * @param n_values_per_frame is the number of data values per particle and
4375 * frame.
4376 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4377 * error has occured.
4379 static tng_function_status tng_allocate_particle_data_mem
4380 (tng_trajectory_t tng_data,
4381 tng_particle_data_t data,
4382 int64_t n_frames,
4383 int64_t stride_length,
4384 const int64_t n_particles,
4385 const int64_t n_values_per_frame)
4387 void ***values;
4388 int64_t i, j, k, size, frame_alloc;
4389 (void)tng_data;
4391 if(n_particles == 0 || n_values_per_frame == 0)
4393 return(TNG_FAILURE);
4396 if(data->strings && data->datatype == TNG_CHAR_DATA)
4398 for(i = data->n_frames; i--;)
4400 for(j = n_particles; j--;)
4402 for(k = data->n_values_per_frame; k--;)
4404 if(data->strings[i][j][k])
4406 free(data->strings[i][j][k]);
4409 free(data->strings[i][j]);
4411 free(data->strings[i]);
4413 free(data->strings);
4415 data->n_frames = n_frames;
4416 n_frames = tng_max_i64(1, n_frames);
4417 data->stride_length = tng_max_i64(1, stride_length);
4418 data->n_values_per_frame = n_values_per_frame;
4419 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
4421 if(data->datatype == TNG_CHAR_DATA)
4423 data->strings = malloc(sizeof(char ***) * frame_alloc);
4424 for(i = frame_alloc; i-- ;)
4426 data->strings[i] = malloc(sizeof(char **) *
4427 n_particles);
4428 if(!data->strings[i])
4430 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4431 sizeof(union data_values *) * n_particles,
4432 __FILE__, __LINE__);
4433 return(TNG_CRITICAL);
4435 for(j = n_particles; j--;)
4437 data->strings[i][j] = malloc(sizeof(char *) *
4438 n_values_per_frame);
4439 if(!data->strings[i][j])
4441 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4442 sizeof(union data_values) * n_values_per_frame,
4443 __FILE__, __LINE__);
4444 return(TNG_CRITICAL);
4446 for(k = n_values_per_frame; k--;)
4448 data->strings[i][j][k] = 0;
4453 else
4455 switch(data->datatype)
4457 case TNG_INT_DATA:
4458 size = sizeof(int64_t);
4459 break;
4460 case TNG_FLOAT_DATA:
4461 size = sizeof(float);
4462 break;
4463 case TNG_DOUBLE_DATA:
4464 default:
4465 size = sizeof(double);
4468 values = realloc(data->values,
4469 size * frame_alloc *
4470 n_particles * n_values_per_frame);
4471 if(!values)
4473 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4474 size * frame_alloc *
4475 n_particles * n_values_per_frame,
4476 __FILE__, __LINE__);
4477 free(data->values);
4478 data->values = 0;
4479 return(TNG_CRITICAL);
4481 data->values = values;
4483 return(TNG_SUCCESS);
4486 static tng_function_status tng_particle_data_find
4487 (tng_trajectory_t tng_data,
4488 const int64_t id,
4489 tng_particle_data_t *data)
4491 int64_t block_index, i;
4492 tng_trajectory_frame_set_t frame_set = &tng_data->
4493 current_trajectory_frame_set;
4494 char block_type_flag;
4496 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4497 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4499 block_type_flag = TNG_TRAJECTORY_BLOCK;
4501 else
4503 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4506 block_index = -1;
4507 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4509 for(i = frame_set->n_particle_data_blocks; i-- ;)
4511 *data = &frame_set->tr_particle_data[i];
4512 if((*data)->block_id == id)
4514 block_index = i;
4515 break;
4519 else
4521 for(i = tng_data->n_particle_data_blocks; i-- ;)
4523 *data = &tng_data->non_tr_particle_data[i];
4524 if((*data)->block_id == id)
4526 block_index = i;
4527 break;
4531 if(block_index == -1)
4533 return(TNG_FAILURE);
4535 return(TNG_SUCCESS);
4538 static tng_function_status tng_data_find
4539 (tng_trajectory_t tng_data,
4540 const int64_t id,
4541 tng_non_particle_data_t *data)
4543 int64_t block_index, i;
4544 tng_trajectory_frame_set_t frame_set = &tng_data->
4545 current_trajectory_frame_set;
4546 char block_type_flag;
4548 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4549 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4551 block_type_flag = TNG_TRAJECTORY_BLOCK;
4553 else
4555 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4558 block_index = -1;
4559 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4561 for(i = frame_set->n_data_blocks; i-- ;)
4563 *data = &frame_set->tr_data[i];
4564 if((*data)->block_id == id)
4566 block_index = i;
4567 break;
4570 if(block_index == -1)
4572 for(i = tng_data->n_data_blocks; i-- ;)
4574 *data = &tng_data->non_tr_data[i];
4575 if((*data)->block_id == id)
4577 block_index = i;
4578 break;
4583 else
4585 for(i = tng_data->n_data_blocks; i-- ;)
4587 *data = &tng_data->non_tr_data[i];
4588 if((*data)->block_id == id)
4590 block_index = i;
4591 break;
4595 if(block_index == -1)
4597 return(TNG_FAILURE);
4599 return(TNG_SUCCESS);
4602 /** Read the values of a particle data block
4603 * @param tng_data is a trajectory data container.
4604 * @param block is the block to store the data (should already contain
4605 * the block headers and the block contents).
4606 * @param offset is the reading offset to point at the place where the actual
4607 * values are stored, starting from the beginning of the block_contents. The
4608 * offset is changed during the reading.
4609 * @param datatype is the type of data of the data block (char, int, float or
4610 * double).
4611 * @param num_first_particle is the number of the first particle in the data
4612 * block. This should be the same as in the corresponding particle mapping
4613 * block.
4614 * @param n_particles is the number of particles in the data block. This should
4615 * be the same as in the corresponding particle mapping block.
4616 * @param first_frame_with_data is the frame number of the first frame with data
4617 * in this data block.
4618 * @param stride_length is the number of frames between each data entry.
4619 * @param n_frames is the number of frames in this data block.
4620 * @param n_values is the number of values per particle and frame stored in this
4621 * data block.
4622 * @param codec_id is the ID of the codec to compress the data.
4623 * @param multiplier is the multiplication factor applied to each data value
4624 * before compression. This factor is applied since some compression algorithms
4625 * work only on integers.
4626 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4627 * error has occured.
4629 static tng_function_status tng_particle_data_read
4630 (tng_trajectory_t tng_data,
4631 tng_gen_block_t block,
4632 int *offset,
4633 const char datatype,
4634 const int64_t num_first_particle,
4635 const int64_t n_particles,
4636 const int64_t first_frame_with_data,
4637 const int64_t stride_length,
4638 int64_t n_frames,
4639 const int64_t n_values,
4640 const int64_t codec_id,
4641 const double multiplier)
4643 int64_t i, j, k, tot_n_particles, n_frames_div;
4644 int size, len;
4645 unsigned long data_size;
4646 char ***first_dim_values, **second_dim_values;
4647 tng_particle_data_t data;
4648 tng_trajectory_frame_set_t frame_set =
4649 &tng_data->current_trajectory_frame_set;
4650 char block_type_flag;
4652 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
4654 switch(datatype)
4656 case TNG_CHAR_DATA:
4657 size = 1;
4658 break;
4659 case TNG_INT_DATA:
4660 size = sizeof(int64_t);
4661 break;
4662 case TNG_FLOAT_DATA:
4663 size = sizeof(float);
4664 break;
4665 case TNG_DOUBLE_DATA:
4666 default:
4667 size = sizeof(double);
4670 /* If the block does not exist, create it */
4671 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
4673 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
4675 block_type_flag = TNG_TRAJECTORY_BLOCK;
4677 else
4679 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4682 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
4683 TNG_SUCCESS)
4685 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
4686 __FILE__, __LINE__);
4687 return(TNG_CRITICAL);
4689 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4691 data = &frame_set->tr_particle_data[frame_set->
4692 n_particle_data_blocks - 1];
4694 else
4696 data = &tng_data->non_tr_particle_data[tng_data->
4697 n_particle_data_blocks - 1];
4699 data->block_id = block->id;
4701 data->block_name = malloc(strlen(block->name) + 1);
4702 if(!data->block_name)
4704 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4705 (int)strlen(block->name)+1, __FILE__, __LINE__);
4706 return(TNG_CRITICAL);
4708 strcpy(data->block_name, block->name);
4710 data->datatype = datatype;
4712 data->values = 0;
4713 /* FIXME: Memory leak from strings. */
4714 data->strings = 0;
4715 data->n_frames = 0;
4716 data->codec_id = codec_id;
4717 data->compression_multiplier = multiplier;
4718 data->last_retrieved_frame = -1;
4721 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
4722 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
4723 tng_data->var_num_atoms_flag)
4725 tot_n_particles = frame_set->n_particles;
4727 else
4729 tot_n_particles = tng_data->n_particles;
4732 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
4734 if(codec_id != TNG_UNCOMPRESSED)
4736 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
4737 switch(codec_id)
4739 case TNG_XTC_COMPRESSION:
4740 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
4741 break;
4742 case TNG_TNG_COMPRESSION:
4743 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
4744 if(tng_uncompress(tng_data, block, datatype,
4745 block->block_contents + *offset,
4746 data_size) != TNG_SUCCESS)
4748 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
4749 __FILE__, __LINE__);
4750 return(TNG_CRITICAL);
4752 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
4753 break;
4754 #ifdef USE_ZLIB
4755 case TNG_GZIP_COMPRESSION:
4756 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
4757 if(tng_gzip_uncompress(tng_data, block,
4758 block->block_contents + *offset,
4759 data_size) != TNG_SUCCESS)
4761 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
4762 __LINE__);
4763 return(TNG_CRITICAL);
4765 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
4766 break;
4767 #endif
4770 /* Allocate memory */
4771 if(!data->values || data->n_frames != n_frames ||
4772 data->n_values_per_frame != n_values)
4774 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
4775 stride_length,
4776 tot_n_particles, n_values) !=
4777 TNG_SUCCESS)
4779 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
4780 __FILE__, __LINE__);
4781 return(TNG_CRITICAL);
4785 data->first_frame_with_data = first_frame_with_data;
4787 if(datatype == TNG_CHAR_DATA)
4789 for(i = 0; i < n_frames_div; i++)
4791 first_dim_values = data->strings[i];
4792 for(j = num_first_particle; j < num_first_particle + n_particles;
4793 j++)
4795 second_dim_values = first_dim_values[j];
4796 for(k = 0; k < n_values; k++)
4798 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
4799 TNG_MAX_STR_LEN);
4800 if(second_dim_values[k])
4802 free(second_dim_values[k]);
4804 second_dim_values[k] = malloc(len);
4805 if(!second_dim_values[k])
4807 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4808 len, __FILE__, __LINE__);
4809 return(TNG_CRITICAL);
4811 strncpy(second_dim_values[k],
4812 block->block_contents+*offset, len);
4813 *offset += len;
4818 else
4820 memcpy((char *)data->values + n_frames_div * size * n_values *
4821 num_first_particle,
4822 block->block_contents + *offset,
4823 block->block_contents_size - *offset);
4824 switch(datatype)
4826 case TNG_FLOAT_DATA:
4827 if(tng_data->input_endianness_swap_func_32)
4829 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
4831 if(tng_data->input_endianness_swap_func_32(tng_data,
4832 (int32_t *)((char *)data->values + i))
4833 != TNG_SUCCESS)
4835 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4836 __FILE__, __LINE__);
4840 break;
4841 case TNG_INT_DATA:
4842 case TNG_DOUBLE_DATA:
4843 if(tng_data->input_endianness_swap_func_64)
4845 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
4847 if(tng_data->input_endianness_swap_func_64(tng_data,
4848 (int64_t *)((char *)data->values + i))
4849 != TNG_SUCCESS)
4851 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4852 __FILE__, __LINE__);
4856 break;
4857 case TNG_CHAR_DATA:
4858 break;
4861 return(TNG_SUCCESS);
4864 /** Write a particle data block
4865 * @param tng_data is a trajectory data container.
4866 * @param block is the block to store the data (should already contain
4867 * the block headers and the block contents).
4868 * @param block_index is the index number of the data block in the frame set.
4869 * @param mapping is the particle mapping that is relevant for the data block.
4870 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4871 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4872 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4873 * error has occured.
4875 static tng_function_status tng_particle_data_block_write
4876 (tng_trajectory_t tng_data,
4877 tng_gen_block_t block,
4878 const int64_t block_index,
4879 const tng_particle_mapping_t mapping,
4880 const char hash_mode)
4882 int64_t n_particles, num_first_particle, n_frames, stride_length;
4883 int64_t frame_step, data_start_pos;
4884 int64_t i, j, k;
4885 int size;
4886 size_t len, offset = 0;
4887 char dependency, temp, *temp_name;
4888 double multiplier;
4889 char ***first_dim_values, **second_dim_values;
4890 tng_trajectory_frame_set_t frame_set;
4891 tng_function_status stat;
4893 tng_particle_data_t data;
4894 char block_type_flag;
4896 frame_set = &tng_data->current_trajectory_frame_set;
4898 /* If we have already started writing frame sets it is too late to write
4899 * non-trajectory data blocks */
4900 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
4902 block_type_flag = TNG_TRAJECTORY_BLOCK;
4904 else
4906 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4909 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4911 return(TNG_CRITICAL);
4914 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4916 data = &frame_set->tr_particle_data[block_index];
4918 /* If this data block has not had any data added in this frame set
4919 * do not write it. */
4920 if(data->first_frame_with_data < frame_set->first_frame)
4922 return(TNG_SUCCESS);
4925 stride_length = tng_max_i64(1, data->stride_length);
4927 else
4929 data = &tng_data->non_tr_particle_data[block_index];
4930 stride_length = 1;
4933 switch(data->datatype)
4935 case TNG_CHAR_DATA:
4936 size = 1;
4937 break;
4938 case TNG_INT_DATA:
4939 size = sizeof(int64_t);
4940 break;
4941 case TNG_FLOAT_DATA:
4942 size = sizeof(float);
4943 break;
4944 case TNG_DOUBLE_DATA:
4945 default:
4946 size = sizeof(double);
4949 len = strlen(data->block_name) + 1;
4951 if(!block->name || strlen(block->name) < len)
4953 temp_name = realloc(block->name, len);
4954 if(!temp_name)
4956 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
4957 __FILE__, __LINE__);
4958 free(block->name);
4959 block->name = 0;
4960 return(TNG_CRITICAL);
4962 block->name = temp_name;
4964 strncpy(block->name, data->block_name, len);
4965 block->id = data->block_id;
4967 /* If writing frame independent data data->n_frames is 0, but n_frames
4968 is used for the loop writing the data (and reserving memory) and needs
4969 to be at least 1 */
4970 n_frames = tng_max_i64(1, data->n_frames);
4972 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4974 /* If the frame set is finished before writing the full number of frames
4975 make sure the data block is not longer than the frame set. */
4976 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
4978 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
4981 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
4982 n_frames / stride_length;
4984 /* TNG compression will use compression precision to get integers from
4985 * floating point data. The compression multiplier stores that information
4986 * to be able to return the precision of the compressed data. */
4987 if(data->codec_id == TNG_TNG_COMPRESSION)
4989 data->compression_multiplier = tng_data->compression_precision;
4991 /* Uncompressed data blocks do not use compression multipliers at all.
4992 * GZip compression does not need it either. */
4993 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
4995 data->compression_multiplier = 1.0;
4998 if(mapping && mapping->n_particles != 0)
5000 n_particles = mapping->n_particles;
5001 num_first_particle = mapping->num_first_particle;
5003 else
5005 num_first_particle = 0;
5006 if(tng_data->var_num_atoms_flag)
5008 n_particles = frame_set->n_particles;
5010 else
5012 n_particles = tng_data->n_particles;
5016 block->block_contents_size = sizeof(char) * 2 +
5017 sizeof(data->n_values_per_frame) +
5018 sizeof(data->codec_id) +
5019 sizeof(num_first_particle) +
5020 sizeof(n_particles);
5022 if(stride_length > 1)
5024 block->block_contents_size += sizeof(data->first_frame_with_data) +
5025 sizeof(data->stride_length);
5028 if(data->codec_id != TNG_UNCOMPRESSED)
5030 block->block_contents_size += sizeof(data->compression_multiplier);
5033 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
5035 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
5037 else
5039 dependency = TNG_PARTICLE_DEPENDENT;
5041 if(dependency & TNG_FRAME_DEPENDENT)
5043 block->block_contents_size += sizeof(char);
5046 data_start_pos = block->block_contents_size;
5048 if(data->datatype == TNG_CHAR_DATA)
5050 for(i = n_frames; i--;)
5052 first_dim_values = data->strings[i];
5053 for(j = num_first_particle; j < num_first_particle + n_particles;
5054 j++)
5056 second_dim_values = first_dim_values[j];
5057 for(k = data->n_values_per_frame; k--;)
5059 block->block_contents_size +=
5060 strlen(second_dim_values[k]) + 1;
5065 else
5067 block->block_contents_size += size * frame_step *
5068 n_particles * data->n_values_per_frame;
5071 if(block->block_contents)
5073 free(block->block_contents);
5075 block->block_contents = malloc(block->block_contents_size);
5076 if(!block->block_contents)
5078 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5079 block->block_contents_size, __FILE__, __LINE__);
5080 return(TNG_CRITICAL);
5084 memcpy(block->block_contents, &data->datatype, sizeof(char));
5085 offset += sizeof(char);
5087 memcpy(block->block_contents+offset, &dependency, sizeof(char));
5088 offset += sizeof(char);
5090 if(dependency & TNG_FRAME_DEPENDENT)
5092 if(stride_length > 1)
5094 temp = 1;
5096 else
5098 temp = 0;
5100 memcpy(block->block_contents+offset, &temp, sizeof(char));
5101 offset += sizeof(char);
5104 memcpy(block->block_contents+offset, &data->n_values_per_frame,
5105 sizeof(data->n_values_per_frame));
5106 if(tng_data->output_endianness_swap_func_64)
5108 if(tng_data->output_endianness_swap_func_64(tng_data,
5109 (int64_t *)block->header_contents+offset)
5110 != TNG_SUCCESS)
5112 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5113 __FILE__, __LINE__);
5116 offset += sizeof(data->n_values_per_frame);
5118 memcpy(block->block_contents+offset, &data->codec_id,
5119 sizeof(data->codec_id));
5120 if(tng_data->output_endianness_swap_func_64)
5122 if(tng_data->output_endianness_swap_func_64(tng_data,
5123 (int64_t *)block->header_contents+offset)
5124 != TNG_SUCCESS)
5126 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5127 __FILE__, __LINE__);
5130 offset += sizeof(data->codec_id);
5132 if(data->codec_id != TNG_UNCOMPRESSED)
5134 memcpy(block->block_contents+offset, &data->compression_multiplier,
5135 sizeof(data->compression_multiplier));
5136 if(tng_data->output_endianness_swap_func_64)
5138 if(tng_data->output_endianness_swap_func_64(tng_data,
5139 (int64_t *)block->header_contents+offset)
5140 != TNG_SUCCESS)
5142 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5143 __FILE__, __LINE__);
5146 offset += sizeof(data->compression_multiplier);
5149 if(data->n_frames > 0 && stride_length > 1)
5151 /* FIXME: first_frame_with_data is not reliably set */
5152 if(data->first_frame_with_data == 0)
5154 data->first_frame_with_data = frame_set->first_frame;
5156 memcpy(block->block_contents+offset, &data->first_frame_with_data,
5157 sizeof(data->first_frame_with_data));
5158 if(tng_data->output_endianness_swap_func_64)
5160 if(tng_data->output_endianness_swap_func_64(tng_data,
5161 (int64_t *)block->header_contents+offset)
5162 != TNG_SUCCESS)
5164 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5165 __FILE__, __LINE__);
5168 offset += sizeof(data->first_frame_with_data);
5170 memcpy(block->block_contents+offset, &stride_length,
5171 sizeof(stride_length));
5172 if(tng_data->output_endianness_swap_func_64)
5174 if(tng_data->output_endianness_swap_func_64(tng_data,
5175 (int64_t *)block->header_contents+offset)
5176 != TNG_SUCCESS)
5178 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5179 __FILE__, __LINE__);
5182 offset += sizeof(stride_length);
5186 memcpy(block->block_contents+offset, &num_first_particle,
5187 sizeof(num_first_particle));
5188 if(tng_data->output_endianness_swap_func_64)
5190 if(tng_data->output_endianness_swap_func_64(tng_data,
5191 (int64_t *)block->header_contents+offset)
5192 != TNG_SUCCESS)
5194 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5195 __FILE__, __LINE__);
5198 offset += sizeof(num_first_particle);
5200 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
5201 if(tng_data->output_endianness_swap_func_64)
5203 if(tng_data->output_endianness_swap_func_64(tng_data,
5204 (int64_t *)block->header_contents+offset)
5205 != TNG_SUCCESS)
5207 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5208 __FILE__, __LINE__);
5211 offset += sizeof(n_particles);
5213 if(data->datatype == TNG_CHAR_DATA)
5215 if(data->strings)
5217 for(i = 0; i < frame_step; i++)
5219 first_dim_values = data->strings[i];
5220 for(j = num_first_particle; j < num_first_particle + n_particles;
5221 j++)
5223 second_dim_values = first_dim_values[j];
5224 for(k = 0; k < data->n_values_per_frame; k++)
5226 len = (unsigned int)strlen(second_dim_values[k]) + 1;
5227 strncpy(block->block_contents+offset,
5228 second_dim_values[k], len);
5229 offset += len;
5235 else if(data->values)
5237 memcpy(block->block_contents + offset, data->values,
5238 block->block_contents_size - offset);
5240 switch(data->datatype)
5242 case TNG_FLOAT_DATA:
5243 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
5244 data->codec_id == TNG_TNG_COMPRESSION)
5246 if(tng_data->input_endianness_swap_func_32)
5248 for(i = offset; i < block->block_contents_size; i+=size)
5250 if(tng_data->input_endianness_swap_func_32(tng_data,
5251 (int32_t *)(block->block_contents + i))
5252 != TNG_SUCCESS)
5254 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5255 __FILE__, __LINE__);
5260 else
5262 multiplier = data->compression_multiplier;
5263 if(fabs(multiplier - 1.0) > 0.00001 ||
5264 tng_data->input_endianness_swap_func_32)
5266 for(i = offset; i < block->block_contents_size; i+=size)
5268 *(float *)(block->block_contents + i) *= (float)multiplier;
5269 if(tng_data->input_endianness_swap_func_32 &&
5270 tng_data->input_endianness_swap_func_32(tng_data,
5271 (int32_t *)(block->block_contents + i))
5272 != TNG_SUCCESS)
5274 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5275 __FILE__, __LINE__);
5280 break;
5281 case TNG_INT_DATA:
5282 if(tng_data->input_endianness_swap_func_64)
5284 for(i = offset; i < block->block_contents_size; i+=size)
5286 if(tng_data->input_endianness_swap_func_64(tng_data,
5287 (int64_t *)(block->block_contents + i))
5288 != TNG_SUCCESS)
5290 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5291 __FILE__, __LINE__);
5295 break;
5296 case TNG_DOUBLE_DATA:
5297 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
5298 data->codec_id == TNG_TNG_COMPRESSION)
5300 if(tng_data->input_endianness_swap_func_64)
5302 for(i = offset; i < block->block_contents_size; i+=size)
5304 if(tng_data->input_endianness_swap_func_64(tng_data,
5305 (int64_t *)(block->block_contents + i))
5306 != TNG_SUCCESS)
5308 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5309 __FILE__, __LINE__);
5314 else
5316 multiplier = data->compression_multiplier;
5317 if(fabs(multiplier - 1.0) > 0.00001 ||
5318 tng_data->input_endianness_swap_func_64)
5320 for(i = offset; i < block->block_contents_size; i+=size)
5322 *(double *)(block->block_contents + i) *= multiplier;
5323 if(tng_data->input_endianness_swap_func_64 &&
5324 tng_data->input_endianness_swap_func_64(tng_data,
5325 (int64_t *)(block->block_contents + i))
5326 != TNG_SUCCESS)
5328 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5329 __FILE__, __LINE__);
5334 break;
5335 case TNG_CHAR_DATA:
5336 break;
5339 else
5341 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
5344 frame_set->n_written_frames += frame_set->n_unwritten_frames;
5345 frame_set->n_unwritten_frames = 0;
5347 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
5349 switch(data->codec_id)
5351 case TNG_XTC_COMPRESSION:
5352 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5353 data->codec_id = TNG_UNCOMPRESSED;
5354 break;
5355 case TNG_TNG_COMPRESSION:
5356 stat = tng_compress(tng_data, block, frame_step,
5357 n_particles, data->datatype,
5358 block->block_contents + data_start_pos);
5359 if(stat != TNG_SUCCESS)
5361 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
5362 __FILE__, __LINE__);
5363 if(stat == TNG_CRITICAL)
5365 return(TNG_CRITICAL);
5367 /* Set the data again, but with no compression (to write only
5368 * the relevant data) */
5369 data->codec_id = TNG_UNCOMPRESSED;
5370 stat = tng_particle_data_block_write(tng_data, block,
5371 block_index, mapping,
5372 hash_mode);
5373 return(stat);
5375 break;
5376 #ifdef USE_ZLIB
5377 case TNG_GZIP_COMPRESSION:
5378 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
5379 stat = tng_gzip_compress(tng_data, block,
5380 block->block_contents + data_start_pos,
5381 block->block_contents_size - data_start_pos);
5382 if(stat != TNG_SUCCESS)
5384 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
5385 __LINE__);
5386 if(stat == TNG_CRITICAL)
5388 return(TNG_CRITICAL);
5390 /* Set the data again, but with no compression (to write only
5391 * the relevant data) */
5392 data->codec_id = TNG_UNCOMPRESSED;
5393 stat = tng_particle_data_block_write(tng_data, block,
5394 block_index, mapping,
5395 hash_mode);
5396 return(stat);
5398 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
5399 break;
5400 #endif
5404 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
5406 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
5407 tng_data->output_file_path, __FILE__, __LINE__);
5408 return(TNG_CRITICAL);
5411 if(fwrite(block->block_contents, block->block_contents_size, 1,
5412 tng_data->output_file) != 1)
5414 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
5415 __LINE__);
5416 return(TNG_CRITICAL);
5419 return(TNG_SUCCESS);
5422 /* TEST: */
5423 /** Create a non-particle data block
5424 * @param tng_data is a trajectory data container.
5425 * @param block_type_flag specifies if this is a trajectory block or a
5426 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
5427 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5428 * error has occured.
5430 static tng_function_status tng_data_block_create
5431 (tng_trajectory_t tng_data,
5432 const char block_type_flag)
5434 tng_trajectory_frame_set_t frame_set =
5435 &tng_data->current_trajectory_frame_set;
5437 tng_non_particle_data_t data;
5439 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5441 frame_set->n_data_blocks++;
5442 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
5443 frame_set->n_data_blocks);
5444 if(!data)
5446 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5447 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
5448 __FILE__, __LINE__);
5449 free(frame_set->tr_data);
5450 frame_set->tr_data = 0;
5451 return(TNG_CRITICAL);
5453 frame_set->tr_data = data;
5455 else
5457 tng_data->n_data_blocks++;
5458 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
5459 tng_data->n_data_blocks);
5460 if(!data)
5462 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5463 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
5464 __FILE__, __LINE__);
5465 free(tng_data->non_tr_data);
5466 tng_data->non_tr_data = 0;
5467 return(TNG_CRITICAL);
5469 tng_data->non_tr_data = data;
5472 return(TNG_SUCCESS);
5475 /* TEST: */
5476 /** Allocate memory for storing non-particle data.
5477 * The allocated block will be refered to by data->values.
5478 * @param tng_data is a trajectory data container.
5479 * @param data is the data struct, which will contain the allocated memory in
5480 * data->values.
5481 * @param n_frames is the number of frames of data to store.
5482 * @param n_values_per_frame is the number of data values per frame.
5483 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5484 * error has occured.
5486 static tng_function_status tng_allocate_data_mem
5487 (tng_trajectory_t tng_data,
5488 tng_non_particle_data_t data,
5489 int64_t n_frames,
5490 int64_t stride_length,
5491 const int64_t n_values_per_frame)
5493 void **values;
5494 int64_t i, j, size, frame_alloc;
5495 (void)tng_data;
5497 if(n_values_per_frame == 0)
5499 return(TNG_FAILURE);
5502 if(data->strings && data->datatype == TNG_CHAR_DATA)
5504 for(i = data->n_frames; i--;)
5506 for(j = data->n_values_per_frame; j--;)
5508 if(data->strings[i][j])
5510 free(data->strings[i][j]);
5511 data->strings[i][j] = 0;
5514 free(data->strings[i]);
5515 data->strings[i] = 0;
5517 free(data->strings);
5519 data->n_frames = n_frames;
5520 data->stride_length = tng_max_i64(1, stride_length);
5521 n_frames = tng_max_i64(1, n_frames);
5522 data->n_values_per_frame = n_values_per_frame;
5523 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5525 if(data->datatype == TNG_CHAR_DATA)
5527 data->strings = malloc(sizeof(char **) * frame_alloc);
5528 for(i = frame_alloc; i-- ;)
5530 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
5531 if(!data->strings[i])
5533 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5534 n_values_per_frame,
5535 __FILE__, __LINE__);
5536 return(TNG_CRITICAL);
5538 for(j = n_values_per_frame; j--;)
5540 data->strings[i][j] = 0;
5544 else
5546 switch(data->datatype)
5548 case TNG_INT_DATA:
5549 size = sizeof(int64_t);
5550 break;
5551 case TNG_FLOAT_DATA:
5552 size = sizeof(float);
5553 break;
5554 case TNG_DOUBLE_DATA:
5555 default:
5556 size = sizeof(double);
5559 values = realloc(data->values,
5560 size * frame_alloc *
5561 n_values_per_frame);
5562 if(!values)
5564 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5565 size * frame_alloc *
5566 n_values_per_frame,
5567 __FILE__, __LINE__);
5568 free(data->values);
5569 data->values = 0;
5570 return(TNG_CRITICAL);
5572 data->values = values;
5575 return(TNG_SUCCESS);
5578 /** Read the values of a non-particle data block
5579 * @param tng_data is a trajectory data container.
5580 * @param block is the block to store the data (should already contain
5581 * the block headers and the block contents).
5582 * @param offset is the reading offset to point at the place where the actual
5583 * values are stored, starting from the beginning of the block_contents. The
5584 * offset is changed during the reading.
5585 * @param datatype is the type of data of the data block (char, int, float or
5586 * double).
5587 * @param first_frame_with_data is the frame number of the first frame with data
5588 * in this data block.
5589 * @param stride_length is the number of frames between each data entry.
5590 * @param n_frames is the number of frames in this data block.
5591 * @param n_values is the number of values per frame stored in this data block.
5592 * @param codec_id is the ID of the codec to compress the data.
5593 * @param multiplier is the multiplication factor applied to each data value
5594 * before compression. This factor is applied since some compression algorithms
5595 * work only on integers.
5596 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5597 * error has occured.
5599 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
5600 tng_gen_block_t block,
5601 int *offset,
5602 const char datatype,
5603 const int64_t first_frame_with_data,
5604 const int64_t stride_length,
5605 int64_t n_frames,
5606 const int64_t n_values,
5607 const int64_t codec_id,
5608 const double multiplier)
5610 int64_t i, j, n_frames_div;
5611 int size, len;
5612 #ifdef USE_ZLIB
5613 unsigned long data_size;
5614 #endif
5615 tng_non_particle_data_t data;
5616 tng_trajectory_frame_set_t frame_set =
5617 &tng_data->current_trajectory_frame_set;
5618 char block_type_flag;
5620 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5622 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
5624 switch(datatype)
5626 case TNG_CHAR_DATA:
5627 size = 1;
5628 break;
5629 case TNG_INT_DATA:
5630 size = sizeof(int64_t);
5631 break;
5632 case TNG_FLOAT_DATA:
5633 size = sizeof(float);
5634 break;
5635 case TNG_DOUBLE_DATA:
5636 default:
5637 size = sizeof(double);
5640 /* If the block does not exist, create it */
5641 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5643 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5645 block_type_flag = TNG_TRAJECTORY_BLOCK;
5647 else
5649 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5652 if(tng_data_block_create(tng_data, block_type_flag) !=
5653 TNG_SUCCESS)
5655 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5656 __FILE__, __LINE__);
5657 return(TNG_CRITICAL);
5659 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5661 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
5663 else
5665 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
5667 data->block_id = block->id;
5669 data->block_name = malloc(strlen(block->name) + 1);
5670 if(!data->block_name)
5672 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5673 (int)strlen(block->name)+1, __FILE__, __LINE__);
5674 return(TNG_CRITICAL);
5676 strcpy(data->block_name, block->name);
5678 data->datatype = datatype;
5680 data->values = 0;
5681 /* FIXME: Memory leak from strings. */
5682 data->strings = 0;
5683 data->n_frames = 0;
5684 data->codec_id = codec_id;
5685 data->compression_multiplier = multiplier;
5686 data->last_retrieved_frame = -1;
5689 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5691 if(codec_id != TNG_UNCOMPRESSED)
5693 switch(codec_id)
5695 #ifdef USE_ZLIB
5696 case TNG_GZIP_COMPRESSION:
5697 data_size = n_frames_div * size * n_values;
5698 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
5699 if(tng_gzip_uncompress(tng_data, block,
5700 block->block_contents + *offset,
5701 data_size) != TNG_SUCCESS)
5703 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5704 __LINE__);
5705 return(TNG_CRITICAL);
5707 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
5708 break;
5709 #endif
5713 /* Allocate memory */
5714 if(!data->values || data->n_frames != n_frames ||
5715 data->n_values_per_frame != n_values)
5717 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
5718 n_values) !=
5719 TNG_SUCCESS)
5721 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
5722 __FILE__, __LINE__);
5723 return(TNG_CRITICAL);
5727 data->first_frame_with_data = first_frame_with_data;
5729 if(datatype == TNG_CHAR_DATA)
5731 for(i = 0; i < n_frames_div; i++)
5733 for(j = 0; j < n_values; j++)
5735 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5736 TNG_MAX_STR_LEN);
5737 if(data->strings[i][j])
5739 free(data->strings[i][j]);
5741 data->strings[i][j] = malloc(len);
5742 if(!data->strings[i][j])
5744 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5745 len, __FILE__, __LINE__);
5746 return(TNG_CRITICAL);
5748 strncpy(data->strings[i][j], block->block_contents+*offset,
5749 len);
5750 *offset += len;
5754 else
5756 memcpy(data->values, block->block_contents + *offset,
5757 block->block_contents_size - *offset);
5758 switch(datatype)
5760 case TNG_FLOAT_DATA:
5761 if(tng_data->input_endianness_swap_func_32)
5763 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5765 if(tng_data->input_endianness_swap_func_32(tng_data,
5766 (int32_t *)((char *)data->values + i))
5767 != TNG_SUCCESS)
5769 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5770 __FILE__, __LINE__);
5774 break;
5775 case TNG_INT_DATA:
5776 case TNG_DOUBLE_DATA:
5777 if(tng_data->input_endianness_swap_func_64)
5779 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5781 if(tng_data->input_endianness_swap_func_64(tng_data,
5782 (int64_t *)((char *)data->values + i))
5783 != TNG_SUCCESS)
5785 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5786 __FILE__, __LINE__);
5790 break;
5791 case TNG_CHAR_DATA:
5792 break;
5795 return(TNG_SUCCESS);
5798 /** Write a non-particle data block
5799 * @param tng_data is a trajectory data container.
5800 * @param block is the block to store the data (should already contain
5801 * the block headers and the block contents).
5802 * @param block_index is the index number of the data block in the frame set.
5803 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5804 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5805 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5806 * error has occured.
5808 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
5809 tng_gen_block_t block,
5810 const int64_t block_index,
5811 const char hash_mode)
5813 int64_t n_frames, stride_length, frame_step;
5814 int64_t i, j;
5815 int offset = 0, size;
5816 unsigned int len;
5817 #ifdef USE_ZLIB
5818 int data_start_pos;
5819 tng_function_status stat;
5820 #endif
5821 char temp, dependency, *temp_name;
5822 double multiplier;
5823 tng_trajectory_frame_set_t frame_set =
5824 &tng_data->current_trajectory_frame_set;
5826 tng_non_particle_data_t data;
5827 char block_type_flag;
5829 /* If we have already started writing frame sets it is too late to write
5830 * non-trajectory data blocks */
5831 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5833 block_type_flag = TNG_TRAJECTORY_BLOCK;
5835 else
5837 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5840 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5842 return(TNG_CRITICAL);
5845 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5847 data = &frame_set->tr_data[block_index];
5849 /* If this data block has not had any data added in this frame set
5850 * do not write it. */
5851 if(data->first_frame_with_data < frame_set->first_frame)
5853 return(TNG_SUCCESS);
5856 stride_length = tng_max_i64(1, data->stride_length);
5858 else
5860 data = &tng_data->non_tr_data[block_index];
5861 stride_length = 1;
5864 switch(data->datatype)
5866 case TNG_CHAR_DATA:
5867 size = 1;
5868 break;
5869 case TNG_INT_DATA:
5870 size = sizeof(int64_t);
5871 break;
5872 case TNG_FLOAT_DATA:
5873 size = sizeof(float);
5874 break;
5875 case TNG_DOUBLE_DATA:
5876 default:
5877 size = sizeof(double);
5880 len = (unsigned int)strlen(data->block_name) + 1;
5882 if(!block->name || strlen(block->name) < len)
5884 temp_name = realloc(block->name, len);
5885 if(!temp_name)
5887 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
5888 __FILE__, __LINE__);
5889 free(block->name);
5890 block->name = 0;
5891 return(TNG_CRITICAL);
5893 block->name = temp_name;
5895 strncpy(block->name, data->block_name, len);
5896 block->id = data->block_id;
5898 /* If writing frame independent data data->n_frames is 0, but n_frames
5899 is used for the loop writing the data (and reserving memory) and needs
5900 to be at least 1 */
5901 n_frames = tng_max_i64(1, data->n_frames);
5903 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5905 /* If the frame set is finished before writing the full number of frames
5906 make sure the data block is not longer than the frame set. */
5907 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5909 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5912 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5913 n_frames / stride_length;
5915 /* TNG compression will use compression precision to get integers from
5916 * floating point data. The compression multiplier stores that information
5917 * to be able to return the precision of the compressed data. */
5918 if(data->codec_id == TNG_TNG_COMPRESSION)
5920 data->compression_multiplier = tng_data->compression_precision;
5922 /* Uncompressed data blocks do not use compression multipliers at all.
5923 * GZip compression does not need it either. */
5924 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5926 data->compression_multiplier = 1.0;
5929 block->block_contents_size = sizeof(char) * 2 +
5930 sizeof(data->n_values_per_frame) +
5931 sizeof(data->codec_id);
5933 if(stride_length > 1)
5935 block->block_contents_size += sizeof(data->first_frame_with_data) +
5936 sizeof(data->stride_length);
5939 if(data->codec_id != TNG_UNCOMPRESSED)
5941 block->block_contents_size += sizeof(data->compression_multiplier);
5944 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
5946 dependency = TNG_FRAME_DEPENDENT;
5948 else
5950 dependency = 0;
5952 if(dependency & TNG_FRAME_DEPENDENT)
5954 block->block_contents_size += sizeof(char);
5957 #ifdef USE_ZLIB
5958 data_start_pos = block->block_contents_size;
5959 #endif
5961 if(data->datatype == TNG_CHAR_DATA)
5963 for(i = n_frames; i--;)
5965 for(j = data->n_values_per_frame; j--;)
5967 block->block_contents_size += strlen(data->strings[i][j]) + 1;
5971 else
5973 block->block_contents_size += size * frame_step *
5974 data->n_values_per_frame;
5977 if(block->block_contents)
5979 free(block->block_contents);
5981 block->block_contents = malloc(block->block_contents_size);
5982 if(!block->block_contents)
5984 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5985 block->block_contents_size, __FILE__, __LINE__);
5986 return(TNG_CRITICAL);
5990 memcpy(block->block_contents, &data->datatype, sizeof(char));
5991 offset += sizeof(char);
5993 memcpy(block->block_contents+offset, &dependency, sizeof(char));
5994 offset += sizeof(char);
5996 if(dependency & TNG_FRAME_DEPENDENT)
5998 if(stride_length > 1)
6000 temp = 1;
6002 else
6004 temp = 0;
6006 memcpy(block->block_contents+offset, &temp, sizeof(char));
6007 offset += sizeof(char);
6010 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6011 sizeof(data->n_values_per_frame));
6012 if(tng_data->output_endianness_swap_func_64)
6014 if(tng_data->output_endianness_swap_func_64(tng_data,
6015 (int64_t *)block->header_contents+offset)
6016 != TNG_SUCCESS)
6018 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6019 __FILE__, __LINE__);
6022 offset += sizeof(data->n_values_per_frame);
6024 memcpy(block->block_contents+offset, &data->codec_id,
6025 sizeof(data->codec_id));
6026 if(tng_data->output_endianness_swap_func_64)
6028 if(tng_data->output_endianness_swap_func_64(tng_data,
6029 (int64_t *)block->header_contents+offset)
6030 != TNG_SUCCESS)
6032 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6033 __FILE__, __LINE__);
6036 offset += sizeof(data->codec_id);
6038 if(data->codec_id != TNG_UNCOMPRESSED)
6040 memcpy(block->block_contents+offset, &data->compression_multiplier,
6041 sizeof(data->compression_multiplier));
6042 if(tng_data->output_endianness_swap_func_64)
6044 if(tng_data->output_endianness_swap_func_64(tng_data,
6045 (int64_t *)block->header_contents+offset)
6046 != TNG_SUCCESS)
6048 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6049 __FILE__, __LINE__);
6052 offset += sizeof(data->compression_multiplier);
6055 if(data->n_frames > 0 && stride_length > 1)
6057 /* FIXME: first_frame_with_data is not reliably set */
6058 if(data->first_frame_with_data == 0)
6060 data->first_frame_with_data = frame_set->first_frame;
6062 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6063 sizeof(data->first_frame_with_data));
6064 if(tng_data->output_endianness_swap_func_64)
6066 if(tng_data->output_endianness_swap_func_64(tng_data,
6067 (int64_t *)block->header_contents+offset)
6068 != TNG_SUCCESS)
6070 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6071 __FILE__, __LINE__);
6074 offset += sizeof(data->first_frame_with_data);
6076 memcpy(block->block_contents+offset, &stride_length,
6077 sizeof(data->stride_length));
6078 if(tng_data->output_endianness_swap_func_64)
6080 if(tng_data->output_endianness_swap_func_64(tng_data,
6081 (int64_t *)block->header_contents+offset)
6082 != TNG_SUCCESS)
6084 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6085 __FILE__, __LINE__);
6088 offset += sizeof(data->stride_length);
6091 if(data->datatype == TNG_CHAR_DATA)
6093 if(data->strings)
6095 for(i = 0; i < frame_step; i++)
6097 for(j = 0; j < data->n_values_per_frame; j++)
6099 len = (unsigned int)strlen(data->strings[i][j]) + 1;
6100 strncpy(block->block_contents+offset, data->strings[i][j],
6101 len);
6102 offset += len;
6107 else if(data->values)
6109 memcpy(block->block_contents + offset, data->values,
6110 block->block_contents_size - offset);
6111 switch(data->datatype)
6113 case TNG_FLOAT_DATA:
6114 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6115 data->codec_id == TNG_TNG_COMPRESSION)
6117 if(tng_data->input_endianness_swap_func_32)
6119 for(i = offset; i < block->block_contents_size; i+=size)
6121 if(tng_data->input_endianness_swap_func_32(tng_data,
6122 (int32_t *)(block->block_contents + i))
6123 != TNG_SUCCESS)
6125 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6126 __FILE__, __LINE__);
6131 else
6133 multiplier = data->compression_multiplier;
6134 if(fabs(multiplier - 1.0) > 0.00001 ||
6135 tng_data->input_endianness_swap_func_32)
6137 for(i = offset; block->block_contents_size; i+=size)
6139 *(float *)(block->block_contents + i) *= (float)multiplier;
6140 if(tng_data->input_endianness_swap_func_32 &&
6141 tng_data->input_endianness_swap_func_32(tng_data,
6142 (int32_t *)(block->block_contents + i))
6143 != TNG_SUCCESS)
6145 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6146 __FILE__, __LINE__);
6151 break;
6152 case TNG_INT_DATA:
6153 if(tng_data->input_endianness_swap_func_64)
6155 for(i = offset; i < block->block_contents_size; i+=size)
6157 if(tng_data->input_endianness_swap_func_64(tng_data,
6158 (int64_t *)(block->block_contents + i))
6159 != TNG_SUCCESS)
6161 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6162 __FILE__, __LINE__);
6166 break;
6167 case TNG_DOUBLE_DATA:
6168 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6169 data->codec_id == TNG_TNG_COMPRESSION)
6171 if(tng_data->input_endianness_swap_func_64)
6173 for(i = offset; i < block->block_contents_size; i+=size)
6175 if(tng_data->input_endianness_swap_func_64(tng_data,
6176 (int64_t *)(block->block_contents + i))
6177 != TNG_SUCCESS)
6179 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6180 __FILE__, __LINE__);
6185 else
6187 multiplier = data->compression_multiplier;
6188 if(fabs(multiplier - 1.0) > 0.00001 ||
6189 tng_data->input_endianness_swap_func_64)
6191 for(i = offset; i < block->block_contents_size; i+=size)
6193 *(double *)(block->block_contents + i) *= multiplier;
6194 if(tng_data->input_endianness_swap_func_64 &&
6195 tng_data->input_endianness_swap_func_64(tng_data,
6196 (int64_t *)(block->block_contents + i))
6197 != TNG_SUCCESS)
6199 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6200 __FILE__, __LINE__);
6205 break;
6206 case TNG_CHAR_DATA:
6207 break;
6210 else
6212 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6215 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6216 frame_set->n_unwritten_frames = 0;
6218 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6220 switch(data->codec_id)
6222 #ifdef USE_ZLIB
6223 case TNG_GZIP_COMPRESSION:
6224 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6225 stat = tng_gzip_compress(tng_data, block,
6226 block->block_contents + data_start_pos,
6227 block->block_contents_size - data_start_pos);
6228 if(stat != TNG_SUCCESS)
6230 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6231 __LINE__);
6232 if(stat == TNG_CRITICAL)
6234 return(TNG_CRITICAL);
6236 data->codec_id = TNG_UNCOMPRESSED;
6238 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6239 break;
6240 #endif
6244 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6246 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6247 tng_data->output_file_path, __FILE__, __LINE__);
6248 return(TNG_CRITICAL);
6251 if(fwrite(block->block_contents, block->block_contents_size, 1,
6252 tng_data->output_file) != 1)
6254 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
6255 __FILE__, __LINE__);
6256 return(TNG_CRITICAL);
6259 return(TNG_SUCCESS);
6262 /** Read the meta information of a data block (particle or non-particle data).
6263 * @param tng_data is a trajectory data container.
6264 * @param block is the block to store the data (should already contain
6265 * the block headers).
6266 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6267 * error has occured.
6269 static tng_function_status tng_data_block_meta_information_read
6270 (tng_trajectory_t tng_data,
6271 tng_gen_block_t block,
6272 int *offset,
6273 char *datatype,
6274 char *dependency,
6275 char *sparse_data,
6276 int64_t *n_values,
6277 int64_t *codec_id,
6278 int64_t *first_frame_with_data,
6279 int64_t *stride_length,
6280 int64_t *n_frames,
6281 int64_t *num_first_particle,
6282 int64_t *block_n_particles,
6283 double *multiplier)
6285 int meta_size;
6286 char *contents;
6288 if(block->block_contents)
6290 contents = block->block_contents;
6292 else
6294 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
6295 contents = malloc(meta_size);
6296 if(!contents)
6298 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6299 meta_size, __FILE__, __LINE__);
6302 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
6304 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
6305 free(contents);
6306 return(TNG_CRITICAL);
6310 memcpy(datatype, contents+*offset,
6311 sizeof(*datatype));
6312 *offset += sizeof(*datatype);
6314 memcpy(dependency, contents+*offset,
6315 sizeof(*dependency));
6316 *offset += sizeof(*dependency);
6318 if(*dependency & TNG_FRAME_DEPENDENT)
6320 memcpy(sparse_data, contents+*offset,
6321 sizeof(*sparse_data));
6322 *offset += sizeof(*sparse_data);
6325 memcpy(n_values, contents+*offset,
6326 sizeof(*n_values));
6327 if(tng_data->input_endianness_swap_func_64)
6329 if(tng_data->input_endianness_swap_func_64(tng_data,
6330 n_values)
6331 != TNG_SUCCESS)
6333 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6334 __FILE__, __LINE__);
6337 *offset += sizeof(*n_values);
6339 memcpy(codec_id, contents+*offset,
6340 sizeof(*codec_id));
6341 if(tng_data->input_endianness_swap_func_64)
6343 if(tng_data->input_endianness_swap_func_64(tng_data,
6344 codec_id)
6345 != TNG_SUCCESS)
6347 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6348 __FILE__, __LINE__);
6351 *offset += sizeof(*codec_id);
6353 if(*codec_id != TNG_UNCOMPRESSED)
6355 memcpy(multiplier, contents+*offset,
6356 sizeof(*multiplier));
6357 if(tng_data->input_endianness_swap_func_64)
6359 if(tng_data->input_endianness_swap_func_64(tng_data,
6360 (int64_t *) multiplier)
6361 != TNG_SUCCESS)
6363 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6364 __FILE__, __LINE__);
6367 *offset += sizeof(*multiplier);
6369 else
6371 *multiplier = 1;
6374 if(*dependency & TNG_FRAME_DEPENDENT)
6376 if(*sparse_data)
6378 memcpy(first_frame_with_data, contents+*offset,
6379 sizeof(*first_frame_with_data));
6380 if(tng_data->input_endianness_swap_func_64)
6382 if(tng_data->input_endianness_swap_func_64(tng_data,
6383 first_frame_with_data)
6384 != TNG_SUCCESS)
6386 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6387 __FILE__, __LINE__);
6390 *offset += sizeof(*first_frame_with_data);
6392 memcpy(stride_length, contents+*offset,
6393 sizeof(*stride_length));
6394 if(tng_data->input_endianness_swap_func_64)
6396 if(tng_data->input_endianness_swap_func_64(tng_data,
6397 stride_length)
6398 != TNG_SUCCESS)
6400 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6401 __FILE__, __LINE__);
6404 *offset += sizeof(*stride_length);
6405 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
6406 (*first_frame_with_data -
6407 tng_data->current_trajectory_frame_set.first_frame);
6409 else
6411 *first_frame_with_data = 0;
6412 *stride_length = 1;
6413 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6416 else
6418 *first_frame_with_data = 0;
6419 *stride_length = 1;
6420 *n_frames = 1;
6423 if (*dependency & TNG_PARTICLE_DEPENDENT)
6425 memcpy(num_first_particle, contents+*offset,
6426 sizeof(*num_first_particle));
6427 if(tng_data->input_endianness_swap_func_64)
6429 if(tng_data->input_endianness_swap_func_64(tng_data,
6430 num_first_particle)
6431 != TNG_SUCCESS)
6433 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6434 __FILE__, __LINE__);
6437 *offset += sizeof(*num_first_particle);
6439 memcpy(block_n_particles, contents+*offset,
6440 sizeof(*block_n_particles));
6441 if(tng_data->input_endianness_swap_func_64)
6443 if(tng_data->input_endianness_swap_func_64(tng_data,
6444 block_n_particles)
6445 != TNG_SUCCESS)
6447 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6448 __FILE__, __LINE__);
6451 *offset += sizeof(*block_n_particles);
6454 if(!block->block_contents)
6456 free(contents);
6458 return(TNG_SUCCESS);
6461 /** Read the contents of a data block (particle or non-particle data).
6462 * @param tng_data is a trajectory data container.
6463 * @param block is the block to store the data (should already contain
6464 * the block headers).
6465 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6466 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6467 * compared to the md5 hash of the read contents to ensure valid data.
6468 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6469 * error has occured.
6471 static tng_function_status tng_data_block_contents_read
6472 (tng_trajectory_t tng_data,
6473 tng_gen_block_t block,
6474 const char hash_mode)
6476 int64_t n_values, codec_id, n_frames, first_frame_with_data;
6477 int64_t stride_length, block_n_particles, num_first_particle;
6478 double multiplier;
6479 char datatype, dependency, sparse_data;
6480 int offset = 0;
6481 tng_bool same_hash;
6483 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
6485 return(TNG_CRITICAL);
6488 if(block->block_contents)
6490 free(block->block_contents);
6493 block->block_contents = malloc(block->block_contents_size);
6494 if(!block->block_contents)
6496 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6497 block->block_contents_size, __FILE__, __LINE__);
6498 return(TNG_CRITICAL);
6501 /* Read the whole block into block_contents to be able to write it to
6502 * disk even if it cannot be interpreted. */
6503 if(fread(block->block_contents, block->block_contents_size, 1,
6504 tng_data->input_file) == 0)
6506 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
6507 return(TNG_CRITICAL);
6510 /* FIXME: Does not check if the size of the contents matches the expected
6511 * size or if the contents can be read. */
6513 if(hash_mode == TNG_USE_HASH)
6515 tng_md5_hash_match_verify(block, &same_hash);
6516 if(same_hash != TNG_TRUE)
6518 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
6519 block->name, __FILE__, __LINE__);
6520 /* return(TNG_FAILURE); */
6524 if(tng_data_block_meta_information_read(tng_data, block,
6525 &offset, &datatype,
6526 &dependency, &sparse_data,
6527 &n_values, &codec_id,
6528 &first_frame_with_data,
6529 &stride_length, &n_frames,
6530 &num_first_particle,
6531 &block_n_particles,
6532 &multiplier) == TNG_CRITICAL)
6534 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6535 block->name, __FILE__, __LINE__);
6536 return(TNG_CRITICAL);
6539 if (dependency & TNG_PARTICLE_DEPENDENT)
6541 return(tng_particle_data_read(tng_data, block,
6542 &offset, datatype,
6543 num_first_particle,
6544 block_n_particles,
6545 first_frame_with_data,
6546 stride_length,
6547 n_frames, n_values,
6548 codec_id, multiplier));
6550 else
6552 return(tng_data_read(tng_data, block,
6553 &offset, datatype,
6554 first_frame_with_data,
6555 stride_length,
6556 n_frames, n_values,
6557 codec_id, multiplier));
6561 /** Update the md5 hash of a block already written to the file
6562 * @param tng_data is a trajectory data container.
6563 * @param block is the block, of which to update the md5 hash.
6564 * @param header_start_pos is the file position where the block header starts.
6565 * @param contents_start_pos is the file position where the block contents
6566 * start.
6567 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6568 * error has occured.
6570 static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
6571 tng_gen_block_t block,
6572 const int64_t header_start_pos,
6573 const int64_t contents_start_pos)
6575 if(block->block_contents)
6577 free(block->block_contents);
6580 block->block_contents = malloc(block->block_contents_size);
6581 if(!block->block_contents)
6583 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6584 block->block_contents_size, __FILE__, __LINE__);
6585 return(TNG_CRITICAL);
6588 fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
6589 if(fread(block->block_contents, block->block_contents_size, 1,
6590 tng_data->output_file) == 0)
6592 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
6593 return(TNG_CRITICAL);
6596 tng_block_md5_hash_generate(block);
6598 fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
6599 SEEK_SET);
6600 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
6602 return(TNG_SUCCESS);
6605 /** Update the frame set pointers in the file header (general info block),
6606 * already written to disk
6607 * @param tng_data is a trajectory data container.
6608 * @param hash_mode specifies whether to update the block md5 hash when
6609 * updating the pointers.
6610 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6611 * error has occured.
6613 static tng_function_status tng_header_pointers_update
6614 (tng_trajectory_t tng_data, const char hash_mode)
6616 tng_gen_block_t block;
6617 FILE *temp = tng_data->input_file;
6618 int64_t output_file_pos, pos, contents_start_pos;
6620 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6622 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6623 __FILE__, __LINE__);
6624 return(TNG_CRITICAL);
6627 tng_data->input_file = tng_data->output_file;
6629 tng_block_init(&block);
6631 output_file_pos = ftell(tng_data->output_file);
6632 fseek(tng_data->output_file, 0, SEEK_SET);
6634 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6636 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
6637 __FILE__, __LINE__);
6638 tng_data->input_file = temp;
6639 tng_block_destroy(&block);
6640 return(TNG_CRITICAL);
6643 contents_start_pos = ftell(tng_data->output_file);
6645 fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
6646 sizeof(int64_t), SEEK_CUR);
6648 tng_data->input_file = temp;
6650 pos = tng_data->first_trajectory_frame_set_output_file_pos;
6652 if(tng_data->input_endianness_swap_func_64)
6654 if(tng_data->input_endianness_swap_func_64(tng_data,
6655 &pos)
6656 != TNG_SUCCESS)
6658 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6659 __FILE__, __LINE__);
6663 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6665 tng_block_destroy(&block);
6666 return(TNG_CRITICAL);
6669 pos = tng_data->last_trajectory_frame_set_output_file_pos;
6671 if(tng_data->input_endianness_swap_func_64)
6673 if(tng_data->input_endianness_swap_func_64(tng_data,
6674 &pos)
6675 != TNG_SUCCESS)
6677 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6678 __FILE__, __LINE__);
6682 if(fwrite(&pos,
6683 sizeof(int64_t), 1, tng_data->output_file) != 1)
6685 tng_block_destroy(&block);
6686 return(TNG_CRITICAL);
6689 if(hash_mode == TNG_USE_HASH)
6691 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
6694 tng_block_destroy(&block);
6696 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
6698 return(TNG_SUCCESS);
6701 /** Update the frame set pointers in the current frame set block, already
6702 * written to disk. It also updates the pointers of the blocks pointing to
6703 * the current frame set block.
6704 * @param tng_data is a trajectory data container.
6705 * @param hash_mode specifies whether to update the block md5 hash when
6706 * updating the pointers.
6707 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6708 * error has occured.
6710 static tng_function_status tng_frame_set_pointers_update
6711 (tng_trajectory_t tng_data, const char hash_mode)
6713 tng_gen_block_t block;
6714 tng_trajectory_frame_set_t frame_set;
6715 FILE *temp = tng_data->input_file;
6716 int64_t pos, output_file_pos, header_start_pos, contents_start_pos;
6718 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6720 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6721 __FILE__, __LINE__);
6722 return(TNG_CRITICAL);
6725 tng_block_init(&block);
6726 output_file_pos = ftell(tng_data->output_file);
6728 tng_data->input_file = tng_data->output_file;
6730 frame_set = &tng_data->current_trajectory_frame_set;
6732 /* Update previous frame set */
6733 if(frame_set->prev_frame_set_file_pos != -1 &&
6734 frame_set->prev_frame_set_file_pos != 0)
6736 fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
6737 SEEK_SET);
6739 header_start_pos = frame_set->prev_frame_set_file_pos;
6741 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6743 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
6744 __FILE__, __LINE__);
6745 tng_data->input_file = temp;
6746 tng_block_destroy(&block);
6747 return(TNG_CRITICAL);
6750 contents_start_pos = ftell(tng_data->output_file);
6752 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
6753 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
6755 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6757 if(tng_data->input_endianness_swap_func_64)
6759 if(tng_data->input_endianness_swap_func_64(tng_data,
6760 &pos)
6761 != TNG_SUCCESS)
6763 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6764 __FILE__, __LINE__);
6768 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6770 tng_data->input_file = temp;
6771 tng_block_destroy(&block);
6772 return(TNG_CRITICAL);
6775 if(hash_mode == TNG_USE_HASH)
6777 tng_md5_hash_update(tng_data, block, header_start_pos,
6778 contents_start_pos);
6780 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
6783 /* Update the frame set one medium stride step before */
6784 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
6785 frame_set->medium_stride_prev_frame_set_file_pos != 0)
6787 fseek(tng_data->output_file,
6788 (long)frame_set->medium_stride_prev_frame_set_file_pos,
6789 SEEK_SET);
6791 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6793 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6794 __FILE__, __LINE__);
6795 tng_data->input_file = temp;
6796 tng_block_destroy(&block);
6797 return(TNG_CRITICAL);
6800 contents_start_pos = ftell(tng_data->output_file);
6802 fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
6803 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
6805 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6807 if(tng_data->input_endianness_swap_func_64)
6809 if(tng_data->input_endianness_swap_func_64(tng_data,
6810 &pos)
6811 != TNG_SUCCESS)
6813 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6814 __FILE__, __LINE__);
6818 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6820 tng_data->input_file = temp;
6821 tng_block_destroy(&block);
6822 return(TNG_CRITICAL);
6825 if(hash_mode == TNG_USE_HASH)
6827 tng_md5_hash_update(tng_data, block,
6828 frame_set->medium_stride_prev_frame_set_file_pos,
6829 contents_start_pos);
6833 /* Update the frame set one long stride step before */
6834 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
6835 frame_set->long_stride_prev_frame_set_file_pos != 0)
6837 fseek(tng_data->output_file,
6838 (long)frame_set->long_stride_prev_frame_set_file_pos,
6839 SEEK_SET);
6841 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6843 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6844 __FILE__, __LINE__);
6845 tng_data->input_file = temp;
6846 tng_block_destroy(&block);
6847 return(TNG_CRITICAL);
6850 contents_start_pos = ftell(tng_data->output_file);
6852 fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
6853 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
6855 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6857 if(tng_data->input_endianness_swap_func_64)
6859 if(tng_data->input_endianness_swap_func_64(tng_data,
6860 &pos)
6861 != TNG_SUCCESS)
6863 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6864 __FILE__, __LINE__);
6868 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6870 tng_data->input_file = temp;
6871 tng_block_destroy(&block);
6872 return(TNG_CRITICAL);
6875 if(hash_mode == TNG_USE_HASH)
6877 tng_md5_hash_update(tng_data, block,
6878 frame_set->long_stride_prev_frame_set_file_pos,
6879 contents_start_pos);
6883 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
6885 tng_data->input_file = temp;
6887 tng_block_destroy(&block);
6889 return(TNG_SUCCESS);
6892 // ** Move the blocks in a frame set so that there is no unused space between
6893 // * them. This can only be done on the last frame set in the file and should
6894 // * be done e.g. if the last frame set in the file has fewer frames than
6895 // * default or after compressing data blocks in a frame set.
6896 // * @param tng_data is a trajectory data container.
6897 // * @details the current_trajectory_frame_set is the one that will be modified.
6898 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6899 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6900 // * FIXME: This function is not finished!!!
6901 // *
6902 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6903 // {
6904 // tng_gen_block_t block;
6905 // tng_trajectory_frame_set_t frame_set;
6906 // FILE *temp = tng_data->input_file;
6907 // int64_t pos, contents_start_pos, output_file_len;
6909 // frame_set = &tng_data->current_trajectory_frame_set;
6911 // if(frame_set->n_written_frames == frame_set->n_frames)
6912 // {
6913 // return(TNG_SUCCESS);
6914 // }
6916 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6917 // tng_data->last_trajectory_frame_set_output_file_pos)
6918 // {
6919 // }
6921 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6922 // {
6923 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6924 // __FILE__, __LINE__);
6925 // return(TNG_CRITICAL);
6926 // }
6928 // tng_block_init(&block);
6929 // // output_file_pos = ftell(tng_data->output_file);
6931 // tng_data->input_file = tng_data->output_file;
6933 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6935 // fseek(tng_data->output_file, pos, SEEK_SET);
6936 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6937 // {
6938 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6939 // __FILE__, __LINE__);
6940 // tng_data->input_file = temp;
6941 // tng_block_destroy(&block);
6942 // return(TNG_CRITICAL);
6943 // }
6945 // contents_start_pos = ftell(tng_data->output_file);
6947 // fseek(tng_data->output_file, 0, SEEK_END);
6948 // output_file_len = ftell(tng_data->output_file);
6949 // pos = contents_start_pos + block->block_contents_size;
6950 // fseek(tng_data->output_file, pos,
6951 // SEEK_SET);
6953 // while(pos < output_file_len)
6954 // {
6955 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6956 // {
6957 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
6958 // __FILE__, __LINE__);
6959 // tng_data->input_file = temp;
6960 // tng_block_destroy(&block);
6961 // return(TNG_CRITICAL);
6962 // }
6963 // pos += block->header_contents_size + block->block_contents_size;
6964 // fseek(tng_data->output_file, pos, SEEK_SET);
6965 // }
6967 // return(TNG_SUCCESS);
6968 // }
6970 /** Finish writing the current frame set. Update the number of frames
6971 * and the hashes of the frame set and all its data blocks (if hash_mode
6972 * == TNG_USE_HASH).
6973 * @param tng_data is a trajectory data container.
6974 * @param hash_mode specifies whether to update the block md5 hash when
6975 * updating the pointers.
6976 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6977 * error has occured.
6979 static tng_function_status tng_frame_set_finalize
6980 (tng_trajectory_t tng_data, const char hash_mode)
6982 tng_gen_block_t block;
6983 tng_trajectory_frame_set_t frame_set;
6984 FILE *temp = tng_data->input_file;
6985 int64_t pos, contents_start_pos, output_file_len;
6987 frame_set = &tng_data->current_trajectory_frame_set;
6989 if(frame_set->n_written_frames == frame_set->n_frames)
6991 return(TNG_SUCCESS);
6994 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6996 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6997 __FILE__, __LINE__);
6998 return(TNG_CRITICAL);
7001 tng_block_init(&block);
7002 /* output_file_pos = ftell(tng_data->output_file); */
7004 tng_data->input_file = tng_data->output_file;
7006 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7008 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7010 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7012 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7013 __FILE__, __LINE__);
7014 tng_data->input_file = temp;
7015 tng_block_destroy(&block);
7016 return(TNG_CRITICAL);
7019 contents_start_pos = ftell(tng_data->output_file);
7021 fseek(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7022 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7023 1, tng_data->output_file) != 1)
7025 tng_data->input_file = temp;
7026 tng_block_destroy(&block);
7027 return(TNG_CRITICAL);
7031 if(hash_mode == TNG_USE_HASH)
7033 tng_md5_hash_update(tng_data, block, pos,
7034 pos + block->header_contents_size);
7037 fseek(tng_data->output_file, 0, SEEK_END);
7038 output_file_len = ftell(tng_data->output_file);
7039 pos = contents_start_pos + block->block_contents_size;
7040 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7042 while(pos < output_file_len)
7044 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7046 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7047 __FILE__, __LINE__);
7048 tng_data->input_file = temp;
7049 tng_block_destroy(&block);
7050 return(TNG_CRITICAL);
7053 if(hash_mode == TNG_USE_HASH)
7055 tng_md5_hash_update(tng_data, block, pos,
7056 pos + block->header_contents_size);
7058 pos += block->header_contents_size + block->block_contents_size;
7059 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7062 tng_data->input_file = temp;
7063 tng_block_destroy(&block);
7064 return(TNG_SUCCESS);
7068 // ** Sets the name of a file contents block
7069 // * @param tng_data is a trajectory data container.
7070 // * @param block is the block, of which to change names.
7071 // * @param new_name is the new name of the block.
7072 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7073 // * error has occured.
7075 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7076 // tng_gen_block_t block,
7077 // const char *new_name)
7078 // {
7079 // int len;
7081 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7083 // * If the currently stored string length is not enough to store the new
7084 // * string it is freed and reallocated. *
7085 // if(block->name && strlen(block->name) < len)
7086 // {
7087 // free(block->name);
7088 // block->name = 0;
7089 // }
7090 // if(!block->name)
7091 // {
7092 // block->name = malloc(len);
7093 // if(!block->name)
7094 // {
7095 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7096 // __FILE__, __LINE__);
7097 // return(TNG_CRITICAL);
7098 // }
7099 // }
7101 // strncpy(block->name, new_name, len);
7103 // return(TNG_SUCCESS);
7104 // }
7107 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7108 const tng_atom_t atom,
7109 tng_residue_t *residue)
7111 (void) tng_data;
7113 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7115 *residue = atom->residue;
7117 return(TNG_SUCCESS);
7120 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7121 const tng_atom_t atom,
7122 char *name,
7123 const int max_len)
7125 (void) tng_data;
7126 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7127 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7129 strncpy(name, atom->name, max_len - 1);
7130 name[max_len - 1] = 0;
7132 if(strlen(atom->name) > (unsigned int)max_len - 1)
7134 return(TNG_FAILURE);
7136 return(TNG_SUCCESS);
7139 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7140 tng_atom_t atom,
7141 const char *new_name)
7143 unsigned int len;
7144 (void)tng_data;
7146 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7147 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7149 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7151 /* If the currently stored string length is not enough to store the new
7152 * string it is freed and reallocated. */
7153 if(atom->name && strlen(atom->name) < len)
7155 free(atom->name);
7156 atom->name = 0;
7158 if(!atom->name)
7160 atom->name = malloc(len);
7161 if(!atom->name)
7163 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7164 __FILE__, __LINE__);
7165 return(TNG_CRITICAL);
7169 strncpy(atom->name, new_name, len);
7171 return(TNG_SUCCESS);
7174 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7175 const tng_atom_t atom,
7176 char *type,
7177 const int max_len)
7179 (void) tng_data;
7180 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7181 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7183 strncpy(type, atom->atom_type, max_len - 1);
7184 type[max_len - 1] = 0;
7186 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7188 return(TNG_FAILURE);
7190 return(TNG_SUCCESS);
7193 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7194 tng_atom_t atom,
7195 const char *new_type)
7197 unsigned int len;
7198 (void)tng_data;
7200 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7201 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7203 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7205 /* If the currently stored string length is not enough to store the new
7206 * string it is freed and reallocated. */
7207 if(atom->atom_type && strlen(atom->atom_type) < len)
7209 free(atom->atom_type);
7210 atom->atom_type = 0;
7212 if(!atom->atom_type)
7214 atom->atom_type = malloc(len);
7215 if(!atom->atom_type)
7217 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7218 __FILE__, __LINE__);
7219 return(TNG_CRITICAL);
7223 strncpy(atom->atom_type, new_type, len);
7225 return(TNG_SUCCESS);
7228 /** Initialise an atom struct
7229 * @param atom is the atom to initialise.
7230 * @return TNG_SUCCESS (0) if successful.
7232 static tng_function_status tng_atom_init(tng_atom_t atom)
7234 atom->name = 0;
7235 atom->atom_type = 0;
7237 return(TNG_SUCCESS);
7240 /** Free the memory in an atom struct
7241 * @param atom is the atom to destroy.
7242 * @return TNG_SUCCESS (0) if successful.
7244 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7246 if(atom->name)
7248 free(atom->name);
7249 atom->name = 0;
7251 if(atom->atom_type)
7253 free(atom->atom_type);
7254 atom->atom_type = 0;
7257 return(TNG_SUCCESS);
7260 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7261 (tng_trajectory_t tng_data,
7262 const char *name,
7263 tng_molecule_t *molecule)
7265 int64_t id, i;
7266 tng_bool found_id = TNG_TRUE;
7268 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7269 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7271 /* Find an unused ID */
7272 id = 0;
7273 while(found_id)
7275 found_id = TNG_FALSE;
7276 for(i = tng_data->n_molecules; i--;)
7278 if(tng_data->molecules[i].id == id)
7280 found_id = TNG_TRUE;
7281 i = 0;
7284 if(found_id)
7286 id++;
7290 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7293 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7294 (tng_trajectory_t tng_data,
7295 const char *name,
7296 const int64_t id,
7297 tng_molecule_t *molecule)
7299 tng_molecule_t new_molecules;
7300 int64_t *new_molecule_cnt_list, i;
7301 tng_function_status stat = TNG_SUCCESS;
7303 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7304 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7306 new_molecules = realloc(tng_data->molecules,
7307 sizeof(struct tng_molecule) *
7308 (tng_data->n_molecules + 1));
7310 if(!new_molecules)
7312 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7313 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7314 __FILE__, __LINE__);
7315 free(tng_data->molecules);
7316 tng_data->molecules = 0;
7317 return(TNG_CRITICAL);
7320 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7321 sizeof(int64_t) *
7322 (tng_data->n_molecules + 1));
7324 if(!new_molecule_cnt_list)
7326 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7327 sizeof(int64_t) * (tng_data->n_molecules + 1),
7328 __FILE__, __LINE__);
7329 free(tng_data->molecule_cnt_list);
7330 tng_data->molecule_cnt_list = 0;
7331 free(new_molecules);
7332 return(TNG_CRITICAL);
7335 tng_data->molecules = new_molecules;
7336 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7338 *molecule = &new_molecules[tng_data->n_molecules];
7340 tng_molecule_init(tng_data, *molecule);
7341 tng_molecule_name_set(tng_data, *molecule, name);
7343 /* FIXME: Should this be a function argument instead? */
7344 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7346 for(i = tng_data->n_molecules; i--;)
7348 if(tng_data->molecules[i].id == id)
7350 stat = TNG_FAILURE;
7351 fprintf(stderr, "TNG library: Molecule ID %"PRId64" already in use. %s: %d\n", id,
7352 __FILE__, __LINE__);
7353 break;
7357 (*molecule)->id = id;
7359 tng_data->n_molecules++;
7361 return(stat);
7364 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
7365 (tng_trajectory_t tng_data,
7366 tng_molecule_t *molecule_p)
7368 tng_bool found_id = TNG_TRUE;
7369 tng_molecule_t new_molecules, molecule;
7370 int64_t *new_molecule_cnt_list, i, id;
7372 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7374 /* Find an unused ID */
7375 id = 0;
7376 while(found_id)
7378 found_id = TNG_FALSE;
7379 for(i = tng_data->n_molecules; i--;)
7381 if(tng_data->molecules[i].id == id)
7383 found_id = TNG_TRUE;
7384 i = 0;
7387 if(found_id)
7389 id++;
7393 new_molecules = realloc(tng_data->molecules,
7394 sizeof(struct tng_molecule) *
7395 (tng_data->n_molecules + 1));
7397 if(!new_molecules)
7399 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7400 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7401 __FILE__, __LINE__);
7402 free(tng_data->molecules);
7403 tng_data->molecules = 0;
7404 return(TNG_CRITICAL);
7407 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7408 sizeof(int64_t) *
7409 (tng_data->n_molecules + 1));
7411 if(!new_molecule_cnt_list)
7413 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7414 sizeof(int64_t) * (tng_data->n_molecules + 1),
7415 __FILE__, __LINE__);
7416 free(tng_data->molecule_cnt_list);
7417 tng_data->molecule_cnt_list = 0;
7418 free(new_molecules);
7419 return(TNG_CRITICAL);
7422 molecule = *molecule_p;
7424 tng_data->molecules = new_molecules;
7425 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7427 new_molecules[tng_data->n_molecules] = *molecule;
7429 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7431 free(*molecule_p);
7433 molecule = &new_molecules[tng_data->n_molecules];
7435 *molecule_p = molecule;
7437 molecule->id = id;
7439 tng_data->n_molecules++;
7441 return(TNG_SUCCESS);
7444 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
7445 const tng_molecule_t molecule,
7446 char *name,
7447 const int max_len)
7449 (void) tng_data;
7450 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7451 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7453 strncpy(name, molecule->name, max_len - 1);
7454 name[max_len - 1] = 0;
7456 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7458 return(TNG_FAILURE);
7460 return(TNG_SUCCESS);
7463 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7464 (tng_trajectory_t tng_data,
7465 tng_molecule_t molecule,
7466 const char *new_name)
7468 unsigned int len;
7469 (void)tng_data;
7471 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7472 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7474 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7476 /* If the currently stored string length is not enough to store the new
7477 * string it is freed and reallocated. */
7478 if(molecule->name && strlen(molecule->name) < len)
7480 free(molecule->name);
7481 molecule->name = 0;
7483 if(!molecule->name)
7485 molecule->name = malloc(len);
7486 if(!molecule->name)
7488 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7489 __FILE__, __LINE__);
7490 return(TNG_CRITICAL);
7494 strncpy(molecule->name, new_name, len);
7496 return(TNG_SUCCESS);
7499 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7500 (const tng_trajectory_t tng_data,
7501 const tng_molecule_t molecule,
7502 int64_t *cnt)
7504 int64_t i, index = -1;
7506 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7507 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7509 for(i = tng_data->n_molecules; i--;)
7511 if(&tng_data->molecules[i] == molecule)
7513 index = i;
7514 i = 0;
7517 if(index == -1)
7519 return(TNG_FAILURE);
7521 *cnt = tng_data->molecule_cnt_list[index];
7523 return(TNG_SUCCESS);
7526 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7527 (tng_trajectory_t tng_data,
7528 tng_molecule_t molecule,
7529 const int64_t cnt)
7531 int64_t i, old_cnt, index = -1;
7533 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7535 for(i = tng_data->n_molecules; i--;)
7537 if(&tng_data->molecules[i] == molecule)
7539 index = i;
7540 i = 0;
7543 if(index == -1)
7545 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7546 __FILE__, __LINE__);
7547 return(TNG_FAILURE);
7549 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7551 old_cnt = tng_data->molecule_cnt_list[index];
7552 tng_data->molecule_cnt_list[index] = cnt;
7554 tng_data->n_particles += (cnt-old_cnt) *
7555 tng_data->molecules[index].n_atoms;
7557 else
7559 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7560 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7562 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7563 tng_data->molecules[index].n_atoms;
7566 return(TNG_SUCCESS);
7569 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7570 (tng_trajectory_t tng_data,
7571 const char *name,
7572 int64_t nr,
7573 tng_molecule_t *molecule)
7575 int64_t i, n_molecules;
7577 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7578 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7579 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7581 n_molecules = tng_data->n_molecules;
7583 for(i = 0; i < n_molecules; i++)
7585 *molecule = &tng_data->molecules[i];
7586 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7588 if(nr == -1 || nr == (*molecule)->id)
7590 return(TNG_SUCCESS);
7595 *molecule = 0;
7597 return(TNG_FAILURE);
7600 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7601 (tng_trajectory_t tng_data,
7602 int64_t index,
7603 tng_molecule_t *molecule)
7605 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7606 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7608 if(index >= tng_data->n_molecules)
7610 *molecule = 0;
7611 return(TNG_FAILURE);
7613 *molecule = &tng_data->molecules[index];
7614 return(TNG_SUCCESS);
7617 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
7618 tng_trajectory_t tng_data_dest)
7620 tng_molecule_t molecule, molecule_temp;
7621 tng_chain_t chain, chain_temp;
7622 tng_residue_t residue, residue_temp;
7623 tng_atom_t atom, atom_temp;
7624 tng_bond_t bond_temp;
7625 tng_function_status stat;
7626 int64_t i, j, k, l, *list_temp;
7628 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7629 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7631 for(i = 0; i < tng_data_dest->n_molecules; i++)
7633 molecule = &tng_data_dest->molecules[i];
7634 tng_molecule_destroy(tng_data_dest, molecule);
7637 tng_data_dest->n_molecules = 0;
7638 tng_data_dest->n_particles = 0;
7640 molecule_temp = realloc(tng_data_dest->molecules,
7641 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7642 if(!molecule_temp)
7644 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7645 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
7646 __FILE__, __LINE__);
7647 free(tng_data_dest->molecules);
7648 tng_data_dest->molecules = 0;
7649 return(TNG_CRITICAL);
7651 list_temp = realloc(tng_data_dest->molecule_cnt_list,
7652 sizeof(int64_t) * tng_data_src->n_molecules);
7653 if(!list_temp)
7655 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7656 sizeof(int64_t) * tng_data_src->n_molecules,
7657 __FILE__, __LINE__);
7658 free(tng_data_dest->molecule_cnt_list);
7659 tng_data_dest->molecule_cnt_list = 0;
7660 free(molecule_temp);
7661 return(TNG_CRITICAL);
7664 tng_data_dest->molecules = molecule_temp;
7665 tng_data_dest->molecule_cnt_list = list_temp;
7667 for(i = 0; i < tng_data_src->n_molecules; i++)
7669 molecule = &tng_data_src->molecules[i];
7670 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7671 &molecule_temp);
7672 if(stat != TNG_SUCCESS)
7674 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7675 __FILE__, __LINE__);
7676 return(stat);
7678 molecule_temp->quaternary_str = molecule->quaternary_str;
7679 for(j = 0; j < molecule->n_chains; j++)
7681 chain = &molecule->chains[j];
7682 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7683 chain->name, chain->id,
7684 &chain_temp);
7685 if(stat != TNG_SUCCESS)
7687 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7688 __FILE__, __LINE__);
7689 return(stat);
7691 for(k = 0; k < chain->n_residues; k++)
7693 residue = &chain->residues[k];
7694 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7695 residue->name, residue->id,
7696 &residue_temp);
7697 if(stat != TNG_SUCCESS)
7699 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7700 __FILE__, __LINE__);
7701 return(stat);
7703 for(l = 0; l < residue->n_atoms; l++)
7705 atom = &molecule->atoms[residue->atoms_offset + l];
7706 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7707 atom->name, atom->atom_type,
7708 atom->id, &atom_temp);
7709 if(stat != TNG_SUCCESS)
7711 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7712 __FILE__, __LINE__);
7713 return(stat);
7718 molecule_temp->n_bonds = molecule->n_bonds;
7719 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7720 molecule->n_bonds);
7721 if(!bond_temp)
7723 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7724 sizeof(struct tng_bond) * molecule->n_bonds,
7725 __FILE__, __LINE__);
7726 free(molecule_temp->bonds);
7727 molecule_temp->n_bonds = 0;
7728 return(TNG_CRITICAL);
7730 molecule_temp->bonds = bond_temp;
7731 for(j = 0; j < molecule->n_bonds; j++)
7733 molecule_temp->bonds[j] = molecule->bonds[j];
7735 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7736 tng_data_src->molecule_cnt_list[i]);
7737 if(stat != TNG_SUCCESS)
7739 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7740 __FILE__, __LINE__);
7741 return(stat);
7744 return(TNG_SUCCESS);
7747 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7748 (const tng_trajectory_t tng_data,
7749 const tng_molecule_t molecule,
7750 int64_t *n)
7752 (void) tng_data;
7753 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7754 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7756 *n = molecule->n_chains;
7758 return(TNG_SUCCESS);
7761 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7762 (tng_trajectory_t tng_data,
7763 tng_molecule_t molecule,
7764 int64_t index,
7765 tng_chain_t *chain)
7767 (void) tng_data;
7768 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7769 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7771 if(index >= molecule->n_chains)
7773 *chain = 0;
7774 return(TNG_FAILURE);
7776 *chain = &molecule->chains[index];
7777 return(TNG_SUCCESS);
7780 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7781 (const tng_trajectory_t tng_data,
7782 const tng_molecule_t molecule,
7783 int64_t *n)
7785 (void) tng_data;
7786 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7787 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7789 *n = molecule->n_residues;
7791 return(TNG_SUCCESS);
7794 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7795 (const tng_trajectory_t tng_data,
7796 const tng_molecule_t molecule,
7797 const int64_t index,
7798 tng_residue_t *residue)
7800 (void) tng_data;
7801 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7802 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7804 if(index >= molecule->n_residues)
7806 *residue = 0;
7807 return(TNG_FAILURE);
7809 *residue = &molecule->residues[index];
7810 return(TNG_SUCCESS);
7813 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7814 (const tng_trajectory_t tng_data,
7815 const tng_molecule_t molecule,
7816 int64_t *n)
7818 (void) tng_data;
7819 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7820 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7822 *n = molecule->n_atoms;
7824 return(TNG_SUCCESS);
7827 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7828 (const tng_trajectory_t tng_data,
7829 const tng_molecule_t molecule,
7830 const int64_t index,
7831 tng_atom_t *atom)
7833 (void) tng_data;
7834 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7835 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7837 if(index >= molecule->n_atoms)
7839 *atom = 0;
7840 return(TNG_FAILURE);
7842 *atom = &molecule->atoms[index];
7843 return(TNG_SUCCESS);
7846 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7847 (tng_trajectory_t tng_data,
7848 tng_molecule_t molecule,
7849 const char *name,
7850 int64_t nr,
7851 tng_chain_t *chain)
7853 int64_t i, n_chains;
7854 (void)tng_data;
7856 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7857 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7859 n_chains = molecule->n_chains;
7861 for(i = 0; i < n_chains; i++)
7863 *chain = &molecule->chains[i];
7864 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7866 if(nr == -1 || nr == (*chain)->id)
7868 return(TNG_SUCCESS);
7873 *chain = 0;
7875 return(TNG_FAILURE);
7878 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7879 (tng_trajectory_t tng_data,
7880 tng_molecule_t molecule,
7881 const char *name,
7882 tng_chain_t *chain)
7884 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7885 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7887 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7888 molecule->n_chains + 1, chain));
7891 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7892 (tng_trajectory_t tng_data,
7893 tng_molecule_t molecule,
7894 const char *name,
7895 const int64_t id,
7896 tng_chain_t *chain)
7898 int64_t i;
7899 tng_chain_t new_chains;
7900 tng_function_status stat = TNG_SUCCESS;
7902 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7903 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7905 new_chains = realloc(molecule->chains,
7906 sizeof(struct tng_chain) *
7907 (molecule->n_chains + 1));
7909 if(!new_chains)
7911 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7912 sizeof(struct tng_chain) * (molecule->n_chains + 1),
7913 __FILE__, __LINE__);
7914 free(molecule->chains);
7915 molecule->chains = 0;
7916 return(TNG_CRITICAL);
7919 molecule->chains = new_chains;
7921 *chain = &new_chains[molecule->n_chains];
7922 (*chain)->name = 0;
7924 tng_chain_name_set(tng_data, *chain, name);
7926 (*chain)->molecule = molecule;
7927 (*chain)->n_residues = 0;
7929 for(i = molecule->n_chains; i--;)
7931 if(molecule->chains[i].id == id)
7933 stat = TNG_FAILURE;
7934 fprintf(stderr, "TNG library: Chain ID already in use. %s: %d\n", __FILE__, __LINE__);
7935 break;
7939 molecule->n_chains++;
7941 (*chain)->id = id;
7943 return(stat);
7946 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7947 (const tng_trajectory_t tng_data,
7948 tng_molecule_t molecule,
7949 const int64_t from_atom_id,
7950 const int64_t to_atom_id,
7951 tng_bond_t *bond)
7953 int64_t i;
7954 tng_bond_t new_bonds;
7955 (void)tng_data;
7957 for(i = 0; i < molecule->n_bonds; i++)
7959 *bond = &molecule->bonds[i];
7960 /* Check if the bond already exists */
7961 if(((*bond)->from_atom_id == from_atom_id && (*bond)->to_atom_id == to_atom_id) ||
7962 ((*bond)->to_atom_id == from_atom_id && (*bond)->from_atom_id == to_atom_id))
7964 return(TNG_SUCCESS);
7968 new_bonds = realloc(molecule->bonds,
7969 sizeof(struct tng_bond) *
7970 (molecule->n_bonds + 1));
7972 if(!new_bonds)
7974 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7975 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
7976 __FILE__, __LINE__);
7977 *bond = 0;
7978 free(molecule->bonds);
7979 molecule->bonds = 0;
7980 return(TNG_CRITICAL);
7983 molecule->bonds = new_bonds;
7985 *bond = &new_bonds[molecule->n_bonds];
7987 (*bond)->from_atom_id = from_atom_id;
7988 (*bond)->to_atom_id = to_atom_id;
7990 molecule->n_bonds++;
7992 return(TNG_SUCCESS);
7995 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7996 (tng_trajectory_t tng_data,
7997 tng_molecule_t molecule,
7998 const char *name,
7999 int64_t id,
8000 tng_atom_t *atom)
8002 int64_t i, n_atoms;
8003 (void)tng_data;
8005 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8007 n_atoms = molecule->n_atoms;
8009 for(i = 0; i < n_atoms; i++)
8011 *atom = &molecule->atoms[i];
8012 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8014 if(id == -1 || id == (*atom)->id)
8016 return(TNG_SUCCESS);
8021 *atom = 0;
8023 return(TNG_FAILURE);
8026 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8027 const tng_chain_t chain,
8028 char *name,
8029 const int max_len)
8031 (void) tng_data;
8032 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8033 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8035 strncpy(name, chain->name, max_len - 1);
8036 name[max_len - 1] = 0;
8038 if(strlen(chain->name) > (unsigned int)max_len - 1)
8040 return(TNG_FAILURE);
8042 return(TNG_SUCCESS);
8045 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8046 (tng_trajectory_t tng_data,
8047 tng_chain_t chain,
8048 const char *new_name)
8050 unsigned int len;
8051 (void)tng_data;
8053 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8055 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8057 /* If the currently stored string length is not enough to store the new
8058 * string it is freed and reallocated. */
8059 if(chain->name && strlen(chain->name) < len)
8061 free(chain->name);
8062 chain->name = 0;
8064 if(!chain->name)
8066 chain->name = malloc(len);
8067 if(!chain->name)
8069 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8070 __FILE__, __LINE__);
8071 return(TNG_CRITICAL);
8075 strncpy(chain->name, new_name, len);
8077 return(TNG_SUCCESS);
8080 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8081 (const tng_trajectory_t tng_data,
8082 const tng_chain_t chain,
8083 int64_t *n)
8085 (void) tng_data;
8086 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8087 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8089 *n = chain->n_residues;
8091 return(TNG_SUCCESS);
8094 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8095 (const tng_trajectory_t tng_data,
8096 const tng_chain_t chain,
8097 const int64_t index,
8098 tng_residue_t *residue)
8100 (void) tng_data;
8101 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8102 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8104 if(index >= chain->n_residues)
8106 *residue = 0;
8107 return(TNG_FAILURE);
8109 *residue = &chain->residues[index];
8110 return(TNG_SUCCESS);
8113 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8114 (tng_trajectory_t tng_data,
8115 tng_chain_t chain,
8116 const char *name,
8117 int64_t id,
8118 tng_residue_t *residue)
8120 int64_t i, n_residues;
8121 (void)tng_data;
8123 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8125 n_residues = chain->n_residues;
8127 for(i = 0; i < n_residues; i++)
8129 *residue = &chain->residues[i];
8130 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8132 if(id == -1 || id == (*residue)->id)
8134 return(TNG_SUCCESS);
8139 *residue = 0;
8141 return(TNG_FAILURE);
8144 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8145 (tng_trajectory_t tng_data,
8146 tng_chain_t chain,
8147 const char *name,
8148 tng_residue_t *residue)
8150 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8151 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8153 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8154 chain->n_residues + 1, residue));
8157 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8158 (tng_trajectory_t tng_data,
8159 tng_chain_t chain,
8160 const char *name,
8161 const int64_t id,
8162 tng_residue_t *residue)
8164 int64_t i, curr_index;
8165 tng_residue_t new_residues, temp_residue, last_residue;
8166 tng_molecule_t molecule = chain->molecule;
8167 tng_function_status stat = TNG_SUCCESS;
8169 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8170 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8172 if(chain->n_residues)
8174 curr_index = chain->residues - molecule->residues;
8176 else
8178 curr_index = -1;
8181 new_residues = realloc(molecule->residues,
8182 sizeof(struct tng_residue) *
8183 (molecule->n_residues + 1));
8185 if(!new_residues)
8187 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8188 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8189 __FILE__, __LINE__);
8190 free(molecule->residues);
8191 molecule->residues = 0;
8192 return(TNG_CRITICAL);
8195 molecule->residues = new_residues;
8197 if(curr_index != -1)
8199 chain->residues = new_residues + curr_index;
8200 if(molecule->n_residues)
8202 last_residue = &new_residues[molecule->n_residues - 1];
8204 temp_residue = chain->residues + (chain->n_residues - 1);
8205 /* Make space in list of residues to add the new residues together with the other
8206 * residues of this chain */
8207 if(temp_residue != last_residue)
8209 ++temp_residue;
8210 memmove(temp_residue + 1, temp_residue,
8211 last_residue - temp_residue);
8215 else
8217 curr_index = molecule->n_residues;
8220 *residue = &molecule->residues[curr_index + chain->n_residues];
8222 if(!chain->n_residues)
8224 chain->residues = *residue;
8227 (*residue)->name = 0;
8228 tng_residue_name_set(tng_data, *residue, name);
8230 (*residue)->chain = chain;
8231 (*residue)->n_atoms = 0;
8232 (*residue)->atoms_offset = 0;
8234 for(i = chain->n_residues; i--;)
8236 if(chain->residues[i].id == id)
8238 stat = TNG_FAILURE;
8239 fprintf(stderr, "TNG library: Residue ID already in use. %s: %d\n", __FILE__, __LINE__);
8240 break;
8244 chain->n_residues++;
8245 molecule->n_residues++;
8247 (*residue)->id = id;
8249 return(stat);
8252 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8253 const tng_residue_t residue,
8254 char *name,
8255 const int max_len)
8257 (void) tng_data;
8258 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8259 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8261 strncpy(name, residue->name, max_len - 1);
8262 name[max_len - 1] = 0;
8264 if(strlen(residue->name) > (unsigned int)max_len - 1)
8266 return(TNG_FAILURE);
8268 return(TNG_SUCCESS);
8271 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8272 tng_residue_t residue,
8273 const char *new_name)
8275 unsigned int len;
8276 (void)tng_data;
8278 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8279 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8281 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8283 /* If the currently stored string length is not enough to store the new
8284 * string it is freed and reallocated. */
8285 if(residue->name && strlen(residue->name) < len)
8287 free(residue->name);
8288 residue->name = 0;
8290 if(!residue->name)
8292 residue->name = malloc(len);
8293 if(!residue->name)
8295 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8296 __FILE__, __LINE__);
8297 return(TNG_CRITICAL);
8301 strncpy(residue->name, new_name, len);
8303 return(TNG_SUCCESS);
8306 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8307 (const tng_trajectory_t tng_data,
8308 const tng_residue_t residue,
8309 int64_t *n)
8311 (void) tng_data;
8312 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8313 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8315 *n = residue->n_atoms;
8317 return(TNG_SUCCESS);
8320 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8321 (const tng_trajectory_t tng_data,
8322 const tng_residue_t residue,
8323 const int64_t index,
8324 tng_atom_t *atom)
8326 tng_chain_t chain;
8327 tng_molecule_t molecule;
8329 (void) tng_data;
8330 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8331 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8333 if(index >= residue->n_atoms)
8335 *atom = 0;
8336 return(TNG_FAILURE);
8338 chain = residue->chain;
8339 molecule = chain->molecule;
8341 if(index + residue->atoms_offset >= molecule->n_atoms)
8343 *atom = 0;
8344 return(TNG_FAILURE);
8347 *atom = &molecule->atoms[residue->atoms_offset + index];
8348 return(TNG_SUCCESS);
8351 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8352 (tng_trajectory_t tng_data,
8353 tng_residue_t residue,
8354 const char *atom_name,
8355 const char *atom_type,
8356 tng_atom_t *atom)
8358 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8359 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8360 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8362 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
8363 residue->chain->molecule->n_atoms + 1,
8364 atom));
8367 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
8368 (tng_trajectory_t tng_data,
8369 tng_residue_t residue,
8370 const char *atom_name,
8371 const char *atom_type,
8372 const int64_t id,
8373 tng_atom_t *atom)
8375 int64_t i;
8376 tng_atom_t new_atoms;
8377 tng_molecule_t molecule = residue->chain->molecule;
8378 tng_function_status stat = TNG_SUCCESS;
8380 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8381 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8382 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8384 if(!residue->n_atoms)
8386 residue->atoms_offset = molecule->n_atoms;
8389 new_atoms = realloc(molecule->atoms,
8390 sizeof(struct tng_atom) *
8391 (molecule->n_atoms + 1));
8393 if(!new_atoms)
8395 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8396 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
8397 __FILE__, __LINE__);
8398 free(molecule->atoms);
8399 molecule->atoms = 0;
8400 return(TNG_CRITICAL);
8403 molecule->atoms = new_atoms;
8405 *atom = &new_atoms[molecule->n_atoms];
8407 tng_atom_init(*atom);
8408 tng_atom_name_set(tng_data, *atom, atom_name);
8409 tng_atom_type_set(tng_data, *atom, atom_type);
8411 (*atom)->residue = residue;
8413 for(i = molecule->n_atoms; i--;)
8415 if(molecule->atoms[i].id == id)
8417 stat = TNG_FAILURE;
8418 fprintf(stderr, "TNG library: Atom ID %"PRId64" already in use. %s: %d\n", id, __FILE__, __LINE__);
8419 break;
8423 residue->n_atoms++;
8424 molecule->n_atoms++;
8426 (*atom)->id = id;
8428 return(stat);
8431 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8432 tng_molecule_t *molecule_p)
8434 *molecule_p = malloc(sizeof(struct tng_molecule));
8435 if(!*molecule_p)
8437 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
8438 sizeof(struct tng_molecule), __FILE__, __LINE__);
8439 return(TNG_CRITICAL);
8442 tng_molecule_init(tng_data, *molecule_p);
8444 return(TNG_SUCCESS);
8447 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8448 tng_molecule_t *molecule_p)
8450 if(!*molecule_p)
8452 return(TNG_SUCCESS);
8455 tng_molecule_destroy(tng_data, *molecule_p);
8457 free(*molecule_p);
8458 *molecule_p = 0;
8460 return(TNG_SUCCESS);
8463 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8464 tng_molecule_t molecule)
8466 (void)tng_data;
8467 molecule->quaternary_str = 1;
8468 molecule->name = 0;
8469 molecule->n_chains = 0;
8470 molecule->chains = 0;
8471 molecule->n_residues = 0;
8472 molecule->residues = 0;
8473 molecule->n_atoms = 0;
8474 molecule->atoms = 0;
8475 molecule->n_bonds = 0;
8476 molecule->bonds = 0;
8478 return(TNG_SUCCESS);
8481 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8482 tng_molecule_t molecule)
8484 int64_t i;
8485 (void)tng_data;
8487 if(molecule->name)
8489 free(molecule->name);
8490 molecule->name = 0;
8493 if(molecule->chains)
8495 for(i = molecule->n_chains; i--;)
8497 if(molecule->chains[i].name)
8499 free(molecule->chains[i].name);
8500 molecule->chains[i].name = 0;
8503 free(molecule->chains);
8504 molecule->chains = 0;
8506 molecule->n_chains = 0;
8508 if(molecule->residues)
8510 for(i = molecule->n_residues; i--;)
8512 if(molecule->residues[i].name)
8514 free(molecule->residues[i].name);
8515 molecule->residues[i].name = 0;
8518 free(molecule->residues);
8519 molecule->residues = 0;
8521 molecule->n_residues = 0;
8523 if(molecule->atoms)
8525 for(i = molecule->n_atoms; i--;)
8527 tng_atom_destroy(&molecule->atoms[i]);
8529 free(molecule->atoms);
8530 molecule->atoms = 0;
8532 molecule->n_atoms = 0;
8534 if(molecule->bonds)
8536 free(molecule->bonds);
8537 molecule->bonds = 0;
8539 molecule->n_bonds = 0;
8541 return(TNG_SUCCESS);
8544 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8545 (const tng_trajectory_t tng_data,
8546 const int64_t nr,
8547 char *name,
8548 int max_len)
8550 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8551 tng_molecule_t mol;
8552 tng_bool found = TNG_FALSE;
8554 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8555 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8557 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8559 if(!molecule_cnt_list)
8561 return(TNG_FAILURE);
8564 for(i = 0; i < tng_data->n_molecules; i++)
8566 mol = &tng_data->molecules[i];
8567 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8569 cnt += mol->n_atoms * molecule_cnt_list[i];
8570 continue;
8572 found = TNG_TRUE;
8573 break;
8575 if(!found)
8577 return(TNG_FAILURE);
8580 strncpy(name, mol->name, max_len - 1);
8581 name[max_len - 1] = 0;
8583 if(strlen(mol->name) > (unsigned int)max_len - 1)
8585 return(TNG_FAILURE);
8587 return(TNG_SUCCESS);
8590 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8591 (const tng_trajectory_t tng_data,
8592 const int64_t nr,
8593 int64_t *id)
8595 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8596 tng_molecule_t mol;
8597 tng_bool found = TNG_FALSE;
8599 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8600 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8602 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8604 if(!molecule_cnt_list)
8606 return(TNG_FAILURE);
8609 for(i = 0; i < tng_data->n_molecules; i++)
8611 mol = &tng_data->molecules[i];
8612 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8614 cnt += mol->n_atoms * molecule_cnt_list[i];
8615 continue;
8617 found = TNG_TRUE;
8618 break;
8620 if(!found)
8622 return(TNG_FAILURE);
8625 *id = mol->id;
8627 return(TNG_SUCCESS);
8630 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8631 (const tng_trajectory_t tng_data,
8632 int64_t *n_bonds,
8633 int64_t **from_atoms,
8634 int64_t **to_atoms)
8636 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8637 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8638 tng_molecule_t mol;
8639 tng_bond_t bond;
8641 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8642 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8643 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8644 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8646 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8648 if(!molecule_cnt_list)
8650 return(TNG_FAILURE);
8653 *n_bonds = 0;
8654 /* First count the total number of bonds to allocate memory */
8655 for(i = 0; i < tng_data->n_molecules; i++)
8657 mol = &tng_data->molecules[i];
8658 mol_cnt = molecule_cnt_list[i];
8659 *n_bonds += mol_cnt * mol->n_bonds;
8661 if(*n_bonds == 0)
8663 return(TNG_SUCCESS);
8666 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8667 if(!*from_atoms)
8669 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8670 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8671 return(TNG_CRITICAL);
8673 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8674 if(!*to_atoms)
8676 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8677 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8678 free(*from_atoms);
8679 *from_atoms = 0;
8680 return(TNG_CRITICAL);
8683 cnt = 0;
8684 for(i = 0; i < tng_data->n_molecules; i++)
8686 mol = &tng_data->molecules[i];
8687 mol_cnt = molecule_cnt_list[i];
8688 for(j = 0; j < mol_cnt; j++)
8690 for(k = 0; k < mol->n_bonds; k++)
8692 bond = &mol->bonds[k];
8693 from_atom = atom_cnt + bond->from_atom_id;
8694 to_atom = atom_cnt + bond->to_atom_id;
8695 (*from_atoms)[cnt] = from_atom;
8696 (*to_atoms)[cnt++] = to_atom;
8698 atom_cnt += mol->n_atoms;
8702 return(TNG_SUCCESS);
8705 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8706 (const tng_trajectory_t tng_data,
8707 const int64_t nr,
8708 char *name,
8709 int max_len)
8711 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8712 tng_molecule_t mol;
8713 tng_atom_t atom;
8714 tng_bool found = TNG_FALSE;
8716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8717 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8719 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8721 if(!molecule_cnt_list)
8723 return(TNG_FAILURE);
8726 for(i = 0; i < tng_data->n_molecules; i++)
8728 mol = &tng_data->molecules[i];
8729 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8731 cnt += mol->n_atoms * molecule_cnt_list[i];
8732 continue;
8734 atom = &mol->atoms[nr % mol->n_atoms];
8735 found = TNG_TRUE;
8736 break;
8738 if(!found)
8740 return(TNG_FAILURE);
8742 if(!atom->residue || !atom->residue->chain)
8744 return(TNG_FAILURE);
8747 strncpy(name, atom->residue->chain->name, max_len - 1);
8748 name[max_len - 1] = 0;
8750 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8752 return(TNG_FAILURE);
8754 return(TNG_SUCCESS);
8757 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8758 (const tng_trajectory_t tng_data,
8759 const int64_t nr,
8760 char *name,
8761 int max_len)
8763 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8764 tng_molecule_t mol;
8765 tng_atom_t atom;
8766 tng_bool found = TNG_FALSE;
8768 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8769 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8771 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8773 if(!molecule_cnt_list)
8775 return(TNG_FAILURE);
8778 for(i = 0; i < tng_data->n_molecules; i++)
8780 mol = &tng_data->molecules[i];
8781 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8783 cnt += mol->n_atoms * molecule_cnt_list[i];
8784 continue;
8786 atom = &mol->atoms[nr % mol->n_atoms];
8787 found = TNG_TRUE;
8788 break;
8790 if(!found)
8792 return(TNG_FAILURE);
8794 if(!atom->residue)
8796 return(TNG_FAILURE);
8799 strncpy(name, atom->residue->name, max_len - 1);
8800 name[max_len - 1] = 0;
8802 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8804 return(TNG_FAILURE);
8806 return(TNG_SUCCESS);
8809 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8810 (const tng_trajectory_t tng_data,
8811 const int64_t nr,
8812 int64_t *id)
8814 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8815 tng_molecule_t mol;
8816 tng_atom_t atom;
8817 tng_bool found = TNG_FALSE;
8819 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8820 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8822 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8824 if(!molecule_cnt_list)
8826 return(TNG_FAILURE);
8829 for(i = 0; i < tng_data->n_molecules; i++)
8831 mol = &tng_data->molecules[i];
8832 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8834 cnt += mol->n_atoms * molecule_cnt_list[i];
8835 continue;
8837 atom = &mol->atoms[nr % mol->n_atoms];
8838 found = TNG_TRUE;
8839 break;
8841 if(!found)
8843 return(TNG_FAILURE);
8845 if(!atom->residue)
8847 return(TNG_FAILURE);
8850 *id = atom->residue->id;
8852 return(TNG_SUCCESS);
8855 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8856 (const tng_trajectory_t tng_data,
8857 const int64_t nr,
8858 int64_t *id)
8860 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8861 tng_molecule_t mol;
8862 tng_atom_t atom;
8863 tng_bool found = TNG_FALSE;
8865 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8866 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8868 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8870 if(!molecule_cnt_list)
8872 return(TNG_FAILURE);
8875 for(i = 0; i < tng_data->n_molecules; i++)
8877 mol = &tng_data->molecules[i];
8878 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8880 cnt += mol->n_atoms * molecule_cnt_list[i];
8881 offset += mol->n_residues * molecule_cnt_list[i];
8882 continue;
8884 atom = &mol->atoms[nr % mol->n_atoms];
8885 found = TNG_TRUE;
8886 break;
8888 if(!found)
8890 return(TNG_FAILURE);
8892 if(!atom->residue)
8894 return(TNG_FAILURE);
8897 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8899 *id = atom->residue->id + offset;
8901 return(TNG_SUCCESS);
8904 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8905 (const tng_trajectory_t tng_data,
8906 const int64_t nr,
8907 char *name,
8908 int max_len)
8910 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8911 tng_molecule_t mol;
8912 tng_atom_t atom;
8913 tng_bool found = TNG_FALSE;
8915 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8916 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8918 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8920 if(!molecule_cnt_list)
8922 return(TNG_FAILURE);
8925 for(i = 0; i < tng_data->n_molecules; i++)
8927 mol = &tng_data->molecules[i];
8928 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8930 cnt += mol->n_atoms * molecule_cnt_list[i];
8931 continue;
8933 atom = &mol->atoms[nr % mol->n_atoms];
8934 found = TNG_TRUE;
8935 break;
8937 if(!found)
8939 return(TNG_FAILURE);
8942 strncpy(name, atom->name, max_len - 1);
8943 name[max_len - 1] = 0;
8945 if(strlen(atom->name) > (unsigned int)max_len - 1)
8947 return(TNG_FAILURE);
8949 return(TNG_SUCCESS);
8952 tng_function_status tng_atom_type_of_particle_nr_get
8953 (const tng_trajectory_t tng_data,
8954 const int64_t nr,
8955 char *type,
8956 int max_len)
8958 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8959 tng_molecule_t mol;
8960 tng_atom_t atom;
8961 tng_bool found = TNG_FALSE;
8963 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8964 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8966 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8968 if(!molecule_cnt_list)
8970 return(TNG_FAILURE);
8973 for(i = 0; i < tng_data->n_molecules; i++)
8975 mol = &tng_data->molecules[i];
8976 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8978 cnt += mol->n_atoms * molecule_cnt_list[i];
8979 continue;
8981 atom = &mol->atoms[nr % mol->n_atoms];
8982 found = TNG_TRUE;
8983 break;
8985 if(!found)
8987 return(TNG_FAILURE);
8990 strncpy(type, atom->atom_type, max_len - 1);
8991 type[max_len - 1] = 0;
8993 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8995 return(TNG_FAILURE);
8997 return(TNG_SUCCESS);
9000 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9001 (tng_trajectory_t tng_data,
9002 const int64_t num_first_particle,
9003 const int64_t n_particles,
9004 const int64_t *mapping_table)
9006 int64_t i;
9007 tng_particle_mapping_t mapping;
9008 tng_trajectory_frame_set_t frame_set;
9010 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9012 frame_set = &tng_data->current_trajectory_frame_set;
9014 /* Sanity check of the particle ranges. Split into multiple if
9015 * statements for improved readability */
9016 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9018 mapping = &frame_set->mappings[i];
9019 if(num_first_particle >= mapping->num_first_particle &&
9020 num_first_particle < mapping->num_first_particle +
9021 mapping->n_particles)
9023 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9024 return(TNG_FAILURE);
9026 if(num_first_particle + n_particles >=
9027 mapping->num_first_particle &&
9028 num_first_particle + n_particles <
9029 mapping->num_first_particle + mapping->n_particles)
9031 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9032 return(TNG_FAILURE);
9034 if(mapping->num_first_particle >= num_first_particle &&
9035 mapping->num_first_particle < num_first_particle +
9036 n_particles)
9038 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9039 return(TNG_FAILURE);
9041 if(mapping->num_first_particle + mapping->n_particles >
9042 num_first_particle &&
9043 mapping->num_first_particle + mapping->n_particles <
9044 num_first_particle + n_particles)
9046 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9047 return(TNG_FAILURE);
9051 frame_set->n_mapping_blocks++;
9053 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9054 frame_set->n_mapping_blocks);
9056 if(!mapping)
9058 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9059 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9060 __FILE__, __LINE__);
9061 free(frame_set->mappings);
9062 frame_set->mappings = 0;
9063 return(TNG_CRITICAL);
9065 frame_set->mappings = mapping;
9067 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9068 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9070 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9071 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9073 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9074 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9075 return(TNG_CRITICAL);
9078 for(i=0; i<n_particles; i++)
9080 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9083 return(TNG_SUCCESS);
9086 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9088 tng_trajectory_frame_set_t frame_set;
9089 tng_particle_mapping_t mapping;
9090 int64_t i;
9092 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9094 frame_set = &tng_data->current_trajectory_frame_set;
9096 if(frame_set->n_mapping_blocks && frame_set->mappings)
9098 for(i = frame_set->n_mapping_blocks; i--;)
9100 mapping = &frame_set->mappings[i];
9101 if(mapping->real_particle_numbers)
9103 free(mapping->real_particle_numbers);
9104 mapping->real_particle_numbers = 0;
9107 free(frame_set->mappings);
9108 frame_set->mappings = 0;
9109 frame_set->n_mapping_blocks = 0;
9112 return(TNG_SUCCESS);
9115 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9117 time_t seconds;
9118 tng_trajectory_frame_set_t frame_set;
9119 tng_trajectory_t tng_data;
9121 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9122 if(!*tng_data_p)
9124 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9125 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9126 return(TNG_CRITICAL);
9129 tng_data = *tng_data_p;
9131 frame_set = &tng_data->current_trajectory_frame_set;
9133 tng_data->input_file_path = 0;
9134 tng_data->input_file = 0;
9135 tng_data->input_file_len = 0;
9136 tng_data->output_file_path = 0;
9137 tng_data->output_file = 0;
9139 tng_data->first_program_name = 0;
9140 tng_data->first_user_name = 0;
9141 tng_data->first_computer_name = 0;
9142 tng_data->first_pgp_signature = 0;
9143 tng_data->last_program_name = 0;
9144 tng_data->last_user_name = 0;
9145 tng_data->last_computer_name = 0;
9146 tng_data->last_pgp_signature = 0;
9147 tng_data->forcefield_name = 0;
9149 seconds = time(0);
9150 if ( seconds == -1)
9152 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9154 else
9156 tng_data->time = seconds;
9159 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9160 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9161 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9162 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9163 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9164 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9165 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9166 tng_data->frame_set_n_frames = 100;
9167 tng_data->n_trajectory_frame_sets = 0;
9168 tng_data->n_trajectory_blocks = 0;
9169 tng_data->medium_stride_length = 100;
9170 tng_data->long_stride_length = 10000;
9172 tng_data->time_per_frame = -1;
9174 tng_data->n_particle_data_blocks = 0;
9175 tng_data->n_data_blocks = 0;
9177 tng_data->non_tr_particle_data = 0;
9178 tng_data->non_tr_data = 0;
9180 tng_data->compress_algo_pos = 0;
9181 tng_data->compress_algo_vel = 0;
9182 tng_data->compression_precision = 1000;
9183 tng_data->distance_unit_exponential = -9;
9185 frame_set->first_frame = -1;
9186 frame_set->n_mapping_blocks = 0;
9187 frame_set->mappings = 0;
9188 frame_set->molecule_cnt_list = 0;
9190 frame_set->n_particle_data_blocks = 0;
9191 frame_set->n_data_blocks = 0;
9193 frame_set->tr_particle_data = 0;
9194 frame_set->tr_data = 0;
9196 frame_set->n_written_frames = 0;
9197 frame_set->n_unwritten_frames = 0;
9199 frame_set->next_frame_set_file_pos = -1;
9200 frame_set->prev_frame_set_file_pos = -1;
9201 frame_set->medium_stride_next_frame_set_file_pos = -1;
9202 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9203 frame_set->long_stride_next_frame_set_file_pos = -1;
9204 frame_set->long_stride_prev_frame_set_file_pos = -1;
9206 frame_set->first_frame_time = -1;
9208 tng_data->n_molecules = 0;
9209 tng_data->molecules = 0;
9210 tng_data->molecule_cnt_list = 0;
9211 tng_data->n_particles = 0;
9214 /* Check the endianness of the computer */
9215 static int32_t endianness_32 = 0x01234567;
9216 /* 0x01234567 */
9217 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9219 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9222 /* 0x67452301 */
9223 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9225 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9229 /* 0x45670123 */
9230 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9232 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9236 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9237 /* 0x0123456789ABCDEF */
9238 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9240 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9243 /* 0xEFCDAB8967452301 */
9244 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9246 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9249 /* 0x89ABCDEF01234567 */
9250 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9252 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9255 /* 0x45670123CDEF89AB */
9256 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9258 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9261 /* 0x23016745AB89EFCD */
9262 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9264 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9268 /* By default do not swap the byte order, i.e. keep the byte order of the
9269 * architecture. The input file endianness will be set when reading the
9270 * header. The output endianness can be changed - before the file is
9271 * written. */
9272 tng_data->input_endianness_swap_func_32 = 0;
9273 tng_data->input_endianness_swap_func_64 = 0;
9274 tng_data->output_endianness_swap_func_32 = 0;
9275 tng_data->output_endianness_swap_func_64 = 0;
9277 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9278 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9279 tng_data->current_trajectory_frame_set.n_frames = 0;
9281 return(TNG_SUCCESS);
9284 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9286 int64_t i, j, k, l;
9287 int64_t n_particles, n_values_per_frame;
9288 tng_trajectory_t tng_data = *tng_data_p;
9289 tng_trajectory_frame_set_t frame_set;
9291 if(!*tng_data_p)
9293 return(TNG_SUCCESS);
9296 frame_set = &tng_data->current_trajectory_frame_set;
9298 if(tng_data->input_file_path)
9300 free(tng_data->input_file_path);
9301 tng_data->input_file_path = 0;
9304 if(tng_data->input_file)
9306 fclose(tng_data->input_file);
9307 tng_data->input_file = 0;
9310 if(tng_data->output_file_path)
9312 free(tng_data->output_file_path);
9313 tng_data->output_file_path = 0;
9316 if(tng_data->output_file)
9318 /* FIXME: Do not always write the hash */
9319 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9320 fclose(tng_data->output_file);
9321 tng_data->output_file = 0;
9324 if(tng_data->first_program_name)
9326 free(tng_data->first_program_name);
9327 tng_data->first_program_name = 0;
9330 if(tng_data->last_program_name)
9332 free(tng_data->last_program_name);
9333 tng_data->last_program_name = 0;
9336 if(tng_data->first_user_name)
9338 free(tng_data->first_user_name);
9339 tng_data->first_user_name = 0;
9342 if(tng_data->last_user_name)
9344 free(tng_data->last_user_name);
9345 tng_data->last_user_name = 0;
9348 if(tng_data->first_computer_name)
9350 free(tng_data->first_computer_name);
9351 tng_data->first_computer_name = 0;
9354 if(tng_data->last_computer_name)
9356 free(tng_data->last_computer_name);
9357 tng_data->last_computer_name = 0;
9360 if(tng_data->first_pgp_signature)
9362 free(tng_data->first_pgp_signature);
9363 tng_data->first_pgp_signature = 0;
9366 if(tng_data->last_pgp_signature)
9368 free(tng_data->last_pgp_signature);
9369 tng_data->last_pgp_signature = 0;
9372 if(tng_data->forcefield_name)
9374 free(tng_data->forcefield_name);
9375 tng_data->forcefield_name = 0;
9378 tng_frame_set_particle_mapping_free(tng_data);
9380 if(frame_set->molecule_cnt_list)
9382 free(frame_set->molecule_cnt_list);
9383 frame_set->molecule_cnt_list = 0;
9386 if(tng_data->var_num_atoms_flag)
9388 n_particles = frame_set->n_particles;
9390 else
9392 n_particles = tng_data->n_particles;
9395 if(tng_data->non_tr_particle_data)
9397 for(i = tng_data->n_particle_data_blocks; i--; )
9399 if(tng_data->non_tr_particle_data[i].values)
9401 free(tng_data->non_tr_particle_data[i].values);
9402 tng_data->non_tr_particle_data[i].values = 0;
9405 if(tng_data->non_tr_particle_data[i].strings)
9407 n_values_per_frame = tng_data->non_tr_particle_data[i].
9408 n_values_per_frame;
9409 if(tng_data->non_tr_particle_data[i].strings[0])
9411 for(j = n_particles; j--;)
9413 if(tng_data->non_tr_particle_data[i].strings[0][j])
9415 for(k = n_values_per_frame; k--;)
9417 if(tng_data->non_tr_particle_data[i].
9418 strings[0][j][k])
9420 free(tng_data->non_tr_particle_data[i].
9421 strings[0][j][k]);
9422 tng_data->non_tr_particle_data[i].
9423 strings[0][j][k] = 0;
9426 free(tng_data->non_tr_particle_data[i].
9427 strings[0][j]);
9428 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9431 free(tng_data->non_tr_particle_data[i].strings[0]);
9432 tng_data->non_tr_particle_data[i].strings[0] = 0;
9434 free(tng_data->non_tr_particle_data[i].strings);
9435 tng_data->non_tr_particle_data[i].strings = 0;
9438 if(tng_data->non_tr_particle_data[i].block_name)
9440 free(tng_data->non_tr_particle_data[i].block_name);
9441 tng_data->non_tr_particle_data[i].block_name = 0;
9444 free(tng_data->non_tr_particle_data);
9445 tng_data->non_tr_particle_data = 0;
9448 if(tng_data->non_tr_data)
9450 for(i = tng_data->n_data_blocks; i--;)
9452 if(tng_data->non_tr_data[i].values)
9454 free(tng_data->non_tr_data[i].values);
9455 tng_data->non_tr_data[i].values = 0;
9458 if(tng_data->non_tr_data[i].strings)
9460 n_values_per_frame = tng_data->non_tr_data[i].
9461 n_values_per_frame;
9462 if(tng_data->non_tr_data[i].strings[0])
9464 for(j = n_values_per_frame; j--;)
9466 if(tng_data->non_tr_data[i].strings[0][j])
9468 free(tng_data->non_tr_data[i].strings[0][j]);
9469 tng_data->non_tr_data[i].strings[0][j] = 0;
9472 free(tng_data->non_tr_data[i].strings[0]);
9473 tng_data->non_tr_data[i].strings[0] = 0;
9475 free(tng_data->non_tr_data[i].strings);
9476 tng_data->non_tr_data[i].strings = 0;
9479 if(tng_data->non_tr_data[i].block_name)
9481 free(tng_data->non_tr_data[i].block_name);
9482 tng_data->non_tr_data[i].block_name = 0;
9485 free(tng_data->non_tr_data);
9486 tng_data->non_tr_data = 0;
9489 tng_data->n_particle_data_blocks = 0;
9490 tng_data->n_data_blocks = 0;
9492 if(tng_data->compress_algo_pos)
9494 free(tng_data->compress_algo_pos);
9495 tng_data->compress_algo_pos = 0;
9497 if(tng_data->compress_algo_vel)
9499 free(tng_data->compress_algo_vel);
9500 tng_data->compress_algo_vel = 0;
9503 if(frame_set->tr_particle_data)
9505 for(i = frame_set->n_particle_data_blocks; i--; )
9507 if(frame_set->tr_particle_data[i].values)
9509 free(frame_set->tr_particle_data[i].values);
9510 frame_set->tr_particle_data[i].values = 0;
9513 if(frame_set->tr_particle_data[i].strings)
9515 n_values_per_frame = frame_set->tr_particle_data[i].
9516 n_values_per_frame;
9517 for(j = frame_set->tr_particle_data[i].n_frames; j--;)
9519 if(frame_set->tr_particle_data[i].strings[j])
9521 for(k = n_particles; k--;)
9523 if(frame_set->tr_particle_data[i].
9524 strings[j][k])
9526 for(l = n_values_per_frame; l--;)
9528 if(frame_set->tr_particle_data[i].
9529 strings[j][k][l])
9531 free(frame_set->tr_particle_data[i].
9532 strings[j][k][l]);
9533 frame_set->tr_particle_data[i].
9534 strings[j][k][l] = 0;
9537 free(frame_set->tr_particle_data[i].
9538 strings[j][k]);
9539 frame_set->tr_particle_data[i].
9540 strings[j][k] = 0;
9543 free(frame_set->tr_particle_data[i].strings[j]);
9544 frame_set->tr_particle_data[i].strings[j] = 0;
9547 free(frame_set->tr_particle_data[i].strings);
9548 frame_set->tr_particle_data[i].strings = 0;
9551 if(frame_set->tr_particle_data[i].block_name)
9553 free(frame_set->tr_particle_data[i].block_name);
9554 frame_set->tr_particle_data[i].block_name = 0;
9557 free(frame_set->tr_particle_data);
9558 frame_set->tr_particle_data = 0;
9561 if(frame_set->tr_data)
9563 for(i = frame_set->n_data_blocks; i--;)
9565 if(frame_set->tr_data[i].values)
9567 free(frame_set->tr_data[i].values);
9568 frame_set->tr_data[i].values = 0;
9571 if(frame_set->tr_data[i].strings)
9573 n_values_per_frame = frame_set->tr_data[i].
9574 n_values_per_frame;
9575 for(j = frame_set->tr_data[i].n_frames; j--;)
9577 if(frame_set->tr_data[i].strings[j])
9579 for(k = n_values_per_frame; k--;)
9581 if(frame_set->tr_data[i].strings[j][k])
9583 free(frame_set->tr_data[i].strings[j][k]);
9584 frame_set->tr_data[i].strings[j][k] = 0;
9587 free(frame_set->tr_data[i].strings[j]);
9588 frame_set->tr_data[i].strings[j] = 0;
9591 free(frame_set->tr_data[i].strings);
9592 frame_set->tr_data[i].strings = 0;
9595 if(frame_set->tr_data[i].block_name)
9597 free(frame_set->tr_data[i].block_name);
9598 frame_set->tr_data[i].block_name = 0;
9601 free(frame_set->tr_data);
9602 frame_set->tr_data = 0;
9605 frame_set->n_particle_data_blocks = 0;
9606 frame_set->n_data_blocks = 0;
9608 if(tng_data->molecules)
9610 for(i=tng_data->n_molecules; i--;)
9612 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9614 free(tng_data->molecules);
9615 tng_data->molecules = 0;
9616 tng_data->n_molecules = 0;
9618 if(tng_data->molecule_cnt_list)
9620 free(tng_data->molecule_cnt_list);
9621 tng_data->molecule_cnt_list = 0;
9624 free(*tng_data_p);
9625 *tng_data_p = 0;
9627 return(TNG_SUCCESS);
9630 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
9631 tng_trajectory_t *dest_p)
9633 tng_trajectory_frame_set_t frame_set;
9634 tng_trajectory_t dest;
9636 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9638 *dest_p = malloc(sizeof(struct tng_trajectory));
9639 if(!*dest_p)
9641 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9642 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9643 return(TNG_CRITICAL);
9646 dest = *dest_p;
9648 frame_set = &dest->current_trajectory_frame_set;
9650 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
9651 if(!dest->input_file_path)
9653 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
9654 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
9655 return(TNG_CRITICAL);
9657 strcpy(dest->input_file_path, src->input_file_path);
9658 dest->input_file = 0;
9659 dest->input_file_len = src->input_file_len;
9660 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
9661 if(!dest->output_file_path)
9663 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
9664 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
9665 return(TNG_CRITICAL);
9667 strcpy(dest->output_file_path, src->output_file_path);
9668 dest->output_file = 0;
9670 dest->first_program_name = 0;
9671 dest->first_user_name = 0;
9672 dest->first_computer_name = 0;
9673 dest->first_pgp_signature = 0;
9674 dest->last_program_name = 0;
9675 dest->last_user_name = 0;
9676 dest->last_computer_name = 0;
9677 dest->last_pgp_signature = 0;
9678 dest->forcefield_name = 0;
9680 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9681 dest->first_trajectory_frame_set_input_file_pos =
9682 src->first_trajectory_frame_set_input_file_pos;
9683 dest->last_trajectory_frame_set_input_file_pos =
9684 src->last_trajectory_frame_set_input_file_pos;
9685 dest->current_trajectory_frame_set_input_file_pos =
9686 src->current_trajectory_frame_set_input_file_pos;
9687 dest->first_trajectory_frame_set_output_file_pos =
9688 src->first_trajectory_frame_set_output_file_pos;
9689 dest->last_trajectory_frame_set_output_file_pos =
9690 src->last_trajectory_frame_set_output_file_pos;
9691 dest->current_trajectory_frame_set_output_file_pos =
9692 src->current_trajectory_frame_set_output_file_pos;
9693 dest->frame_set_n_frames = src->frame_set_n_frames;
9694 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9695 dest->n_trajectory_blocks = src->n_trajectory_blocks;
9696 dest->medium_stride_length = src->medium_stride_length;
9697 dest->long_stride_length = src->long_stride_length;
9699 dest->time_per_frame = src->time_per_frame;
9701 /* Currently the non trajectory data blocks are not copied since it
9702 * can lead to problems when freeing memory in a parallel block. */
9703 dest->n_particle_data_blocks = 0;
9704 dest->n_data_blocks = 0;
9705 dest->non_tr_particle_data = 0;
9706 dest->non_tr_data = 0;
9708 dest->compress_algo_pos = 0;
9709 dest->compress_algo_vel = 0;
9710 dest->distance_unit_exponential = -9;
9711 dest->compression_precision = 1000;
9713 frame_set->n_mapping_blocks = 0;
9714 frame_set->mappings = 0;
9715 frame_set->molecule_cnt_list = 0;
9717 frame_set->n_particle_data_blocks = 0;
9718 frame_set->n_data_blocks = 0;
9720 frame_set->tr_particle_data = 0;
9721 frame_set->tr_data = 0;
9723 frame_set->next_frame_set_file_pos = -1;
9724 frame_set->prev_frame_set_file_pos = -1;
9725 frame_set->medium_stride_next_frame_set_file_pos = -1;
9726 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9727 frame_set->long_stride_next_frame_set_file_pos = -1;
9728 frame_set->long_stride_prev_frame_set_file_pos = -1;
9729 frame_set->first_frame = -1;
9731 dest->n_molecules = 0;
9732 dest->molecules = 0;
9733 dest->molecule_cnt_list = 0;
9734 dest->n_particles = src->n_particles;
9736 dest->endianness_32 = src->endianness_32;
9737 dest->endianness_64 = src->endianness_64;
9738 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9739 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9740 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9741 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9743 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9744 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9745 dest->current_trajectory_frame_set.n_frames = 0;
9747 return(TNG_SUCCESS);
9750 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
9751 char *file_name, const int max_len)
9753 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9754 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9756 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9757 file_name[max_len - 1] = 0;
9759 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9761 return(TNG_FAILURE);
9763 return(TNG_SUCCESS);
9766 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
9767 const char *file_name)
9769 unsigned int len;
9770 char *temp;
9772 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9773 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9776 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9777 file_name) == 0)
9779 return(TNG_SUCCESS);
9782 if(tng_data->input_file)
9784 fclose(tng_data->input_file);
9787 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
9788 temp = realloc(tng_data->input_file_path, len);
9789 if(!temp)
9791 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9792 __FILE__, __LINE__);
9793 free(tng_data->input_file_path);
9794 tng_data->input_file_path = 0;
9795 return(TNG_CRITICAL);
9797 tng_data->input_file_path = temp;
9799 strncpy(tng_data->input_file_path, file_name, len);
9801 return(tng_input_file_init(tng_data));
9804 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
9805 char *file_name, const int max_len)
9807 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9808 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9810 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9811 file_name[max_len - 1] = 0;
9813 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9815 return(TNG_FAILURE);
9817 return(TNG_SUCCESS);
9820 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
9821 const char *file_name)
9823 int len;
9824 char *temp;
9826 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9827 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9829 if(tng_data->output_file_path &&
9830 strcmp(tng_data->output_file_path, file_name) == 0)
9832 return(TNG_SUCCESS);
9835 if(tng_data->output_file)
9837 fclose(tng_data->output_file);
9840 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
9841 temp = realloc(tng_data->output_file_path, len);
9842 if(!temp)
9844 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9845 __FILE__, __LINE__);
9846 free(tng_data->output_file_path);
9847 tng_data->output_file_path = 0;
9848 return(TNG_CRITICAL);
9850 tng_data->output_file_path = temp;
9852 strncpy(tng_data->output_file_path, file_name, len);
9854 return(tng_output_file_init(tng_data));
9857 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9858 (tng_trajectory_t tng_data,
9859 const char *file_name)
9861 int len;
9862 char *temp;
9864 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9865 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9867 if(tng_data->output_file_path &&
9868 strcmp(tng_data->output_file_path, file_name) == 0)
9870 return(TNG_SUCCESS);
9873 if(tng_data->output_file)
9875 fclose(tng_data->output_file);
9878 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
9879 temp = realloc(tng_data->output_file_path, len);
9880 if(!temp)
9882 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9883 __FILE__, __LINE__);
9884 free(tng_data->output_file_path);
9885 tng_data->output_file_path = 0;
9886 return(TNG_CRITICAL);
9888 tng_data->output_file_path = temp;
9890 strncpy(tng_data->output_file_path, file_name, len);
9892 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
9893 if(!tng_data->output_file)
9895 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9896 tng_data->output_file_path, __FILE__, __LINE__);
9897 return(TNG_CRITICAL);
9900 return(TNG_SUCCESS);
9903 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9904 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
9906 tng_endianness_32 end_32;
9907 tng_endianness_64 end_64;
9909 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9910 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9912 if(tng_data->output_endianness_swap_func_32)
9914 /* If other endianness variants are added they must be added here as well */
9915 if(tng_data->output_endianness_swap_func_32 ==
9916 &tng_swap_byte_order_big_endian_32)
9918 end_32 = TNG_BIG_ENDIAN_32;
9920 else if(tng_data->output_endianness_swap_func_32 ==
9921 &tng_swap_byte_order_little_endian_32)
9923 end_32 = TNG_LITTLE_ENDIAN_32;
9925 else
9927 return(TNG_FAILURE);
9930 else
9932 end_32 = (tng_endianness_32)tng_data->endianness_32;
9935 if(tng_data->output_endianness_swap_func_64)
9937 /* If other endianness variants are added they must be added here as well */
9938 if(tng_data->output_endianness_swap_func_64 ==
9939 &tng_swap_byte_order_big_endian_64)
9941 end_64 = TNG_BIG_ENDIAN_64;
9943 else if(tng_data->output_endianness_swap_func_64 ==
9944 &tng_swap_byte_order_little_endian_64)
9946 end_64 = TNG_LITTLE_ENDIAN_64;
9948 else
9950 return(TNG_FAILURE);
9953 else
9955 end_64 = (tng_endianness_64)tng_data->endianness_64;
9958 if((int)end_32 != (int)end_64)
9960 return(TNG_FAILURE);
9963 if(end_32 == TNG_LITTLE_ENDIAN_32)
9965 *endianness = TNG_LITTLE_ENDIAN;
9968 else if(end_32 == TNG_BIG_ENDIAN_32)
9970 *endianness = TNG_BIG_ENDIAN;
9972 else
9974 return(TNG_FAILURE);
9977 return(TNG_SUCCESS);
9980 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9981 (tng_trajectory_t tng_data,
9982 const tng_file_endianness endianness)
9984 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9986 /* Tne endianness cannot be changed if the data has already been written
9987 * to the output file. */
9988 if(ftell(tng_data->output_file) > 0)
9990 return(TNG_FAILURE);
9993 if(endianness == TNG_BIG_ENDIAN)
9995 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9997 tng_data->output_endianness_swap_func_32 = 0;
9999 else
10001 tng_data->output_endianness_swap_func_32 =
10002 &tng_swap_byte_order_big_endian_32;
10004 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10006 tng_data->output_endianness_swap_func_64 = 0;
10008 else
10010 tng_data->output_endianness_swap_func_64 =
10011 &tng_swap_byte_order_big_endian_64;
10013 return(TNG_SUCCESS);
10015 else if(endianness == TNG_LITTLE_ENDIAN)
10017 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10019 tng_data->output_endianness_swap_func_32 = 0;
10021 else
10023 tng_data->output_endianness_swap_func_32 =
10024 &tng_swap_byte_order_little_endian_32;
10026 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10028 tng_data->output_endianness_swap_func_64 = 0;
10030 else
10032 tng_data->output_endianness_swap_func_64 =
10033 &tng_swap_byte_order_little_endian_64;
10035 return(TNG_SUCCESS);
10038 /* If the specified endianness is neither big nor little endian return a
10039 * failure. */
10040 return(TNG_FAILURE);
10043 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10044 (const tng_trajectory_t tng_data,
10045 char *name, const int max_len)
10047 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10048 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10050 strncpy(name, tng_data->first_program_name, max_len - 1);
10051 name[max_len - 1] = 0;
10053 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10055 return(TNG_FAILURE);
10057 return(TNG_SUCCESS);
10060 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10061 const char *new_name)
10063 unsigned int len;
10065 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10066 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10068 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10070 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10072 free(tng_data->first_program_name);
10073 tng_data->first_program_name = 0;
10075 if(!tng_data->first_program_name)
10077 tng_data->first_program_name = malloc(len);
10078 if(!tng_data->first_program_name)
10080 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10081 __FILE__, __LINE__);
10082 return(TNG_CRITICAL);
10086 strncpy(tng_data->first_program_name, new_name, len);
10088 return(TNG_SUCCESS);
10091 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10092 (const tng_trajectory_t tng_data,
10093 char *name, const int max_len)
10095 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10096 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10098 strncpy(name, tng_data->last_program_name, max_len - 1);
10099 name[max_len - 1] = 0;
10101 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10103 return(TNG_FAILURE);
10105 return(TNG_SUCCESS);
10108 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10109 (tng_trajectory_t tng_data,
10110 const char *new_name)
10112 unsigned int len;
10114 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10115 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10117 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10119 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10121 free(tng_data->last_program_name);
10122 tng_data->last_program_name = 0;
10124 if(!tng_data->last_program_name)
10126 tng_data->last_program_name = malloc(len);
10127 if(!tng_data->last_program_name)
10129 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10130 __FILE__, __LINE__);
10131 return(TNG_CRITICAL);
10135 strncpy(tng_data->last_program_name, new_name, len);
10137 return(TNG_SUCCESS);
10140 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10141 (const tng_trajectory_t tng_data,
10142 char *name, const int max_len)
10144 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10145 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10147 strncpy(name, tng_data->first_user_name, max_len - 1);
10148 name[max_len - 1] = 0;
10150 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10152 return(TNG_FAILURE);
10154 return(TNG_SUCCESS);
10157 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10158 (tng_trajectory_t tng_data,
10159 const char *new_name)
10161 unsigned int len;
10163 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10164 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10166 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10168 /* If the currently stored string length is not enough to store the new
10169 * string it is freed and reallocated. */
10170 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10172 free(tng_data->first_user_name);
10173 tng_data->first_user_name = 0;
10175 if(!tng_data->first_user_name)
10177 tng_data->first_user_name = malloc(len);
10178 if(!tng_data->first_user_name)
10180 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10181 __FILE__, __LINE__);
10182 return(TNG_CRITICAL);
10186 strncpy(tng_data->first_user_name, new_name, len);
10188 return(TNG_SUCCESS);
10191 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10192 (const tng_trajectory_t tng_data,
10193 char *name, const int max_len)
10195 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10196 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10198 strncpy(name, tng_data->last_user_name, max_len - 1);
10199 name[max_len - 1] = 0;
10201 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10203 return(TNG_FAILURE);
10205 return(TNG_SUCCESS);
10208 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10209 (tng_trajectory_t tng_data,
10210 const char *new_name)
10212 unsigned int len;
10214 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10215 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10217 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10219 /* If the currently stored string length is not enough to store the new
10220 * string it is freed and reallocated. */
10221 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10223 free(tng_data->last_user_name);
10224 tng_data->last_user_name = 0;
10226 if(!tng_data->last_user_name)
10228 tng_data->last_user_name = malloc(len);
10229 if(!tng_data->last_user_name)
10231 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10232 __FILE__, __LINE__);
10233 return(TNG_CRITICAL);
10237 strncpy(tng_data->last_user_name, new_name, len);
10239 return(TNG_SUCCESS);
10242 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10243 (const tng_trajectory_t tng_data,
10244 char *name, const int max_len)
10246 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10247 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10249 strncpy(name, tng_data->first_computer_name, max_len - 1);
10250 name[max_len - 1] = 0;
10252 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10254 return(TNG_FAILURE);
10256 return(TNG_SUCCESS);
10259 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10260 (tng_trajectory_t tng_data,
10261 const char *new_name)
10263 unsigned int len;
10265 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10266 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10268 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10270 /* If the currently stored string length is not enough to store the new
10271 * string it is freed and reallocated. */
10272 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10274 free(tng_data->first_computer_name);
10275 tng_data->first_computer_name = 0;
10277 if(!tng_data->first_computer_name)
10279 tng_data->first_computer_name = malloc(len);
10280 if(!tng_data->first_computer_name)
10282 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10283 __FILE__, __LINE__);
10284 return(TNG_CRITICAL);
10288 strncpy(tng_data->first_computer_name, new_name, len);
10290 return(TNG_SUCCESS);
10293 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10294 (const tng_trajectory_t tng_data,
10295 char *name, const int max_len)
10297 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10298 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10300 strncpy(name, tng_data->last_computer_name, max_len - 1);
10301 name[max_len - 1] = 0;
10303 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10305 return(TNG_FAILURE);
10307 return(TNG_SUCCESS);
10310 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10311 (tng_trajectory_t tng_data,
10312 const char *new_name)
10314 unsigned int len;
10316 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10317 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10319 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10321 /* If the currently stored string length is not enough to store the new
10322 * string it is freed and reallocated. */
10323 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10324 len)
10326 free(tng_data->last_computer_name);
10327 tng_data->last_computer_name = 0;
10329 if(!tng_data->last_computer_name)
10331 tng_data->last_computer_name = malloc(len);
10332 if(!tng_data->last_computer_name)
10334 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10335 __FILE__, __LINE__);
10336 return(TNG_CRITICAL);
10340 strncpy(tng_data->last_computer_name, new_name, len);
10342 return(TNG_SUCCESS);
10345 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10346 (const tng_trajectory_t tng_data,
10347 char *signature, const int max_len)
10349 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10350 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10352 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
10353 signature[max_len - 1] = 0;
10355 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10357 return(TNG_FAILURE);
10359 return(TNG_SUCCESS);
10362 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10363 (tng_trajectory_t tng_data,
10364 const char *signature)
10366 unsigned int len;
10368 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10369 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10371 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10373 /* If the currently stored string length is not enough to store the new
10374 * string it is freed and reallocated. */
10375 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10376 len)
10378 free(tng_data->first_pgp_signature);
10379 tng_data->first_pgp_signature = 0;
10381 if(!tng_data->first_pgp_signature)
10383 tng_data->first_pgp_signature = malloc(len);
10384 if(!tng_data->first_pgp_signature)
10386 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10387 __FILE__, __LINE__);
10388 return(TNG_CRITICAL);
10392 strncpy(tng_data->first_pgp_signature, signature, len);
10394 return(TNG_SUCCESS);
10397 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10398 (const tng_trajectory_t tng_data,
10399 char *signature, const int max_len)
10401 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10402 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10404 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10405 signature[max_len - 1] = 0;
10407 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10409 return(TNG_FAILURE);
10411 return(TNG_SUCCESS);
10414 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10415 (tng_trajectory_t tng_data,
10416 const char *signature)
10418 unsigned int len;
10420 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10421 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10423 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10425 /* If the currently stored string length is not enough to store the new
10426 * string it is freed and reallocated. */
10427 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10428 len)
10430 free(tng_data->last_pgp_signature);
10431 tng_data->last_pgp_signature = 0;
10433 if(!tng_data->last_pgp_signature)
10435 tng_data->last_pgp_signature = malloc(len);
10436 if(!tng_data->last_pgp_signature)
10438 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10439 __FILE__, __LINE__);
10440 return(TNG_CRITICAL);
10444 strncpy(tng_data->last_pgp_signature, signature, len);
10446 return(TNG_SUCCESS);
10449 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10450 (const tng_trajectory_t tng_data,
10451 char *name, const int max_len)
10453 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10454 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10456 strncpy(name, tng_data->forcefield_name, max_len - 1);
10457 name[max_len - 1] = 0;
10459 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10461 return(TNG_FAILURE);
10463 return(TNG_SUCCESS);
10466 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10467 (tng_trajectory_t tng_data,
10468 const char *new_name)
10470 unsigned int len;
10472 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10473 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10475 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10477 /* If the currently stored string length is not enough to store the new
10478 * string it is freed and reallocated. */
10479 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10481 free(tng_data->forcefield_name);
10482 tng_data->forcefield_name = 0;
10484 if(!tng_data->forcefield_name)
10486 tng_data->forcefield_name = malloc(len);
10487 if(!tng_data->forcefield_name)
10489 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10490 __FILE__, __LINE__);
10491 return(TNG_CRITICAL);
10495 strncpy(tng_data->forcefield_name, new_name, len);
10497 return(TNG_SUCCESS);
10500 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10501 (const tng_trajectory_t tng_data,
10502 int64_t *len)
10504 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10505 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10507 *len = tng_data->medium_stride_length;
10509 return(TNG_SUCCESS);
10512 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10513 (tng_trajectory_t tng_data,
10514 const int64_t len)
10516 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10518 if(len >= tng_data->long_stride_length)
10520 return(TNG_FAILURE);
10522 tng_data->medium_stride_length = len;
10524 return(TNG_SUCCESS);
10527 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10528 (const tng_trajectory_t tng_data,
10529 int64_t *len)
10531 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10532 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10534 *len = tng_data->long_stride_length;
10536 return(TNG_SUCCESS);
10539 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10540 (tng_trajectory_t tng_data,
10541 const int64_t len)
10543 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10545 if(len <= tng_data->medium_stride_length)
10547 return(TNG_FAILURE);
10549 tng_data->long_stride_length = len;
10551 return(TNG_SUCCESS);
10554 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10555 (const tng_trajectory_t tng_data,
10556 double *time)
10558 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10559 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10561 *time = tng_data->time_per_frame;
10563 return(TNG_SUCCESS);
10566 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10567 (tng_trajectory_t tng_data,
10568 const double time)
10570 tng_trajectory_frame_set_t frame_set;
10572 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10573 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10575 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10577 return(TNG_SUCCESS);
10580 frame_set = &tng_data->current_trajectory_frame_set;
10582 /* If the current frame set is not finished write it to disk before
10583 changing time per frame. */
10584 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10586 frame_set->n_frames = frame_set->n_unwritten_frames;
10587 tng_frame_set_write(tng_data, TNG_USE_HASH);
10589 tng_data->time_per_frame = time;
10591 return(TNG_SUCCESS);
10594 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10595 (const tng_trajectory_t tng_data,
10596 int64_t *len)
10598 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10599 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10601 *len = tng_data->input_file_len;
10603 return(TNG_SUCCESS);
10606 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10607 (const tng_trajectory_t tng_data,
10608 int64_t *n)
10610 tng_gen_block_t block;
10611 tng_function_status stat;
10612 long file_pos;
10613 int64_t last_file_pos, first_frame, n_frames;
10615 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10616 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10617 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10619 file_pos = ftell(tng_data->input_file);
10620 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10622 if(last_file_pos <= 0)
10624 return(TNG_FAILURE);
10627 tng_block_init(&block);
10628 fseek(tng_data->input_file,
10629 (long)last_file_pos,
10630 SEEK_SET);
10631 /* Read block headers first to see that a frame set block is found. */
10632 stat = tng_block_header_read(tng_data, block);
10633 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10635 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
10636 __FILE__, __LINE__);
10637 tng_block_destroy(&block);
10638 return(TNG_FAILURE);
10640 tng_block_destroy(&block);
10642 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
10644 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
10645 __FILE__, __LINE__);
10646 return(TNG_CRITICAL);
10648 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
10650 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
10651 __FILE__, __LINE__);
10652 return(TNG_CRITICAL);
10654 fseek(tng_data->input_file, file_pos, SEEK_SET);
10656 *n = first_frame + n_frames;
10658 return(TNG_SUCCESS);
10661 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10662 (const tng_trajectory_t tng_data,
10663 double *precision)
10665 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10667 *precision = tng_data->compression_precision;
10669 return(TNG_SUCCESS);
10672 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10673 (tng_trajectory_t tng_data,
10674 const double precision)
10676 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10678 tng_data->compression_precision = precision;
10680 return(TNG_SUCCESS);
10683 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10684 (tng_trajectory_t tng_data,
10685 const int64_t n)
10687 tng_molecule_t mol;
10688 tng_chain_t chain;
10689 tng_residue_t res;
10690 tng_atom_t atom;
10691 tng_function_status stat;
10692 int64_t diff, n_mod, n_impl;
10694 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
10696 diff = n - tng_data->n_particles;
10698 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10699 if(stat == TNG_SUCCESS)
10701 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
10703 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10704 __FILE__, __LINE__);
10705 return(TNG_FAILURE);
10707 diff -= n_impl * mol->n_atoms;
10710 if(diff == 0)
10712 if(stat == TNG_SUCCESS)
10714 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10715 return(stat);
10717 return(TNG_SUCCESS);
10719 else if(diff < 0)
10721 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10722 fprintf(stderr, "particle count.\n");
10723 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10724 __FILE__, __LINE__);
10725 /* FIXME: Should we set the count of all other molecules to 0 and add
10726 * implicit molecules? */
10727 return(TNG_FAILURE);
10729 if(stat != TNG_SUCCESS)
10731 stat = tng_molecule_add(tng_data,
10732 "TNG_IMPLICIT_MOL",
10733 &mol);
10734 if(stat != TNG_SUCCESS)
10736 return(stat);
10738 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10739 if(stat != TNG_SUCCESS)
10741 return(stat);
10743 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10744 if(stat != TNG_SUCCESS)
10746 return(stat);
10748 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10749 if(stat != TNG_SUCCESS)
10751 return(stat);
10754 else
10756 if(mol->n_atoms > 1)
10758 n_mod = diff % mol->n_atoms;
10759 if(n_mod != 0)
10761 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10762 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10763 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10764 __FILE__, __LINE__);
10765 return(TNG_FAILURE);
10767 diff /= mol->n_atoms;
10770 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10772 return(stat);
10775 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10776 (const tng_trajectory_t tng_data,
10777 int64_t *n)
10779 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10780 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10782 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10784 *n = tng_data->n_particles;
10786 else
10788 *n = tng_data->current_trajectory_frame_set.n_particles;
10791 return(TNG_SUCCESS);
10794 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10795 (const tng_trajectory_t tng_data,
10796 char *variable)
10798 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10799 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10801 *variable = tng_data->var_num_atoms_flag;
10803 return(TNG_SUCCESS);
10806 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10807 (const tng_trajectory_t tng_data,
10808 int64_t *n)
10810 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10811 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10813 *n = tng_data->n_molecules;
10815 return(TNG_SUCCESS);
10818 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10819 (const tng_trajectory_t tng_data,
10820 int64_t *n)
10822 int64_t *cnt_list = 0, cnt = 0, i;
10824 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10825 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10827 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10829 if(!cnt_list)
10831 return(TNG_FAILURE);
10834 for(i = tng_data->n_molecules; i --;)
10836 cnt += cnt_list[i];
10839 *n = cnt;
10841 return(TNG_SUCCESS);
10844 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10845 (const tng_trajectory_t tng_data,
10846 int64_t **mol_cnt_list)
10848 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10850 if(tng_data->var_num_atoms_flag)
10852 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10853 molecule_cnt_list;
10855 else
10857 *mol_cnt_list = tng_data->molecule_cnt_list;
10859 if(*mol_cnt_list == 0)
10861 return(TNG_FAILURE);
10863 return(TNG_SUCCESS);
10866 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10867 (const tng_trajectory_t tng_data,
10868 int64_t *exp)
10870 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10871 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10873 *exp = tng_data->distance_unit_exponential;
10875 return(TNG_SUCCESS);
10878 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10879 (const tng_trajectory_t tng_data,
10880 const int64_t exp)
10882 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10884 tng_data->distance_unit_exponential = exp;
10886 return(TNG_SUCCESS);
10889 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10890 (const tng_trajectory_t tng_data,
10891 int64_t *n)
10893 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10894 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10896 *n = tng_data->frame_set_n_frames;
10898 return(TNG_SUCCESS);
10901 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10902 (const tng_trajectory_t tng_data,
10903 const int64_t n)
10905 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10907 tng_data->frame_set_n_frames = n;
10909 return(TNG_SUCCESS);
10912 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10913 (const tng_trajectory_t tng_data,
10914 int64_t *n)
10916 int64_t long_stride_length, medium_stride_length;
10917 long file_pos, orig_frame_set_file_pos;
10918 tng_trajectory_frame_set_t frame_set;
10919 struct tng_trajectory_frame_set orig_frame_set;
10920 tng_gen_block_t block;
10921 tng_function_status stat;
10922 int64_t cnt = 0;
10924 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10925 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10927 orig_frame_set = tng_data->current_trajectory_frame_set;
10929 frame_set = &tng_data->current_trajectory_frame_set;
10931 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10932 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
10934 tng_block_init(&block);
10935 fseek(tng_data->input_file,
10936 file_pos,
10937 SEEK_SET);
10938 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10939 /* Read block headers first to see what block is found. */
10940 stat = tng_block_header_read(tng_data, block);
10941 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10943 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n", file_pos,
10944 __FILE__, __LINE__);
10945 tng_block_destroy(&block);
10946 return(TNG_CRITICAL);
10949 if(tng_block_read_next(tng_data, block,
10950 TNG_SKIP_HASH) != TNG_SUCCESS)
10952 tng_block_destroy(&block);
10953 return(TNG_CRITICAL);
10956 ++cnt;
10958 long_stride_length = tng_data->long_stride_length;
10959 medium_stride_length = tng_data->medium_stride_length;
10961 /* Take long steps forward until a long step forward would be too long or
10962 * the last frame set is found */
10963 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
10964 while(file_pos > 0)
10966 if(file_pos > 0)
10968 cnt += long_stride_length;
10969 fseek(tng_data->input_file, file_pos, SEEK_SET);
10970 /* Read block headers first to see what block is found. */
10971 stat = tng_block_header_read(tng_data, block);
10972 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10974 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
10975 file_pos, __FILE__, __LINE__);
10976 tng_block_destroy(&block);
10977 return(TNG_CRITICAL);
10980 if(tng_block_read_next(tng_data, block,
10981 TNG_SKIP_HASH) != TNG_SUCCESS)
10983 tng_block_destroy(&block);
10984 return(TNG_CRITICAL);
10987 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
10990 /* Take medium steps forward until a medium step forward would be too long
10991 * or the last frame set is found */
10992 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
10993 while(file_pos > 0)
10995 if(file_pos > 0)
10997 cnt += medium_stride_length;
10998 fseek(tng_data->input_file,
10999 file_pos,
11000 SEEK_SET);
11001 /* Read block headers first to see what block is found. */
11002 stat = tng_block_header_read(tng_data, block);
11003 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11005 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11006 file_pos, __FILE__, __LINE__);
11007 tng_block_destroy(&block);
11008 return(TNG_CRITICAL);
11011 if(tng_block_read_next(tng_data, block,
11012 TNG_SKIP_HASH) != TNG_SUCCESS)
11014 tng_block_destroy(&block);
11015 return(TNG_CRITICAL);
11018 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11021 /* Take one step forward until the last frame set is found */
11022 file_pos = (long)frame_set->next_frame_set_file_pos;
11023 while(file_pos > 0)
11025 if(file_pos > 0)
11027 ++cnt;
11028 fseek(tng_data->input_file,
11029 file_pos,
11030 SEEK_SET);
11031 /* Read block headers first to see what block is found. */
11032 stat = tng_block_header_read(tng_data, block);
11033 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11035 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11036 file_pos, __FILE__, __LINE__);
11037 tng_block_destroy(&block);
11038 return(TNG_CRITICAL);
11041 if(tng_block_read_next(tng_data, block,
11042 TNG_SKIP_HASH) != TNG_SUCCESS)
11044 tng_block_destroy(&block);
11045 return(TNG_CRITICAL);
11048 file_pos = (long)frame_set->next_frame_set_file_pos;
11051 tng_block_destroy(&block);
11053 *n = tng_data->n_trajectory_frame_sets = cnt;
11055 *frame_set = orig_frame_set;
11057 fseek(tng_data->input_file,
11058 (long)tng_data->first_trajectory_frame_set_input_file_pos,
11059 SEEK_SET);
11061 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11063 return(TNG_SUCCESS);
11066 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11067 (const tng_trajectory_t tng_data,
11068 tng_trajectory_frame_set_t *frame_set_p)
11070 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11072 *frame_set_p = &tng_data->current_trajectory_frame_set;
11074 return(TNG_SUCCESS);
11077 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11078 (tng_trajectory_t tng_data,
11079 const int64_t nr)
11081 int64_t long_stride_length, medium_stride_length;
11082 int64_t file_pos, curr_nr = 0, n_frame_sets;
11083 tng_trajectory_frame_set_t frame_set;
11084 tng_gen_block_t block;
11085 tng_function_status stat;
11087 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11088 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11090 frame_set = &tng_data->current_trajectory_frame_set;
11092 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11094 if(stat != TNG_SUCCESS)
11096 return(stat);
11099 if(nr >= n_frame_sets)
11101 return(TNG_FAILURE);
11104 long_stride_length = tng_data->long_stride_length;
11105 medium_stride_length = tng_data->medium_stride_length;
11107 /* FIXME: The frame set number of the current frame set is not stored */
11109 if(nr < n_frame_sets - 1 - nr)
11111 /* Start from the beginning */
11112 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11114 else
11116 /* Start from the end */
11117 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11118 curr_nr = n_frame_sets - 1;
11120 if(file_pos <= 0)
11122 return(TNG_FAILURE);
11125 tng_block_init(&block);
11126 fseek(tng_data->input_file,
11127 (long)file_pos,
11128 SEEK_SET);
11129 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11130 /* Read block headers first to see what block is found. */
11131 stat = tng_block_header_read(tng_data, block);
11132 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11134 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11135 __FILE__, __LINE__);
11136 tng_block_destroy(&block);
11137 return(TNG_CRITICAL);
11140 if(tng_block_read_next(tng_data, block,
11141 TNG_SKIP_HASH) != TNG_SUCCESS)
11143 tng_block_destroy(&block);
11144 return(TNG_CRITICAL);
11147 if(curr_nr == nr)
11149 tng_block_destroy(&block);
11150 return(TNG_SUCCESS);
11153 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11155 /* Take long steps forward until a long step forward would be too long or
11156 * the right frame set is found */
11157 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11159 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11160 if(file_pos > 0)
11162 curr_nr += long_stride_length;
11163 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11164 /* Read block headers first to see what block is found. */
11165 stat = tng_block_header_read(tng_data, block);
11166 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11168 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11169 file_pos, __FILE__, __LINE__);
11170 tng_block_destroy(&block);
11171 return(TNG_CRITICAL);
11174 if(tng_block_read_next(tng_data, block,
11175 TNG_SKIP_HASH) != TNG_SUCCESS)
11177 tng_block_destroy(&block);
11178 return(TNG_CRITICAL);
11180 if(curr_nr == nr)
11182 tng_block_destroy(&block);
11183 return(TNG_SUCCESS);
11188 /* Take medium steps forward until a medium step forward would be too long
11189 * or the right frame set is found */
11190 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11192 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11193 if(file_pos > 0)
11195 curr_nr += medium_stride_length;
11196 fseek(tng_data->input_file,
11197 (long)file_pos,
11198 SEEK_SET);
11199 /* Read block headers first to see what block is found. */
11200 stat = tng_block_header_read(tng_data, block);
11201 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11203 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11204 file_pos, __FILE__, __LINE__);
11205 tng_block_destroy(&block);
11206 return(TNG_CRITICAL);
11209 if(tng_block_read_next(tng_data, block,
11210 TNG_SKIP_HASH) != TNG_SUCCESS)
11212 tng_block_destroy(&block);
11213 return(TNG_CRITICAL);
11215 if(curr_nr == nr)
11217 tng_block_destroy(&block);
11218 return(TNG_SUCCESS);
11223 /* Take one step forward until the right frame set is found */
11224 while(file_pos > 0 && curr_nr < nr)
11226 file_pos = frame_set->next_frame_set_file_pos;
11228 if(file_pos > 0)
11230 ++curr_nr;
11231 fseek(tng_data->input_file,
11232 (long)file_pos,
11233 SEEK_SET);
11234 /* Read block headers first to see what block is found. */
11235 stat = tng_block_header_read(tng_data, block);
11236 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11238 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11239 file_pos, __FILE__, __LINE__);
11240 tng_block_destroy(&block);
11241 return(TNG_CRITICAL);
11244 if(tng_block_read_next(tng_data, block,
11245 TNG_SKIP_HASH) != TNG_SUCCESS)
11247 tng_block_destroy(&block);
11248 return(TNG_CRITICAL);
11250 if(curr_nr == nr)
11252 tng_block_destroy(&block);
11253 return(TNG_SUCCESS);
11258 /* Take long steps backward until a long step backward would be too long
11259 * or the right frame set is found */
11260 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11262 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11263 if(file_pos > 0)
11265 curr_nr -= long_stride_length;
11266 fseek(tng_data->input_file,
11267 (long)file_pos,
11268 SEEK_SET);
11269 /* Read block headers first to see what block is found. */
11270 stat = tng_block_header_read(tng_data, block);
11271 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11273 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11274 file_pos, __FILE__, __LINE__);
11275 tng_block_destroy(&block);
11276 return(TNG_CRITICAL);
11279 if(tng_block_read_next(tng_data, block,
11280 TNG_SKIP_HASH) != TNG_SUCCESS)
11282 tng_block_destroy(&block);
11283 return(TNG_CRITICAL);
11285 if(curr_nr == nr)
11287 tng_block_destroy(&block);
11288 return(TNG_SUCCESS);
11293 /* Take medium steps backward until a medium step backward would be too long
11294 * or the right frame set is found */
11295 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11297 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11298 if(file_pos > 0)
11300 curr_nr -= medium_stride_length;
11301 fseek(tng_data->input_file,
11302 (long)file_pos,
11303 SEEK_SET);
11304 /* Read block headers first to see what block is found. */
11305 stat = tng_block_header_read(tng_data, block);
11306 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11308 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11309 file_pos, __FILE__, __LINE__);
11310 tng_block_destroy(&block);
11311 return(TNG_CRITICAL);
11314 if(tng_block_read_next(tng_data, block,
11315 TNG_SKIP_HASH) != TNG_SUCCESS)
11317 tng_block_destroy(&block);
11318 return(TNG_CRITICAL);
11320 if(curr_nr == nr)
11322 tng_block_destroy(&block);
11323 return(TNG_SUCCESS);
11328 /* Take one step backward until the right frame set is found */
11329 while(file_pos > 0 && curr_nr > nr)
11331 file_pos = frame_set->prev_frame_set_file_pos;
11332 if(file_pos > 0)
11334 --curr_nr;
11335 fseek(tng_data->input_file,
11336 (long)file_pos,
11337 SEEK_SET);
11338 /* Read block headers first to see what block is found. */
11339 stat = tng_block_header_read(tng_data, block);
11340 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11342 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11343 file_pos, __FILE__, __LINE__);
11344 tng_block_destroy(&block);
11345 return(TNG_CRITICAL);
11348 if(tng_block_read_next(tng_data, block,
11349 TNG_SKIP_HASH) != TNG_SUCCESS)
11351 tng_block_destroy(&block);
11352 return(TNG_CRITICAL);
11354 if(curr_nr == nr)
11356 tng_block_destroy(&block);
11357 return(TNG_SUCCESS);
11362 /* If for some reason the current frame set is not yet found,
11363 * take one step forward until the right frame set is found */
11364 while(file_pos > 0 && curr_nr < nr)
11366 file_pos = frame_set->next_frame_set_file_pos;
11367 if(file_pos > 0)
11369 ++curr_nr;
11370 fseek(tng_data->input_file,
11371 (long)file_pos,
11372 SEEK_SET);
11373 /* Read block headers first to see what block is found. */
11374 stat = tng_block_header_read(tng_data, block);
11375 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11377 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11378 file_pos, __FILE__, __LINE__);
11379 tng_block_destroy(&block);
11380 return(TNG_CRITICAL);
11383 if(tng_block_read_next(tng_data, block,
11384 TNG_SKIP_HASH) != TNG_SUCCESS)
11386 tng_block_destroy(&block);
11387 return(TNG_CRITICAL);
11389 if(curr_nr == nr)
11391 tng_block_destroy(&block);
11392 return(TNG_SUCCESS);
11397 tng_block_destroy(&block);
11398 return(TNG_FAILURE);
11401 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11402 (tng_trajectory_t tng_data,
11403 const int64_t frame)
11405 int64_t first_frame, last_frame, n_frames_per_frame_set;
11406 int64_t long_stride_length, medium_stride_length;
11407 int64_t file_pos, temp_frame, n_frames;
11408 tng_trajectory_frame_set_t frame_set;
11409 tng_gen_block_t block;
11410 tng_function_status stat;
11412 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11413 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11415 frame_set = &tng_data->current_trajectory_frame_set;
11417 tng_block_init(&block);
11419 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11421 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11422 fseek(tng_data->input_file,
11423 (long)file_pos,
11424 SEEK_SET);
11425 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11426 /* Read block headers first to see what block is found. */
11427 stat = tng_block_header_read(tng_data, block);
11428 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11430 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11431 file_pos, __FILE__, __LINE__);
11432 tng_block_destroy(&block);
11433 return(TNG_CRITICAL);
11436 if(tng_block_read_next(tng_data, block,
11437 TNG_SKIP_HASH) != TNG_SUCCESS)
11439 tng_block_destroy(&block);
11440 return(TNG_CRITICAL);
11444 first_frame = tng_max_i64(frame_set->first_frame, 0);
11445 last_frame = first_frame + frame_set->n_frames - 1;
11446 /* Is this the right frame set? */
11447 if(first_frame <= frame && frame <= last_frame)
11449 tng_block_destroy(&block);
11450 return(TNG_SUCCESS);
11453 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11454 long_stride_length = tng_data->long_stride_length;
11455 medium_stride_length = tng_data->medium_stride_length;
11457 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11458 TNG_SUCCESS)
11460 if(temp_frame - first_frame > n_frames_per_frame_set)
11462 n_frames_per_frame_set = temp_frame - first_frame;
11466 tng_num_frames_get(tng_data, &n_frames);
11468 if(frame >= n_frames)
11470 tng_block_destroy(&block);
11471 return(TNG_FAILURE);
11474 if(first_frame - frame >= frame ||
11475 frame - last_frame >
11476 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11478 /* Start from the beginning */
11479 if(first_frame - frame >= frame)
11481 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11483 if(file_pos <= 0)
11485 tng_block_destroy(&block);
11486 return(TNG_FAILURE);
11489 /* Start from the end */
11490 else if(frame - first_frame > (n_frames - 1) - frame)
11492 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11494 /* If the last frame set position is not set start from the current
11495 * frame set, since it will be closer than the first frame set. */
11497 /* Start from current */
11498 else
11500 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11503 if(file_pos > 0)
11505 fseek(tng_data->input_file,
11506 (long)file_pos,
11507 SEEK_SET);
11508 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11509 /* Read block headers first to see what block is found. */
11510 stat = tng_block_header_read(tng_data, block);
11511 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11513 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11514 file_pos, __FILE__, __LINE__);
11515 tng_block_destroy(&block);
11516 return(TNG_CRITICAL);
11519 if(tng_block_read_next(tng_data, block,
11520 TNG_SKIP_HASH) != TNG_SUCCESS)
11522 tng_block_destroy(&block);
11523 return(TNG_CRITICAL);
11528 first_frame = tng_max_i64(frame_set->first_frame, 0);
11529 last_frame = first_frame + frame_set->n_frames - 1;
11531 if(frame >= first_frame && frame <= last_frame)
11533 tng_block_destroy(&block);
11534 return(TNG_SUCCESS);
11537 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11539 /* Take long steps forward until a long step forward would be too long or
11540 * the right frame set is found */
11541 while(file_pos > 0 && first_frame + long_stride_length *
11542 n_frames_per_frame_set <= frame)
11544 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11545 if(file_pos > 0)
11547 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11548 /* Read block headers first to see what block is found. */
11549 stat = tng_block_header_read(tng_data, block);
11550 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11552 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11553 file_pos, __FILE__, __LINE__);
11554 tng_block_destroy(&block);
11555 return(TNG_CRITICAL);
11558 if(tng_block_read_next(tng_data, block,
11559 TNG_SKIP_HASH) != TNG_SUCCESS)
11561 tng_block_destroy(&block);
11562 return(TNG_CRITICAL);
11565 first_frame = tng_max_i64(frame_set->first_frame, 0);
11566 last_frame = first_frame + frame_set->n_frames - 1;
11567 if(frame >= first_frame && frame <= last_frame)
11569 tng_block_destroy(&block);
11570 return(TNG_SUCCESS);
11574 /* Take medium steps forward until a medium step forward would be too long
11575 * or the right frame set is found */
11576 while(file_pos > 0 && first_frame + medium_stride_length *
11577 n_frames_per_frame_set <= frame)
11579 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11580 if(file_pos > 0)
11582 fseek(tng_data->input_file,
11583 (long)file_pos,
11584 SEEK_SET);
11585 /* Read block headers first to see what block is found. */
11586 stat = tng_block_header_read(tng_data, block);
11587 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11589 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11590 file_pos, __FILE__, __LINE__);
11591 tng_block_destroy(&block);
11592 return(TNG_CRITICAL);
11595 if(tng_block_read_next(tng_data, block,
11596 TNG_SKIP_HASH) != TNG_SUCCESS)
11598 tng_block_destroy(&block);
11599 return(TNG_CRITICAL);
11602 first_frame = tng_max_i64(frame_set->first_frame, 0);
11603 last_frame = first_frame + frame_set->n_frames - 1;
11604 if(frame >= first_frame && frame <= last_frame)
11606 tng_block_destroy(&block);
11607 return(TNG_SUCCESS);
11611 /* Take one step forward until the right frame set is found */
11612 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11614 file_pos = frame_set->next_frame_set_file_pos;
11615 if(file_pos > 0)
11617 fseek(tng_data->input_file,
11618 (long)file_pos,
11619 SEEK_SET);
11620 /* Read block headers first to see what block is found. */
11621 stat = tng_block_header_read(tng_data, block);
11622 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11624 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11625 file_pos, __FILE__, __LINE__);
11626 tng_block_destroy(&block);
11627 return(TNG_CRITICAL);
11630 if(tng_block_read_next(tng_data, block,
11631 TNG_SKIP_HASH) != TNG_SUCCESS)
11633 tng_block_destroy(&block);
11634 return(TNG_CRITICAL);
11637 first_frame = tng_max_i64(frame_set->first_frame, 0);
11638 last_frame = first_frame + frame_set->n_frames - 1;
11639 if(frame >= first_frame && frame <= last_frame)
11641 tng_block_destroy(&block);
11642 return(TNG_SUCCESS);
11646 /* Take long steps backward until a long step backward would be too long
11647 * or the right frame set is found */
11648 while(file_pos > 0 && first_frame - long_stride_length *
11649 n_frames_per_frame_set >= frame)
11651 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11652 if(file_pos > 0)
11654 fseek(tng_data->input_file,
11655 (long)file_pos,
11656 SEEK_SET);
11657 /* Read block headers first to see what block is found. */
11658 stat = tng_block_header_read(tng_data, block);
11659 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11661 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11662 file_pos, __FILE__, __LINE__);
11663 tng_block_destroy(&block);
11664 return(TNG_CRITICAL);
11667 if(tng_block_read_next(tng_data, block,
11668 TNG_SKIP_HASH) != TNG_SUCCESS)
11670 tng_block_destroy(&block);
11671 return(TNG_CRITICAL);
11674 first_frame = tng_max_i64(frame_set->first_frame, 0);
11675 last_frame = first_frame + frame_set->n_frames - 1;
11676 if(frame >= first_frame && frame <= last_frame)
11678 tng_block_destroy(&block);
11679 return(TNG_SUCCESS);
11683 /* Take medium steps backward until a medium step backward would be too long
11684 * or the right frame set is found */
11685 while(file_pos > 0 && first_frame - medium_stride_length *
11686 n_frames_per_frame_set >= frame)
11688 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11689 if(file_pos > 0)
11691 fseek(tng_data->input_file,
11692 (long)file_pos,
11693 SEEK_SET);
11694 /* Read block headers first to see what block is found. */
11695 stat = tng_block_header_read(tng_data, block);
11696 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11698 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11699 file_pos, __FILE__, __LINE__);
11700 tng_block_destroy(&block);
11701 return(TNG_CRITICAL);
11704 if(tng_block_read_next(tng_data, block,
11705 TNG_SKIP_HASH) != TNG_SUCCESS)
11707 tng_block_destroy(&block);
11708 return(TNG_CRITICAL);
11711 first_frame = tng_max_i64(frame_set->first_frame, 0);
11712 last_frame = first_frame + frame_set->n_frames - 1;
11713 if(frame >= first_frame && frame <= last_frame)
11715 tng_block_destroy(&block);
11716 return(TNG_SUCCESS);
11720 /* Take one step backward until the right frame set is found */
11721 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11723 file_pos = frame_set->prev_frame_set_file_pos;
11724 if(file_pos > 0)
11726 fseek(tng_data->input_file,
11727 (long)file_pos,
11728 SEEK_SET);
11729 /* Read block headers first to see what block is found. */
11730 stat = tng_block_header_read(tng_data, block);
11731 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11733 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11734 file_pos, __FILE__, __LINE__);
11735 tng_block_destroy(&block);
11736 return(TNG_CRITICAL);
11739 if(tng_block_read_next(tng_data, block,
11740 TNG_SKIP_HASH) != TNG_SUCCESS)
11742 tng_block_destroy(&block);
11743 return(TNG_CRITICAL);
11746 first_frame = tng_max_i64(frame_set->first_frame, 0);
11747 last_frame = first_frame + frame_set->n_frames - 1;
11748 if(frame >= first_frame && frame <= last_frame)
11750 tng_block_destroy(&block);
11751 return(TNG_SUCCESS);
11755 /* If for some reason the current frame set is not yet found,
11756 * take one step forward until the right frame set is found */
11757 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11759 file_pos = frame_set->next_frame_set_file_pos;
11760 if(file_pos > 0)
11762 fseek(tng_data->input_file,
11763 (long)file_pos,
11764 SEEK_SET);
11765 /* Read block headers first to see what block is found. */
11766 stat = tng_block_header_read(tng_data, block);
11767 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11769 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11770 file_pos, __FILE__, __LINE__);
11771 tng_block_destroy(&block);
11772 return(TNG_CRITICAL);
11775 if(tng_block_read_next(tng_data, block,
11776 TNG_SKIP_HASH) != TNG_SUCCESS)
11778 tng_block_destroy(&block);
11779 return(TNG_CRITICAL);
11782 first_frame = tng_max_i64(frame_set->first_frame, 0);
11783 last_frame = first_frame + frame_set->n_frames - 1;
11784 if(frame >= first_frame && frame <= last_frame)
11786 tng_block_destroy(&block);
11787 return(TNG_SUCCESS);
11791 tng_block_destroy(&block);
11792 return(TNG_FAILURE);
11795 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11796 (const tng_trajectory_t tng_data,
11797 const tng_trajectory_frame_set_t frame_set,
11798 int64_t *pos)
11800 (void)tng_data;
11802 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11803 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11805 *pos = frame_set->next_frame_set_file_pos;
11807 return(TNG_SUCCESS);
11810 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11811 (const tng_trajectory_t tng_data,
11812 const tng_trajectory_frame_set_t frame_set,
11813 int64_t *pos)
11815 (void)tng_data;
11817 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11818 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11820 *pos = frame_set->prev_frame_set_file_pos;
11822 return(TNG_SUCCESS);
11825 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11826 (const tng_trajectory_t tng_data,
11827 const tng_trajectory_frame_set_t frame_set,
11828 int64_t *first_frame,
11829 int64_t *last_frame)
11831 (void)tng_data;
11833 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11834 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11835 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11837 *first_frame = frame_set->first_frame;
11838 *last_frame = *first_frame + frame_set->n_frames - 1;
11840 return(TNG_SUCCESS);
11843 /** Translate from the particle numbering used in a frame set to the real
11844 * particle numbering - used in the molecule description.
11845 * @param frame_set is the frame_set containing the mappings to use.
11846 * @param local is the index number of the atom in this frame set
11847 * @param real is set to the index of the atom in the molecular system.
11848 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11849 * cannot be found.
11851 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11852 (const tng_trajectory_frame_set_t frame_set,
11853 const int64_t local,
11854 int64_t *real)
11856 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11857 tng_particle_mapping_t mapping;
11858 if(n_blocks <= 0)
11860 *real = local;
11861 return(TNG_SUCCESS);
11863 for(i = 0; i < n_blocks; i++)
11865 mapping = &frame_set->mappings[i];
11866 first = mapping->num_first_particle;
11867 if(local < first ||
11868 local >= first + mapping->n_particles)
11870 continue;
11872 *real = mapping->real_particle_numbers[local-first];
11873 return(TNG_SUCCESS);
11875 *real = local;
11876 return(TNG_FAILURE);
11879 /** Translate from the real particle numbering to the particle numbering
11880 * used in a frame set.
11881 * @param frame_set is the frame_set containing the mappings to use.
11882 * @param real is the index number of the atom in the molecular system.
11883 * @param local is set to the index of the atom in this frame set.
11884 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11885 * cannot be found.
11887 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11888 (const tng_trajectory_frame_set_t frame_set,
11889 const int64_t real,
11890 int64_t *local)
11892 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11893 tng_particle_mapping_t mapping;
11894 if(n_blocks <= 0)
11896 *local = real;
11897 return(TNG_SUCCESS);
11899 for(i = 0; i < n_blocks; i++)
11901 mapping = &frame_set->mappings[i];
11902 for(j = mapping->n_particles; j--;)
11904 if(mapping->real_particle_numbers[j] == real)
11906 *local = j;
11907 return(TNG_SUCCESS);
11911 return(TNG_FAILURE);
11915 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11916 (tng_trajectory_t tng_data,
11917 const char hash_mode)
11919 int cnt = 0, prev_pos = 0;
11920 tng_gen_block_t block;
11922 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11924 tng_data->n_trajectory_frame_sets = 0;
11926 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11928 return(TNG_CRITICAL);
11931 if(!tng_data->input_file_len)
11933 fseek(tng_data->input_file, 0, SEEK_END);
11934 tng_data->input_file_len = ftell(tng_data->input_file);
11935 fseek(tng_data->input_file, 0, SEEK_SET);
11938 tng_block_init(&block);
11939 /* Non trajectory blocks (they come before the trajectory
11940 * blocks in the file) */
11941 while (prev_pos < tng_data->input_file_len &&
11942 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11943 block->id != -1 &&
11944 block->id != TNG_TRAJECTORY_FRAME_SET)
11946 if(tng_block_read_next(tng_data, block,
11947 hash_mode) == TNG_SUCCESS)
11949 cnt++;
11951 prev_pos = ftell(tng_data->input_file);
11954 /* Go back if a trajectory block was encountered */
11955 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11957 fseek(tng_data->input_file, prev_pos, SEEK_SET);
11960 tng_block_destroy(&block);
11962 return(TNG_SUCCESS);
11965 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11966 (tng_trajectory_t tng_data,
11967 const char hash_mode)
11969 int i;
11970 tng_gen_block_t data_block;
11972 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11974 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11976 return(TNG_CRITICAL);
11979 /* TODO: If there is already frame set data written to this file (e.g. when
11980 * appending to an already existing file we might need to move frame sets to
11981 * the end of the file. */
11983 if(tng_general_info_block_write(tng_data, hash_mode)
11984 != TNG_SUCCESS)
11986 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11987 tng_data->input_file_path, __FILE__, __LINE__);
11988 return(TNG_CRITICAL);
11991 if(tng_molecules_block_write(tng_data, hash_mode)
11992 != TNG_SUCCESS)
11994 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11995 tng_data->input_file_path, __FILE__, __LINE__);
11996 return(TNG_CRITICAL);
11999 /* FIXME: Currently writing non-trajectory data blocks here.
12000 * Should perhaps be moved. */
12001 tng_block_init(&data_block);
12002 for(i = 0; i < tng_data->n_data_blocks; i++)
12004 data_block->id = tng_data->non_tr_data[i].block_id;
12005 tng_data_block_write(tng_data, data_block,
12006 i, hash_mode);
12009 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12011 data_block->id = tng_data->non_tr_particle_data[i].block_id;
12012 tng_particle_data_block_write(tng_data, data_block,
12013 i, 0, hash_mode);
12016 tng_block_destroy(&data_block);
12018 return(TNG_SUCCESS);
12021 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12022 tng_gen_block_t block,
12023 const char hash_mode)
12025 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12026 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12028 switch(block->id)
12030 case TNG_TRAJECTORY_FRAME_SET:
12031 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12032 case TNG_PARTICLE_MAPPING:
12033 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12034 case TNG_GENERAL_INFO:
12035 return(tng_general_info_block_read(tng_data, block, hash_mode));
12036 case TNG_MOLECULES:
12037 return(tng_molecules_block_read(tng_data, block, hash_mode));
12038 default:
12039 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12041 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12043 else
12045 /* Skip to the next block */
12046 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12047 return(TNG_FAILURE);
12052 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12053 (tng_trajectory_t tng_data,
12054 const char hash_mode)
12056 long file_pos;
12057 tng_gen_block_t block;
12058 tng_function_status stat;
12060 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12062 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12064 return(TNG_CRITICAL);
12067 file_pos = ftell(tng_data->input_file);
12069 tng_block_init(&block);
12071 if(!tng_data->input_file_len)
12073 fseek(tng_data->input_file, 0, SEEK_END);
12074 tng_data->input_file_len = ftell(tng_data->input_file);
12075 fseek(tng_data->input_file, file_pos, SEEK_SET);
12078 /* Read block headers first to see what block is found. */
12079 stat = tng_block_header_read(tng_data, block);
12080 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12082 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12083 file_pos, __FILE__, __LINE__);
12084 tng_block_destroy(&block);
12085 return(TNG_CRITICAL);
12088 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12090 if(tng_block_read_next(tng_data, block,
12091 hash_mode) == TNG_SUCCESS)
12093 tng_data->n_trajectory_frame_sets++;
12094 file_pos = ftell(tng_data->input_file);
12095 /* Read all blocks until next frame set block */
12096 stat = tng_block_header_read(tng_data, block);
12097 while(file_pos < tng_data->input_file_len &&
12098 stat != TNG_CRITICAL &&
12099 block->id != TNG_TRAJECTORY_FRAME_SET)
12101 stat = tng_block_read_next(tng_data, block,
12102 hash_mode);
12103 if(stat != TNG_CRITICAL)
12105 file_pos = ftell(tng_data->input_file);
12106 if(file_pos < tng_data->input_file_len)
12108 stat = tng_block_header_read(tng_data, block);
12112 if(stat == TNG_CRITICAL)
12114 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12115 file_pos, __FILE__, __LINE__);
12116 tng_block_destroy(&block);
12117 return(stat);
12120 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12122 fseek(tng_data->input_file, file_pos, SEEK_SET);
12126 tng_block_destroy(&block);
12128 return(TNG_SUCCESS);
12132 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12133 (tng_trajectory_t tng_data,
12134 const char hash_mode,
12135 const int64_t block_id)
12137 long file_pos;
12138 tng_gen_block_t block;
12139 tng_function_status stat;
12140 int found_flag = 1;
12142 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12144 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12146 return(TNG_CRITICAL);
12149 file_pos = (long)tng_data->current_trajectory_frame_set_input_file_pos;
12151 if(file_pos < 0)
12153 /* No current frame set. This means that the first frame set must be
12154 * read */
12155 found_flag = 0;
12156 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12159 if(file_pos > 0)
12161 fseek(tng_data->input_file,
12162 file_pos,
12163 SEEK_SET);
12165 else
12167 return(TNG_FAILURE);
12170 tng_block_init(&block);
12172 if(!tng_data->input_file_len)
12174 fseek(tng_data->input_file, 0, SEEK_END);
12175 tng_data->input_file_len = ftell(tng_data->input_file);
12176 fseek(tng_data->input_file, file_pos, SEEK_SET);
12179 /* Read block headers first to see what block is found. */
12180 stat = tng_block_header_read(tng_data, block);
12181 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12183 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12184 file_pos, __FILE__, __LINE__);
12185 tng_block_destroy(&block);
12186 return(TNG_CRITICAL);
12188 /* If the current frame set had already been read skip its block contents */
12189 if(found_flag)
12191 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12193 /* Otherwiese read the frame set block */
12194 else
12196 stat = tng_block_read_next(tng_data, block,
12197 hash_mode);
12198 if(stat != TNG_SUCCESS)
12200 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12201 tng_block_destroy(&block);
12202 return(stat);
12205 file_pos = ftell(tng_data->input_file);
12207 found_flag = 0;
12209 /* Read only blocks of the requested ID
12210 * until next frame set block */
12211 stat = tng_block_header_read(tng_data, block);
12212 while(file_pos < tng_data->input_file_len &&
12213 stat != TNG_CRITICAL &&
12214 block->id != TNG_TRAJECTORY_FRAME_SET)
12216 if(block->id == block_id)
12218 stat = tng_block_read_next(tng_data, block,
12219 hash_mode);
12220 if(stat != TNG_CRITICAL)
12222 file_pos = ftell(tng_data->input_file);
12223 found_flag = 1;
12224 if(file_pos < tng_data->input_file_len)
12226 stat = tng_block_header_read(tng_data, block);
12230 else
12232 file_pos += (long)(block->block_contents_size + block->header_contents_size);
12233 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12234 if(file_pos < tng_data->input_file_len)
12236 stat = tng_block_header_read(tng_data, block);
12240 if(stat == TNG_CRITICAL)
12242 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12243 file_pos, __FILE__, __LINE__);
12244 tng_block_destroy(&block);
12245 return(stat);
12248 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12250 fseek(tng_data->input_file, file_pos, SEEK_SET);
12253 tng_block_destroy(&block);
12255 if(found_flag)
12257 return(TNG_SUCCESS);
12259 else
12261 return(TNG_FAILURE);
12265 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12266 (tng_trajectory_t tng_data,
12267 const char hash_mode)
12269 long file_pos;
12271 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12273 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12275 return(TNG_CRITICAL);
12278 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12280 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12282 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12285 if(file_pos > 0)
12287 fseek(tng_data->input_file,
12288 file_pos,
12289 SEEK_SET);
12291 else
12293 return(TNG_FAILURE);
12296 return(tng_frame_set_read(tng_data, hash_mode));
12299 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12300 (tng_trajectory_t tng_data,
12301 const char hash_mode,
12302 const int64_t block_id)
12304 long file_pos;
12305 tng_gen_block_t block;
12306 tng_function_status stat;
12308 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12310 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12312 return(TNG_CRITICAL);
12315 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12317 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12319 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12322 if(file_pos > 0)
12324 fseek(tng_data->input_file,
12325 file_pos,
12326 SEEK_SET);
12328 else
12330 return(TNG_FAILURE);
12333 tng_block_init(&block);
12335 if(!tng_data->input_file_len)
12337 fseek(tng_data->input_file, 0, SEEK_END);
12338 tng_data->input_file_len = ftell(tng_data->input_file);
12339 fseek(tng_data->input_file, file_pos, SEEK_SET);
12342 /* Read block headers first to see what block is found. */
12343 stat = tng_block_header_read(tng_data, block);
12344 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12346 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12347 file_pos, __FILE__, __LINE__);
12348 tng_block_destroy(&block);
12349 return(TNG_CRITICAL);
12352 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12354 if(tng_block_read_next(tng_data, block,
12355 hash_mode) == TNG_SUCCESS)
12357 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12360 tng_block_destroy(&block);
12362 return(stat);
12365 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
12366 const char hash_mode)
12368 int i, j;
12369 tng_gen_block_t block;
12370 tng_trajectory_frame_set_t frame_set;
12371 tng_function_status stat;
12373 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12375 frame_set = &tng_data->current_trajectory_frame_set;
12377 if(frame_set->n_written_frames == frame_set->n_frames)
12379 return(TNG_SUCCESS);
12382 tng_data->current_trajectory_frame_set_output_file_pos =
12383 ftell(tng_data->output_file);
12384 tng_data->last_trajectory_frame_set_output_file_pos =
12385 tng_data->current_trajectory_frame_set_output_file_pos;
12387 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12389 return(TNG_FAILURE);
12392 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12394 tng_data->first_trajectory_frame_set_output_file_pos =
12395 tng_data->current_trajectory_frame_set_output_file_pos;
12398 tng_block_init(&block);
12400 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12402 tng_block_destroy(&block);
12403 return(TNG_FAILURE);
12406 /* Write non-particle data blocks */
12407 for(i = 0; i<frame_set->n_data_blocks; i++)
12409 block->id = frame_set->tr_data[i].block_id;
12410 tng_data_block_write(tng_data, block, i, hash_mode);
12412 /* Write the mapping blocks and particle data blocks*/
12413 if(frame_set->n_mapping_blocks)
12415 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12417 block->id = TNG_PARTICLE_MAPPING;
12418 if(frame_set->mappings[i].n_particles > 0)
12420 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12421 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12423 block->id = frame_set->tr_particle_data[j].block_id;
12424 tng_particle_data_block_write(tng_data, block,
12425 j, &frame_set->mappings[i],
12426 hash_mode);
12431 else
12433 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12435 block->id = frame_set->tr_particle_data[i].block_id;
12436 tng_particle_data_block_write(tng_data, block,
12437 i, 0, hash_mode);
12442 /* Update pointers in the general info block */
12443 stat = tng_header_pointers_update(tng_data, hash_mode);
12445 if(stat == TNG_SUCCESS)
12447 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12450 tng_block_destroy(&block);
12452 frame_set->n_unwritten_frames = 0;
12454 fflush(tng_data->output_file);
12456 return(stat);
12459 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12460 (tng_trajectory_t tng_data,
12461 const char hash_mode)
12463 tng_trajectory_frame_set_t frame_set;
12465 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12467 frame_set = &tng_data->current_trajectory_frame_set;
12469 if(frame_set->n_unwritten_frames == 0)
12471 return(TNG_SUCCESS);
12473 frame_set->n_frames = frame_set->n_unwritten_frames;
12475 return(tng_frame_set_write(tng_data, hash_mode));
12478 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12479 (tng_trajectory_t tng_data,
12480 const int64_t first_frame,
12481 const int64_t n_frames)
12483 tng_gen_block_t block;
12484 tng_trajectory_frame_set_t frame_set;
12485 FILE *temp = tng_data->input_file;
12486 int64_t curr_pos;
12488 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12489 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12490 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12492 frame_set = &tng_data->current_trajectory_frame_set;
12494 curr_pos = ftell(tng_data->output_file);
12496 if(curr_pos <= 10)
12498 tng_file_headers_write(tng_data, TNG_USE_HASH);
12501 /* Set pointer to previous frame set to the one that was loaded
12502 * before.
12503 * FIXME: This is a bit risky. If they are not added in order
12504 * it will be wrong. */
12505 if(tng_data->n_trajectory_frame_sets)
12507 frame_set->prev_frame_set_file_pos =
12508 tng_data->current_trajectory_frame_set_output_file_pos;
12511 tng_data->current_trajectory_frame_set_output_file_pos =
12512 ftell(tng_data->output_file);
12514 tng_data->n_trajectory_frame_sets++;
12516 /* Set the medium range pointers */
12517 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12519 frame_set->medium_stride_prev_frame_set_file_pos =
12520 tng_data->first_trajectory_frame_set_output_file_pos;
12522 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12524 /* FIXME: Currently only working if the previous frame set has its
12525 * medium stride pointer already set. This might need some fixing. */
12526 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12527 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12529 tng_block_init(&block);
12530 tng_data->input_file = tng_data->output_file;
12532 curr_pos = ftell(tng_data->output_file);
12533 fseek(tng_data->output_file,
12534 (long)frame_set->medium_stride_prev_frame_set_file_pos,
12535 SEEK_SET);
12537 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12539 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12540 __FILE__, __LINE__);
12541 tng_data->input_file = temp;
12542 tng_block_destroy(&block);
12543 return(TNG_CRITICAL);
12546 /* Read the next frame set from the previous frame set and one
12547 * medium stride step back */
12548 fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
12549 sizeof(int64_t), SEEK_CUR);
12550 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12551 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12552 1, tng_data->output_file) == 0)
12554 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12555 tng_data->input_file = temp;
12556 tng_block_destroy(&block);
12557 return(TNG_CRITICAL);
12560 if(tng_data->input_endianness_swap_func_64)
12562 if(tng_data->input_endianness_swap_func_64(tng_data,
12563 &frame_set->medium_stride_prev_frame_set_file_pos)
12564 != TNG_SUCCESS)
12566 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12567 __FILE__, __LINE__);
12571 tng_block_destroy(&block);
12573 /* Set the long range pointers */
12574 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12576 frame_set->long_stride_prev_frame_set_file_pos =
12577 tng_data->first_trajectory_frame_set_output_file_pos;
12579 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12581 /* FIXME: Currently only working if the previous frame set has its
12582 * long stride pointer already set. This might need some fixing. */
12583 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12584 frame_set->long_stride_prev_frame_set_file_pos != 0)
12586 tng_block_init(&block);
12587 tng_data->input_file = tng_data->output_file;
12589 fseek(tng_data->output_file,
12590 (long)frame_set->long_stride_prev_frame_set_file_pos,
12591 SEEK_SET);
12593 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12595 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12596 __FILE__, __LINE__);
12597 tng_data->input_file = temp;
12598 tng_block_destroy(&block);
12599 return(TNG_CRITICAL);
12602 /* Read the next frame set from the previous frame set and one
12603 * long stride step back */
12604 fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
12605 sizeof(int64_t), SEEK_CUR);
12607 tng_block_destroy(&block);
12609 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12610 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12611 1, tng_data->output_file) == 0)
12613 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12614 tng_data->input_file = temp;
12615 return(TNG_CRITICAL);
12618 if(tng_data->input_endianness_swap_func_64)
12620 if(tng_data->input_endianness_swap_func_64(tng_data,
12621 &frame_set->long_stride_prev_frame_set_file_pos)
12622 != TNG_SUCCESS)
12624 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12625 __FILE__, __LINE__);
12632 tng_data->input_file = temp;
12633 fseek(tng_data->output_file, (long)curr_pos, SEEK_SET);
12637 frame_set->first_frame = first_frame;
12638 frame_set->n_frames = n_frames;
12639 frame_set->n_written_frames = 0;
12640 frame_set->n_unwritten_frames = 0;
12641 frame_set->first_frame_time = -1;
12643 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12644 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12646 tng_data->first_trajectory_frame_set_output_file_pos =
12647 tng_data->current_trajectory_frame_set_output_file_pos;
12649 /* FIXME: Should check the frame number instead of the file_pos,
12650 * in case frame sets are not in order */
12651 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12652 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12653 tng_data->last_trajectory_frame_set_output_file_pos <
12654 tng_data->current_trajectory_frame_set_output_file_pos)
12656 tng_data->last_trajectory_frame_set_output_file_pos =
12657 tng_data->current_trajectory_frame_set_output_file_pos;
12660 return(TNG_SUCCESS);
12663 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12664 (tng_trajectory_t tng_data,
12665 const int64_t first_frame,
12666 const int64_t n_frames,
12667 const double first_frame_time)
12669 tng_function_status stat;
12671 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12672 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12673 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12674 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12677 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12678 if(stat != TNG_SUCCESS)
12680 return(stat);
12682 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12684 return(stat);
12687 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12688 (tng_trajectory_t tng_data,
12689 const double first_frame_time)
12691 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12692 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12694 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12696 return(TNG_SUCCESS);
12699 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12700 (const tng_trajectory_t tng_data,
12701 int64_t *frame)
12703 long file_pos, next_frame_set_file_pos;
12704 tng_gen_block_t block;
12705 tng_function_status stat;
12707 tng_trajectory_frame_set_t frame_set;
12709 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12710 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12711 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12713 file_pos = ftell(tng_data->input_file);
12715 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12717 next_frame_set_file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12719 else
12721 frame_set = &tng_data->current_trajectory_frame_set;
12722 next_frame_set_file_pos = (long)frame_set->next_frame_set_file_pos;
12725 if(next_frame_set_file_pos <= 0)
12727 return(TNG_FAILURE);
12730 fseek(tng_data->input_file, (long)next_frame_set_file_pos, SEEK_SET);
12731 /* Read block headers first to see that a frame set block is found. */
12732 tng_block_init(&block);
12733 stat = tng_block_header_read(tng_data, block);
12734 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12736 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12737 file_pos, __FILE__, __LINE__);
12738 return(TNG_CRITICAL);
12740 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12742 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12744 tng_block_destroy(&block);
12746 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12748 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12749 __FILE__, __LINE__);
12750 return(TNG_CRITICAL);
12752 fseek(tng_data->input_file, file_pos, SEEK_SET);
12754 return(TNG_SUCCESS);
12757 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12758 (tng_trajectory_t tng_data,
12759 const int64_t id,
12760 const char *block_name,
12761 const char datatype,
12762 const char block_type_flag,
12763 int64_t n_frames,
12764 const int64_t n_values_per_frame,
12765 int64_t stride_length,
12766 const int64_t codec_id,
12767 void *new_data)
12769 int i, j, size, len;
12770 tng_trajectory_frame_set_t frame_set;
12771 tng_non_particle_data_t data;
12772 char **first_dim_values;
12773 char *new_data_c=new_data;
12774 int64_t n_frames_div;
12776 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12777 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12778 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12780 frame_set = &tng_data->current_trajectory_frame_set;
12782 if(stride_length <= 0)
12784 stride_length = 1;
12787 /* If the block does not exist, create it */
12788 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
12790 if(tng_data_block_create(tng_data, block_type_flag) !=
12791 TNG_SUCCESS)
12793 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
12794 __FILE__, __LINE__);
12795 return(TNG_CRITICAL);
12797 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12799 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12801 else
12803 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12805 data->block_id = id;
12807 data->block_name = malloc(strlen(block_name) + 1);
12808 if(!data->block_name)
12810 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12811 (int)strlen(block_name)+1, __FILE__, __LINE__);
12812 return(TNG_CRITICAL);
12814 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12816 data->values = 0;
12817 /* FIXME: Memory leak from strings. */
12818 data->strings = 0;
12819 data->last_retrieved_frame = -1;
12822 data->datatype = datatype;
12823 data->stride_length = tng_max_i64(stride_length, 1);
12824 data->n_values_per_frame = n_values_per_frame;
12825 data->n_frames = n_frames;
12826 data->codec_id = codec_id;
12827 data->compression_multiplier = 1.0;
12828 /* FIXME: This can cause problems. */
12829 data->first_frame_with_data = frame_set->first_frame;
12831 switch(datatype)
12833 case TNG_FLOAT_DATA:
12834 size = sizeof(float);
12835 break;
12836 case TNG_INT_DATA:
12837 size = sizeof(int64_t);
12838 break;
12839 case TNG_DOUBLE_DATA:
12840 default:
12841 size = sizeof(double);
12842 break;
12845 if(new_data_c)
12847 /* Allocate memory */
12848 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12849 n_values_per_frame) !=
12850 TNG_SUCCESS)
12852 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
12853 __FILE__, __LINE__);
12854 return(TNG_CRITICAL);
12857 if(n_frames > frame_set->n_unwritten_frames)
12859 frame_set->n_unwritten_frames = n_frames;
12862 n_frames_div = (n_frames % stride_length) ?
12863 n_frames / stride_length + 1:
12864 n_frames / stride_length;
12866 if(datatype == TNG_CHAR_DATA)
12868 for(i = 0; i < n_frames_div; i++)
12870 first_dim_values = data->strings[i];
12871 for(j = 0; j < n_values_per_frame; j++)
12873 len = tng_min_i((int)strlen(new_data_c) + 1,
12874 TNG_MAX_STR_LEN);
12875 if(first_dim_values[j])
12877 free(first_dim_values[j]);
12879 first_dim_values[j] = malloc(len);
12880 if(!first_dim_values[j])
12882 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12883 len, __FILE__, __LINE__);
12884 return(TNG_CRITICAL);
12886 strncpy(first_dim_values[j],
12887 new_data_c, len);
12888 new_data_c += len;
12892 else
12894 memcpy(data->values, new_data, size * n_frames_div *
12895 n_values_per_frame);
12899 return(TNG_SUCCESS);
12902 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12903 (tng_trajectory_t tng_data,
12904 const int64_t id,
12905 const char *block_name,
12906 const char datatype,
12907 const char block_type_flag,
12908 int64_t n_frames,
12909 const int64_t n_values_per_frame,
12910 int64_t stride_length,
12911 const int64_t num_first_particle,
12912 const int64_t n_particles,
12913 const int64_t codec_id,
12914 void *new_data)
12916 int i, size, len;
12917 int64_t j, k;
12918 int64_t tot_n_particles, n_frames_div;
12919 char ***first_dim_values, **second_dim_values;
12920 tng_trajectory_frame_set_t frame_set;
12921 tng_particle_data_t data;
12922 char *new_data_c=new_data;
12924 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12925 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12926 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12927 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12928 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12931 frame_set = &tng_data->current_trajectory_frame_set;
12933 if(stride_length <= 0)
12935 stride_length = 1;
12938 /* If the block does not exist, create it */
12939 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
12941 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
12942 TNG_SUCCESS)
12944 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12945 __FILE__, __LINE__);
12946 return(TNG_CRITICAL);
12948 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12950 data = &frame_set->tr_particle_data[frame_set->
12951 n_particle_data_blocks - 1];
12953 else
12955 data = &tng_data->non_tr_particle_data[tng_data->
12956 n_particle_data_blocks - 1];
12958 data->block_id = id;
12960 data->block_name = malloc(strlen(block_name) + 1);
12961 if(!data->block_name)
12963 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12964 (int)strlen(block_name)+1, __FILE__, __LINE__);
12965 return(TNG_CRITICAL);
12967 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12969 data->datatype = datatype;
12971 data->values = 0;
12972 /* FIXME: Memory leak from strings. */
12973 data->strings = 0;
12974 data->last_retrieved_frame = -1;
12977 data->stride_length = tng_max_i64(stride_length, 1);
12978 data->n_values_per_frame = n_values_per_frame;
12979 data->n_frames = n_frames;
12980 data->codec_id = codec_id;
12981 data->compression_multiplier = 1.0;
12982 /* FIXME: This can cause problems. */
12983 data->first_frame_with_data = frame_set->first_frame;
12985 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12987 tot_n_particles = frame_set->n_particles;
12989 else
12991 tot_n_particles = tng_data->n_particles;
12994 /* If data values are supplied add that data to the data block. */
12995 if(new_data_c)
12997 /* Allocate memory */
12998 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
12999 stride_length, tot_n_particles,
13000 n_values_per_frame) !=
13001 TNG_SUCCESS)
13003 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13004 __FILE__, __LINE__);
13005 return(TNG_CRITICAL);
13008 if(n_frames > frame_set->n_unwritten_frames)
13010 frame_set->n_unwritten_frames = n_frames;
13013 n_frames_div = (n_frames % stride_length) ?
13014 n_frames / stride_length + 1:
13015 n_frames / stride_length;
13017 if(datatype == TNG_CHAR_DATA)
13019 for(i = 0; i < n_frames_div; i++)
13021 first_dim_values = data->strings[i];
13022 for(j = num_first_particle; j < num_first_particle + n_particles;
13023 j++)
13025 second_dim_values = first_dim_values[j];
13026 for(k = 0; k < n_values_per_frame; k++)
13028 len = tng_min_i((int)strlen(new_data_c) + 1,
13029 TNG_MAX_STR_LEN);
13030 if(second_dim_values[k])
13032 free(second_dim_values[k]);
13034 second_dim_values[k] = malloc(len);
13035 if(!second_dim_values[k])
13037 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13038 len, __FILE__, __LINE__);
13039 return(TNG_CRITICAL);
13041 strncpy(second_dim_values[k],
13042 new_data_c, len);
13043 new_data_c += len;
13048 else
13050 switch(datatype)
13052 case TNG_INT_DATA:
13053 size = sizeof(int64_t);
13054 break;
13055 case TNG_FLOAT_DATA:
13056 size = sizeof(float);
13057 break;
13058 case TNG_DOUBLE_DATA:
13059 default:
13060 size = sizeof(double);
13063 memcpy(data->values, new_data, size * n_frames_div *
13064 n_particles * n_values_per_frame);
13068 return(TNG_SUCCESS);
13071 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13072 (tng_trajectory_t tng_data,
13073 int64_t block_id,
13074 char *name,
13075 int max_len)
13077 int64_t i;
13078 tng_trajectory_frame_set_t frame_set;
13079 tng_function_status stat;
13080 tng_particle_data_t p_data;
13081 tng_non_particle_data_t np_data;
13082 int block_type = -1;
13084 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13085 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13087 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13089 p_data = &tng_data->non_tr_particle_data[i];
13090 if(p_data->block_id == block_id)
13092 strncpy(name, p_data->block_name, max_len);
13093 name[max_len - 1] = '\0';
13094 return(TNG_SUCCESS);
13097 for(i = 0; i < tng_data->n_data_blocks; i++)
13099 np_data = &tng_data->non_tr_data[i];
13100 if(np_data->block_id == block_id)
13102 strncpy(name, np_data->block_name, max_len);
13103 name[max_len - 1] = '\0';
13104 return(TNG_SUCCESS);
13108 frame_set = &tng_data->current_trajectory_frame_set;
13110 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13111 if(stat == TNG_SUCCESS)
13113 block_type = TNG_PARTICLE_BLOCK_DATA;
13115 else
13117 stat = tng_data_find(tng_data, block_id, &np_data);
13118 if(stat == TNG_SUCCESS)
13120 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13122 else
13124 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13125 if(stat != TNG_SUCCESS)
13127 return(stat);
13129 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13130 if(stat == TNG_SUCCESS)
13132 block_type = TNG_PARTICLE_BLOCK_DATA;
13134 else
13136 stat = tng_data_find(tng_data, block_id, &np_data);
13137 if(stat == TNG_SUCCESS)
13139 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13144 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13146 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13148 p_data = &frame_set->tr_particle_data[i];
13149 if(p_data->block_id == block_id)
13151 strncpy(name, p_data->block_name, max_len);
13152 name[max_len - 1] = '\0';
13153 return(TNG_SUCCESS);
13157 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13159 for(i = 0; i < frame_set->n_data_blocks; i++)
13161 np_data = &frame_set->tr_data[i];
13162 if(np_data->block_id == block_id)
13164 strncpy(name, np_data->block_name, max_len);
13165 name[max_len - 1] = '\0';
13166 return(TNG_SUCCESS);
13171 return(TNG_FAILURE);
13174 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13175 (const tng_trajectory_t tng_data,
13176 int64_t block_id,
13177 int *block_dependency)
13179 int64_t i;
13180 tng_function_status stat;
13181 tng_particle_data_t p_data;
13182 tng_non_particle_data_t np_data;
13184 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13185 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13187 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13189 p_data = &tng_data->non_tr_particle_data[i];
13190 if(p_data->block_id == block_id)
13192 *block_dependency = TNG_PARTICLE_DEPENDENT;
13193 return(TNG_SUCCESS);
13196 for(i = 0; i < tng_data->n_data_blocks; i++)
13198 np_data = &tng_data->non_tr_data[i];
13199 if(np_data->block_id == block_id)
13201 *block_dependency = 0;
13202 return(TNG_SUCCESS);
13206 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13207 if(stat == TNG_SUCCESS)
13209 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13210 return(TNG_SUCCESS);
13212 else
13214 stat = tng_data_find(tng_data, block_id, &np_data);
13215 if(stat == TNG_SUCCESS)
13217 *block_dependency = TNG_FRAME_DEPENDENT;
13218 return(TNG_SUCCESS);
13220 else
13222 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13223 if(stat != TNG_SUCCESS)
13225 return(stat);
13227 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13228 if(stat == TNG_SUCCESS)
13230 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13231 return(TNG_SUCCESS);
13233 else
13235 stat = tng_data_find(tng_data, block_id, &np_data);
13236 if(stat == TNG_SUCCESS)
13238 *block_dependency = TNG_FRAME_DEPENDENT;
13239 return(TNG_SUCCESS);
13245 return(TNG_FAILURE);
13248 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13249 (const tng_trajectory_t tng_data,
13250 int64_t block_id,
13251 int64_t *n_values_per_frame)
13253 int64_t i;
13254 tng_function_status stat;
13255 tng_particle_data_t p_data;
13256 tng_non_particle_data_t np_data;
13258 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13259 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13261 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13263 p_data = &tng_data->non_tr_particle_data[i];
13264 if(p_data->block_id == block_id)
13266 *n_values_per_frame = p_data->n_values_per_frame;
13267 return(TNG_SUCCESS);
13270 for(i = 0; i < tng_data->n_data_blocks; i++)
13272 np_data = &tng_data->non_tr_data[i];
13273 if(np_data->block_id == block_id)
13275 *n_values_per_frame = np_data->n_values_per_frame;
13276 return(TNG_SUCCESS);
13280 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13281 if(stat == TNG_SUCCESS)
13283 *n_values_per_frame = p_data->n_values_per_frame;
13284 return(TNG_SUCCESS);
13286 else
13288 stat = tng_data_find(tng_data, block_id, &np_data);
13289 if(stat == TNG_SUCCESS)
13291 *n_values_per_frame = np_data->n_values_per_frame;
13292 return(TNG_SUCCESS);
13294 else
13296 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13297 if(stat != TNG_SUCCESS)
13299 return(stat);
13301 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13302 if(stat == TNG_SUCCESS)
13304 *n_values_per_frame = p_data->n_values_per_frame;
13305 return(TNG_SUCCESS);
13307 else
13309 stat = tng_data_find(tng_data, block_id, &np_data);
13310 if(stat == TNG_SUCCESS)
13312 *n_values_per_frame = np_data->n_values_per_frame;
13313 return(TNG_SUCCESS);
13319 return(TNG_FAILURE);
13322 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13323 (tng_trajectory_t tng_data,
13324 const int64_t frame_nr,
13325 const int64_t block_id,
13326 const void *values,
13327 const char hash_mode)
13329 int64_t header_pos, file_pos;
13330 int64_t output_file_len, n_values_per_frame, size, contents_size;
13331 int64_t header_size, temp_first, temp_last;
13332 int64_t i, last_frame;
13333 long temp_current;
13334 tng_gen_block_t block;
13335 tng_trajectory_frame_set_t frame_set;
13336 FILE *temp = tng_data->input_file;
13337 struct tng_non_particle_data data;
13338 tng_function_status stat;
13339 char dependency, sparse_data, datatype;
13340 void *copy;
13342 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13343 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13344 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13346 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13348 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13349 __FILE__, __LINE__);
13350 return(TNG_CRITICAL);
13353 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13354 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13355 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13356 tng_data->first_trajectory_frame_set_input_file_pos =
13357 tng_data->first_trajectory_frame_set_output_file_pos;
13358 tng_data->last_trajectory_frame_set_input_file_pos =
13359 tng_data->last_trajectory_frame_set_output_file_pos;
13360 tng_data->current_trajectory_frame_set_input_file_pos =
13361 tng_data->current_trajectory_frame_set_output_file_pos;
13363 tng_data->input_file = tng_data->output_file;
13365 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13367 frame_set = &tng_data->current_trajectory_frame_set;
13369 if(stat != TNG_SUCCESS)
13371 last_frame = frame_set->first_frame +
13372 frame_set->n_frames - 1;
13373 /* If the wanted frame would be in the frame set after the last
13374 * frame set create a new frame set. */
13375 if(stat == TNG_FAILURE &&
13376 last_frame < frame_nr)
13377 /* (last_frame < frame_nr &&
13378 tng_data->current_trajectory_frame_set.first_frame +
13379 tng_data->frame_set_n_frames >= frame_nr))*/
13381 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13383 last_frame = frame_nr - 1;
13385 tng_frame_set_new(tng_data,
13386 last_frame+1,
13387 tng_data->frame_set_n_frames);
13388 file_pos = ftell(tng_data->output_file);
13389 fseek(tng_data->output_file, 0, SEEK_END);
13390 output_file_len = ftell(tng_data->output_file);
13391 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13393 /* Read mapping blocks from the last frame set */
13394 tng_block_init(&block);
13396 stat = tng_block_header_read(tng_data, block);
13397 while(file_pos < output_file_len &&
13398 stat != TNG_CRITICAL &&
13399 block->id != TNG_TRAJECTORY_FRAME_SET)
13401 if(block->id == TNG_PARTICLE_MAPPING)
13403 tng_trajectory_mapping_block_read(tng_data, block,
13404 hash_mode);
13406 else
13408 fseek(tng_data->output_file, (long)block->block_contents_size,
13409 SEEK_CUR);
13411 file_pos = ftell(tng_data->output_file);
13412 if(file_pos < output_file_len)
13414 stat = tng_block_header_read(tng_data, block);
13418 tng_block_destroy(&block);
13419 /* Write the frame set to disk */
13420 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13422 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13423 return(TNG_CRITICAL);
13426 else
13428 tng_data->input_file = temp;
13429 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13430 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13431 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13432 return(stat);
13436 tng_block_init(&block);
13438 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13440 fseek(tng_data->output_file, 0, SEEK_END);
13441 output_file_len = ftell(tng_data->output_file);
13442 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13444 /* Read past the frame set block first */
13445 stat = tng_block_header_read(tng_data, block);
13446 if(stat == TNG_CRITICAL)
13448 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13449 file_pos, __FILE__, __LINE__);
13450 tng_block_destroy(&block);
13451 tng_data->input_file = temp;
13453 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13454 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13455 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13456 return(stat);
13458 fseek(tng_data->output_file, (long)block->block_contents_size,
13459 SEEK_CUR);
13461 /* Read all block headers until next frame set block or
13462 * until the wanted block id is found */
13463 stat = tng_block_header_read(tng_data, block);
13464 while(file_pos < output_file_len &&
13465 stat != TNG_CRITICAL &&
13466 block->id != block_id &&
13467 block->id != TNG_TRAJECTORY_FRAME_SET)
13469 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
13470 file_pos = ftell(tng_data->output_file);
13471 if(file_pos < output_file_len)
13473 stat = tng_block_header_read(tng_data, block);
13476 if(stat == TNG_CRITICAL)
13478 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13479 file_pos, __FILE__, __LINE__);
13480 tng_block_destroy(&block);
13481 tng_data->input_file = temp;
13482 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13483 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13484 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13485 return(stat);
13488 contents_size = block->block_contents_size;
13489 header_size = block->header_contents_size;
13491 header_pos = ftell(tng_data->output_file) - header_size;
13492 frame_set = &tng_data->current_trajectory_frame_set;
13494 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
13496 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13497 tng_block_destroy(&block);
13498 return(TNG_CRITICAL);
13500 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
13502 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13503 tng_block_destroy(&block);
13504 return(TNG_CRITICAL);
13506 data.datatype = datatype;
13508 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13509 (dependency & TNG_PARTICLE_DEPENDENT))
13511 tng_block_destroy(&block);
13512 tng_data->input_file = temp;
13514 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13515 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13516 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13517 return(TNG_FAILURE);
13520 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
13522 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13523 tng_block_destroy(&block);
13524 return(TNG_CRITICAL);
13527 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
13528 tng_data->input_file) == 0)
13530 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13531 tng_block_destroy(&block);
13532 return(TNG_CRITICAL);
13534 if(tng_data->output_endianness_swap_func_64)
13536 if(tng_data->output_endianness_swap_func_64(tng_data,
13537 &data.n_values_per_frame)
13538 != TNG_SUCCESS)
13540 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13541 __FILE__, __LINE__);
13545 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
13546 tng_data->input_file) == 0)
13548 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13549 tng_block_destroy(&block);
13550 return(TNG_CRITICAL);
13552 if(tng_data->output_endianness_swap_func_64)
13554 if(tng_data->output_endianness_swap_func_64(tng_data,
13555 &data.codec_id)
13556 != TNG_SUCCESS)
13558 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13559 __FILE__, __LINE__);
13563 if(data.codec_id != TNG_UNCOMPRESSED)
13565 if(fread(&data.compression_multiplier,
13566 sizeof(data.compression_multiplier), 1, tng_data->input_file)
13567 == 0)
13569 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13570 tng_block_destroy(&block);
13571 return(TNG_CRITICAL);
13573 if(tng_data->output_endianness_swap_func_64)
13575 if(tng_data->output_endianness_swap_func_64(tng_data,
13576 (int64_t *)&data.compression_multiplier)
13577 != TNG_SUCCESS)
13579 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13580 __FILE__, __LINE__);
13584 else
13586 data.compression_multiplier = 1;
13589 if(sparse_data)
13591 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
13592 1, tng_data->input_file) == 0)
13594 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13595 tng_block_destroy(&block);
13596 return(TNG_CRITICAL);
13598 if(tng_data->output_endianness_swap_func_64)
13600 if(tng_data->output_endianness_swap_func_64(tng_data,
13601 &data.first_frame_with_data)
13602 != TNG_SUCCESS)
13604 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13605 __FILE__, __LINE__);
13609 if(fread(&data.stride_length, sizeof(data.stride_length),
13610 1, tng_data->input_file) == 0)
13612 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13613 tng_block_destroy(&block);
13614 return(TNG_CRITICAL);
13616 if(tng_data->output_endianness_swap_func_64)
13618 if(tng_data->output_endianness_swap_func_64(tng_data,
13619 &data.stride_length)
13620 != TNG_SUCCESS)
13622 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13623 __FILE__, __LINE__);
13627 else
13629 data.first_frame_with_data = 0;
13630 data.stride_length = 1;
13632 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13634 tng_data->input_file = temp;
13636 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13637 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13638 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13640 switch(data.datatype)
13642 case(TNG_INT_DATA):
13643 size = sizeof(int64_t);
13644 break;
13645 case(TNG_FLOAT_DATA):
13646 size = sizeof(float);
13647 break;
13648 case(TNG_DOUBLE_DATA):
13649 size = sizeof(double);
13650 break;
13651 default:
13652 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13653 __LINE__);
13654 tng_block_destroy(&block);
13655 return(TNG_FAILURE);
13658 n_values_per_frame = data.n_values_per_frame;
13660 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13661 data.first_frame_with_data)) /
13662 data.stride_length;
13663 file_pos *= size * n_values_per_frame;
13665 if(file_pos > contents_size)
13667 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13668 __LINE__);
13669 tng_block_destroy(&block);
13670 return(TNG_FAILURE);
13673 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
13675 /* If the endianness is not big endian the data needs to be swapped */
13676 if((data.datatype == TNG_INT_DATA ||
13677 data.datatype == TNG_DOUBLE_DATA) &&
13678 tng_data->output_endianness_swap_func_64)
13680 copy = malloc(n_values_per_frame * size);
13681 memcpy(copy, values, n_values_per_frame * size);
13682 for(i = 0; i < n_values_per_frame; i++)
13684 if(tng_data->output_endianness_swap_func_64(tng_data,
13685 (int64_t *)copy+i)
13686 != TNG_SUCCESS)
13688 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13689 __FILE__, __LINE__);
13692 fwrite(copy, n_values_per_frame, size,
13693 tng_data->output_file);
13694 free(copy);
13696 else if(data.datatype == TNG_FLOAT_DATA &&
13697 tng_data->output_endianness_swap_func_32)
13699 copy = malloc(n_values_per_frame * size);
13700 memcpy(copy, values, n_values_per_frame * size);
13701 for(i = 0; i < n_values_per_frame; i++)
13703 if(tng_data->output_endianness_swap_func_32(tng_data,
13704 (int32_t *)copy+i)
13705 != TNG_SUCCESS)
13707 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13708 __FILE__, __LINE__);
13711 fwrite(copy, n_values_per_frame, size,
13712 tng_data->output_file);
13713 free(copy);
13716 else
13718 fwrite(values, n_values_per_frame, size, tng_data->output_file);
13721 fflush(tng_data->output_file);
13723 /* Update the number of written frames in the frame set. */
13724 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13726 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13729 /* If the last frame has been written update the hash */
13730 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13731 data.first_frame_with_data) >=
13732 frame_set->n_frames)
13734 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13735 header_size);
13738 tng_block_destroy(&block);
13740 return(TNG_SUCCESS);
13743 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13744 (tng_trajectory_t tng_data,
13745 const int64_t frame_nr,
13746 const int64_t block_id,
13747 const int64_t val_first_particle,
13748 const int64_t val_n_particles,
13749 const void *values,
13750 const char hash_mode)
13752 int64_t header_pos, file_pos, tot_n_particles;
13753 int64_t output_file_len, n_values_per_frame, size, contents_size;
13754 int64_t header_size, temp_first, temp_last;
13755 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13756 int64_t i, last_frame;
13757 long temp_current;
13758 tng_gen_block_t block;
13759 tng_trajectory_frame_set_t frame_set;
13760 FILE *temp = tng_data->input_file;
13761 struct tng_particle_data data;
13762 tng_function_status stat;
13763 tng_particle_mapping_t mapping;
13764 char dependency, sparse_data, datatype;
13765 void *copy;
13767 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13768 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13769 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13770 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13771 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13773 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13775 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13776 __FILE__, __LINE__);
13777 return(TNG_CRITICAL);
13780 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13781 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13782 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13783 tng_data->first_trajectory_frame_set_input_file_pos =
13784 tng_data->first_trajectory_frame_set_output_file_pos;
13785 tng_data->last_trajectory_frame_set_input_file_pos =
13786 tng_data->last_trajectory_frame_set_output_file_pos;
13787 tng_data->current_trajectory_frame_set_input_file_pos =
13788 tng_data->current_trajectory_frame_set_output_file_pos;
13790 tng_data->input_file = tng_data->output_file;
13792 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13794 frame_set = &tng_data->current_trajectory_frame_set;
13796 if(stat != TNG_SUCCESS)
13798 last_frame = frame_set->first_frame +
13799 frame_set->n_frames - 1;
13800 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
13801 last_frame); */
13802 /* If the wanted frame would be in the frame set after the last
13803 * frame set create a new frame set. */
13804 if(stat == TNG_FAILURE &&
13805 (last_frame < frame_nr &&
13806 last_frame + tng_data->frame_set_n_frames >= frame_nr))
13808 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13810 last_frame = frame_nr - 1;
13812 tng_frame_set_new(tng_data,
13813 last_frame+1,
13814 tng_data->frame_set_n_frames);
13816 file_pos = ftell(tng_data->output_file);
13817 fseek(tng_data->output_file, 0, SEEK_END);
13818 output_file_len = ftell(tng_data->output_file);
13819 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13821 /* Read mapping blocks from the last frame set */
13822 tng_block_init(&block);
13824 stat = tng_block_header_read(tng_data, block);
13825 while(file_pos < output_file_len &&
13826 stat != TNG_CRITICAL &&
13827 block->id != TNG_TRAJECTORY_FRAME_SET)
13829 if(block->id == TNG_PARTICLE_MAPPING)
13831 tng_trajectory_mapping_block_read(tng_data, block,
13832 hash_mode);
13834 else
13836 fseek(tng_data->output_file, (long)block->block_contents_size,
13837 SEEK_CUR);
13839 file_pos = ftell(tng_data->output_file);
13840 if(file_pos < output_file_len)
13842 stat = tng_block_header_read(tng_data, block);
13846 tng_block_destroy(&block);
13847 /* Write the frame set to disk */
13848 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13850 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13851 exit(1);
13854 else
13856 tng_data->input_file = temp;
13857 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13858 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13859 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13860 return(stat);
13865 tng_block_init(&block);
13867 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13869 fseek(tng_data->output_file, 0, SEEK_END);
13870 output_file_len = ftell(tng_data->output_file);
13871 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13873 /* Read past the frame set block first */
13874 stat = tng_block_header_read(tng_data, block);
13875 if(stat == TNG_CRITICAL)
13877 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13878 file_pos, __FILE__, __LINE__);
13879 tng_block_destroy(&block);
13880 tng_data->input_file = temp;
13882 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13883 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13884 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13885 return(stat);
13887 fseek(tng_data->output_file, (long)block->block_contents_size,
13888 SEEK_CUR);
13890 if(tng_data->var_num_atoms_flag)
13892 tot_n_particles = frame_set->n_particles;
13894 else
13896 tot_n_particles = tng_data->n_particles;
13899 if(val_n_particles < tot_n_particles)
13901 mapping_block_end_pos = -1;
13902 /* Read all mapping blocks to find the right place to put the data */
13903 stat = tng_block_header_read(tng_data, block);
13904 while(file_pos < output_file_len &&
13905 stat != TNG_CRITICAL &&
13906 block->id != TNG_TRAJECTORY_FRAME_SET)
13908 if(block->id == TNG_PARTICLE_MAPPING)
13910 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13912 else
13914 fseek(tng_data->output_file, (long)block->block_contents_size,
13915 SEEK_CUR);
13917 file_pos = ftell(tng_data->output_file);
13918 if(block->id == TNG_PARTICLE_MAPPING)
13920 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13921 if(val_first_particle >= mapping->num_first_particle &&
13922 val_first_particle < mapping->num_first_particle +
13923 mapping->n_particles &&
13924 val_first_particle + val_n_particles <=
13925 mapping->num_first_particle + mapping->n_particles)
13927 mapping_block_end_pos = file_pos;
13930 if(file_pos < output_file_len)
13932 stat = tng_block_header_read(tng_data, block);
13935 if(stat == TNG_CRITICAL)
13937 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13938 file_pos, __FILE__, __LINE__);
13939 tng_block_destroy(&block);
13940 tng_data->input_file = temp;
13942 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13943 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13944 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13945 return(stat);
13947 if(mapping_block_end_pos < 0)
13949 tng_block_destroy(&block);
13950 tng_data->input_file = temp;
13952 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13953 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13954 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13955 return(TNG_FAILURE);
13957 fseek(tng_data->output_file, (long)mapping_block_end_pos, SEEK_SET);
13960 /* Read all block headers until next frame set block or
13961 * until the wanted block id is found */
13962 stat = tng_block_header_read(tng_data, block);
13963 while(file_pos < output_file_len &&
13964 stat != TNG_CRITICAL &&
13965 block->id != block_id &&
13966 block->id != TNG_PARTICLE_MAPPING &&
13967 block->id != TNG_TRAJECTORY_FRAME_SET)
13969 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
13970 file_pos = ftell(tng_data->output_file);
13971 if(file_pos < output_file_len)
13973 stat = tng_block_header_read(tng_data, block);
13976 if(stat == TNG_CRITICAL)
13978 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13979 file_pos, __FILE__, __LINE__);
13980 tng_block_destroy(&block);
13981 tng_data->input_file = temp;
13983 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13984 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13985 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13986 return(stat);
13989 contents_size = block->block_contents_size;
13990 header_size = block->header_contents_size;
13992 header_pos = ftell(tng_data->output_file) - header_size;
13993 frame_set = &tng_data->current_trajectory_frame_set;
13995 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
13997 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13998 tng_block_destroy(&block);
13999 return(TNG_CRITICAL);
14002 data.datatype = datatype;
14004 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14006 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14007 tng_block_destroy(&block);
14008 return(TNG_CRITICAL);
14011 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14012 !(dependency & TNG_PARTICLE_DEPENDENT))
14014 tng_block_destroy(&block);
14015 tng_data->input_file = temp;
14017 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14018 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14019 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14020 return(TNG_FAILURE);
14023 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14025 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14026 tng_block_destroy(&block);
14027 return(TNG_CRITICAL);
14030 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14031 tng_data->input_file) == 0)
14033 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14034 tng_block_destroy(&block);
14035 return(TNG_CRITICAL);
14037 if(tng_data->output_endianness_swap_func_64)
14039 if(tng_data->output_endianness_swap_func_64(tng_data,
14040 &data.n_values_per_frame)
14041 != TNG_SUCCESS)
14043 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14044 __FILE__, __LINE__);
14048 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14049 tng_data->input_file) == 0)
14051 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14052 tng_block_destroy(&block);
14053 return(TNG_CRITICAL);
14055 if(tng_data->output_endianness_swap_func_64)
14057 if(tng_data->output_endianness_swap_func_64(tng_data,
14058 &data.codec_id)
14059 != TNG_SUCCESS)
14061 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14062 __FILE__, __LINE__);
14066 if(data.codec_id != TNG_UNCOMPRESSED)
14068 if(fread(&data.compression_multiplier,
14069 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14070 == 0)
14072 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14073 tng_block_destroy(&block);
14074 return(TNG_CRITICAL);
14077 if(tng_data->output_endianness_swap_func_64)
14079 if(tng_data->output_endianness_swap_func_64(tng_data,
14080 (int64_t *)&data.compression_multiplier)
14081 != TNG_SUCCESS)
14083 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14084 __FILE__, __LINE__);
14088 else
14090 data.compression_multiplier = 1;
14093 if(sparse_data)
14095 if(fread(&data.first_frame_with_data,
14096 sizeof(data.first_frame_with_data),
14097 1, tng_data->input_file) == 0)
14099 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14100 tng_block_destroy(&block);
14101 return(TNG_CRITICAL);
14103 if(tng_data->output_endianness_swap_func_64)
14105 if(tng_data->output_endianness_swap_func_64(tng_data,
14106 &data.first_frame_with_data)
14107 != TNG_SUCCESS)
14109 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14110 __FILE__, __LINE__);
14114 if(fread(&data.stride_length, sizeof(data.stride_length),
14115 1, tng_data->input_file) == 0)
14117 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14118 tng_block_destroy(&block);
14119 return(TNG_CRITICAL);
14121 if(tng_data->output_endianness_swap_func_64)
14123 if(tng_data->output_endianness_swap_func_64(tng_data,
14124 &data.stride_length)
14125 != TNG_SUCCESS)
14127 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14128 __FILE__, __LINE__);
14132 else
14134 data.first_frame_with_data = 0;
14135 data.stride_length = 1;
14137 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14139 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14140 tng_data->input_file) == 0)
14142 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14143 tng_block_destroy(&block);
14144 return(TNG_CRITICAL);
14146 if(tng_data->output_endianness_swap_func_64)
14148 if(tng_data->output_endianness_swap_func_64(tng_data,
14149 &num_first_particle)
14150 != TNG_SUCCESS)
14152 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14153 __FILE__, __LINE__);
14157 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14158 tng_data->input_file) == 0)
14160 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14161 tng_block_destroy(&block);
14162 return(TNG_CRITICAL);
14164 if(tng_data->output_endianness_swap_func_64)
14166 if(tng_data->output_endianness_swap_func_64(tng_data,
14167 &block_n_particles)
14168 != TNG_SUCCESS)
14170 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14171 __FILE__, __LINE__);
14176 tng_data->input_file = temp;
14178 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14179 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14180 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14183 switch(data.datatype)
14185 case(TNG_INT_DATA):
14186 size = sizeof(int64_t);
14187 break;
14188 case(TNG_FLOAT_DATA):
14189 size = sizeof(float);
14190 break;
14191 case(TNG_DOUBLE_DATA):
14192 size = sizeof(double);
14193 break;
14194 default:
14195 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14196 __LINE__);
14197 tng_block_destroy(&block);
14198 return(TNG_FAILURE);
14201 n_values_per_frame = data.n_values_per_frame;
14203 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14204 data.first_frame_with_data)) /
14205 data.stride_length;
14206 file_pos *= block_n_particles * size * n_values_per_frame;
14208 if(file_pos > contents_size)
14210 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14211 __LINE__);
14212 tng_block_destroy(&block);
14213 return(TNG_FAILURE);
14216 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14218 /* If the endianness is not big endian the data needs to be swapped */
14219 if((data.datatype == TNG_INT_DATA ||
14220 data.datatype == TNG_DOUBLE_DATA) &&
14221 tng_data->output_endianness_swap_func_64)
14223 copy = malloc(val_n_particles * n_values_per_frame * size);
14224 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14225 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14227 if(tng_data->output_endianness_swap_func_64(tng_data,
14228 (int64_t *) copy+i)
14229 != TNG_SUCCESS)
14231 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14232 __FILE__, __LINE__);
14235 fwrite(copy, val_n_particles * n_values_per_frame, size,
14236 tng_data->output_file);
14237 free(copy);
14239 else if(data.datatype == TNG_FLOAT_DATA &&
14240 tng_data->output_endianness_swap_func_32)
14242 copy = malloc(val_n_particles * n_values_per_frame * size);
14243 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14244 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14246 if(tng_data->output_endianness_swap_func_32(tng_data,
14247 (int32_t *) copy+i)
14248 != TNG_SUCCESS)
14250 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14251 __FILE__, __LINE__);
14254 fwrite(copy, val_n_particles * n_values_per_frame, size,
14255 tng_data->output_file);
14256 free(copy);
14259 else
14261 fwrite(values, val_n_particles * n_values_per_frame, size,
14262 tng_data->output_file);
14264 fflush(tng_data->output_file);
14266 /* Update the number of written frames in the frame set. */
14267 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14269 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14272 /* If the last frame has been written update the hash */
14273 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14274 data.first_frame_with_data) >=
14275 frame_set->n_frames)
14277 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14278 header_size);
14281 tng_block_destroy(&block);
14282 return(TNG_SUCCESS);
14285 static tng_function_status tng_data_values_alloc
14286 (const tng_trajectory_t tng_data,
14287 union data_values ***values,
14288 const int64_t n_frames,
14289 const int64_t n_values_per_frame,
14290 const char type)
14292 int64_t i;
14293 tng_function_status stat;
14295 if(n_frames <= 0 || n_values_per_frame <= 0)
14297 return(TNG_FAILURE);
14300 if(*values)
14302 stat = tng_data_values_free(tng_data, *values, n_frames,
14303 n_values_per_frame,
14304 type);
14305 if(stat != TNG_SUCCESS)
14307 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
14308 __FILE__, __LINE__);
14309 return(stat);
14312 *values = malloc(sizeof(union data_values *) * n_frames);
14313 if(!*values)
14315 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14316 sizeof(union data_values **) * n_frames,
14317 __FILE__, __LINE__);
14318 return(TNG_CRITICAL);
14322 for(i = n_frames; i--;)
14324 (*values)[i] = malloc(sizeof(union data_values) *
14325 n_values_per_frame);
14326 if(!(*values)[i])
14328 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14329 sizeof(union data_values) * n_values_per_frame,
14330 __FILE__, __LINE__);
14331 free(values);
14332 values = 0;
14333 return(TNG_CRITICAL);
14336 return(TNG_SUCCESS);
14339 /* FIXME: This needs ***values */
14340 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
14341 (const tng_trajectory_t tng_data,
14342 union data_values **values,
14343 const int64_t n_frames,
14344 const int64_t n_values_per_frame,
14345 const char type)
14347 int64_t i, j;
14348 (void)tng_data;
14350 if(values)
14352 for(i = 0; i < n_frames; i++)
14354 if(values[i])
14356 if(type == TNG_CHAR_DATA)
14358 for(j = n_values_per_frame; j--;)
14360 if(values[i][j].c)
14362 free(values[i][j].c);
14363 values[i][j].c = 0;
14367 free(values[i]);
14368 values[i] = 0;
14371 free(values);
14372 values = 0;
14375 return(TNG_SUCCESS);
14378 static tng_function_status tng_particle_data_values_alloc
14379 (const tng_trajectory_t tng_data,
14380 union data_values ****values,
14381 const int64_t n_frames,
14382 const int64_t n_particles,
14383 const int64_t n_values_per_frame,
14384 const char type)
14386 int64_t i, j;
14387 tng_function_status stat;
14389 if(n_particles == 0 || n_values_per_frame == 0)
14391 return(TNG_FAILURE);
14394 if(*values)
14396 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
14397 n_particles, n_values_per_frame,
14398 type);
14399 if(stat != TNG_SUCCESS)
14401 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
14402 __FILE__, __LINE__);
14403 return(stat);
14406 *values = malloc(sizeof(union data_values **) * n_frames);
14407 if(!*values)
14409 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14410 sizeof(union data_values **) * n_frames,
14411 __FILE__, __LINE__);
14412 return(TNG_CRITICAL);
14416 for(i = n_frames; i--;)
14418 (*values)[i] = malloc(sizeof(union data_values *) *
14419 n_particles);
14420 if(!(*values)[i])
14422 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14423 sizeof(union data_values *) * n_particles,
14424 __FILE__, __LINE__);
14425 free(*values);
14426 *values = 0;
14427 return(TNG_CRITICAL);
14429 for(j = n_particles; j--;)
14431 (*values)[i][j] = malloc(sizeof(union data_values) *
14432 n_values_per_frame);
14433 if(!(*values)[i][j])
14435 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14436 sizeof(union data_values *) * n_particles,
14437 __FILE__, __LINE__);
14438 tng_particle_data_values_free(tng_data, *values, n_frames,
14439 n_particles, n_values_per_frame,
14440 type);
14441 *values = 0;
14442 return(TNG_CRITICAL);
14446 return(TNG_SUCCESS);
14449 /* FIXME: This needs ****values */
14450 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
14451 (const tng_trajectory_t tng_data,
14452 union data_values ***values,
14453 const int64_t n_frames,
14454 const int64_t n_particles,
14455 const int64_t n_values_per_frame,
14456 const char type)
14458 int64_t i, j, k;
14459 (void)tng_data;
14461 if(values)
14463 for(i = 0; i < n_frames; i++)
14465 if(values[i])
14467 for(j = 0; j < n_particles; j++)
14469 if(type == TNG_CHAR_DATA)
14471 for(k = n_values_per_frame; k--;)
14473 if(values[i][j][k].c)
14475 free(values[i][j][k].c);
14476 values[i][j][k].c = 0;
14480 free(values[i][j]);
14481 values[i][j] = 0;
14483 free(values[i]);
14484 values[i] = 0;
14487 free(values);
14488 values = 0;
14491 return(TNG_SUCCESS);
14495 tng_function_status DECLSPECDLLEXPORT tng_data_get
14496 (tng_trajectory_t tng_data,
14497 const int64_t block_id,
14498 union data_values ***values,
14499 int64_t *n_frames,
14500 int64_t *n_values_per_frame,
14501 char *type)
14503 int64_t i, j, file_pos, block_index;
14504 int size;
14505 size_t len;
14506 tng_non_particle_data_t data;
14507 tng_trajectory_frame_set_t frame_set;
14508 tng_gen_block_t block;
14509 tng_function_status stat;
14511 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14512 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14513 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14514 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14516 frame_set = &tng_data->current_trajectory_frame_set;
14518 block_index = -1;
14519 data = 0;
14521 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
14523 tng_block_init(&block);
14524 file_pos = ftell(tng_data->input_file);
14525 /* Read all blocks until next frame set block */
14526 stat = tng_block_header_read(tng_data, block);
14527 while(file_pos < tng_data->input_file_len &&
14528 stat != TNG_CRITICAL &&
14529 block->id != TNG_TRAJECTORY_FRAME_SET)
14531 /* Use hash by default */
14532 stat = tng_block_read_next(tng_data, block,
14533 TNG_USE_HASH);
14534 if(stat != TNG_CRITICAL)
14536 file_pos = ftell(tng_data->input_file);
14537 if(file_pos < tng_data->input_file_len)
14539 stat = tng_block_header_read(tng_data, block);
14543 tng_block_destroy(&block);
14544 if(stat == TNG_CRITICAL)
14546 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14547 file_pos, __FILE__, __LINE__);
14548 return(stat);
14551 for(i = frame_set->n_data_blocks; i-- ;)
14553 data = &frame_set->tr_data[i];
14554 if(data->block_id == block_id)
14556 block_index = i;
14557 break;
14560 if(block_index < 0)
14562 return(TNG_FAILURE);
14566 *n_frames = tng_max_i64(1, data->n_frames);
14567 *n_values_per_frame = data->n_values_per_frame;
14568 *type = data->datatype;
14570 if(*values == 0)
14572 if(tng_data_values_alloc(tng_data, values, *n_frames,
14573 *n_values_per_frame,
14574 *type)
14575 != TNG_SUCCESS)
14577 return(TNG_CRITICAL);
14581 switch(*type)
14583 case TNG_CHAR_DATA:
14584 for(i=*n_frames; i--;)
14586 for(j=*n_values_per_frame; j--;)
14588 len = strlen(data->strings[i][j]) + 1;
14589 (*values)[i][j].c = malloc(len);
14590 strncpy((*values)[i][j].c, data->strings[i][j], len);
14593 break;
14594 case TNG_INT_DATA:
14595 size = sizeof(int);
14596 for(i=*n_frames; i--;)
14598 for(j=*n_values_per_frame; j--;)
14600 (*values)[i][j].i = *(int *)((char *)data->values + size *
14601 (i*(*n_values_per_frame) + j));
14604 break;
14605 case TNG_FLOAT_DATA:
14606 size = sizeof(float);
14607 for(i=*n_frames; i--;)
14609 for(j=*n_values_per_frame; j--;)
14611 (*values)[i][j].f = *(float *)((char *)data->values + size *
14612 (i*(*n_values_per_frame) + j));
14615 break;
14616 case TNG_DOUBLE_DATA:
14617 default:
14618 size = sizeof(double);
14619 for(i=*n_frames; i--;)
14621 for(j=*n_values_per_frame; j--;)
14623 (*values)[i][j].d = *(double *)((char *)data->values + size *
14624 (i*(*n_values_per_frame) + j));
14629 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14631 return(TNG_SUCCESS);
14634 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
14635 const int64_t block_id,
14636 void **values,
14637 int64_t *n_frames,
14638 int64_t *stride_length,
14639 int64_t *n_values_per_frame,
14640 char *type)
14642 int64_t file_pos, data_size, n_frames_div, block_index;
14643 int i, size;
14644 tng_non_particle_data_t data;
14645 tng_trajectory_frame_set_t frame_set;
14646 tng_gen_block_t block;
14647 void *temp;
14648 tng_function_status stat;
14650 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14651 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14652 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14653 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14654 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14656 frame_set = &tng_data->current_trajectory_frame_set;
14658 block_index = -1;
14659 data = 0;
14661 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
14663 tng_block_init(&block);
14664 file_pos = ftell(tng_data->input_file);
14665 /* Read all blocks until next frame set block */
14666 stat = tng_block_header_read(tng_data, block);
14667 while(file_pos < tng_data->input_file_len &&
14668 stat != TNG_CRITICAL &&
14669 block->id != TNG_TRAJECTORY_FRAME_SET)
14671 /* Use hash by default */
14672 stat = tng_block_read_next(tng_data, block,
14673 TNG_USE_HASH);
14674 if(stat != TNG_CRITICAL)
14676 file_pos = ftell(tng_data->input_file);
14677 if(file_pos < tng_data->input_file_len)
14679 stat = tng_block_header_read(tng_data, block);
14683 tng_block_destroy(&block);
14684 if(stat == TNG_CRITICAL)
14686 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14687 file_pos, __FILE__, __LINE__);
14688 return(stat);
14691 for(i = frame_set->n_data_blocks; i-- ;)
14693 data = &frame_set->tr_data[i];
14694 if(data->block_id == block_id)
14696 block_index = i;
14697 break;
14700 if(block_index < 0)
14702 return(TNG_FAILURE);
14706 *type = data->datatype;
14708 switch(*type)
14710 case TNG_CHAR_DATA:
14711 return(TNG_FAILURE);
14712 case TNG_INT_DATA:
14713 size = sizeof(int64_t);
14714 break;
14715 case TNG_FLOAT_DATA:
14716 size = sizeof(float);
14717 break;
14718 case TNG_DOUBLE_DATA:
14719 default:
14720 size = sizeof(double);
14723 *n_frames = data->n_frames;
14724 *n_values_per_frame = data->n_values_per_frame;
14725 *stride_length = data->stride_length;
14726 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
14727 *n_frames / *stride_length;
14729 data_size = n_frames_div * size *
14730 *n_values_per_frame;
14732 temp = realloc(*values, data_size);
14733 if(!temp)
14735 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14736 data_size, __FILE__, __LINE__);
14737 free(*values);
14738 *values = 0;
14739 return(TNG_CRITICAL);
14742 *values = temp;
14744 memcpy(*values, data->values, data_size);
14746 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14748 return(TNG_SUCCESS);
14751 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14752 (tng_trajectory_t tng_data,
14753 const int64_t block_id,
14754 const int64_t start_frame_nr,
14755 const int64_t end_frame_nr,
14756 const char hash_mode,
14757 union data_values ***values,
14758 int64_t *n_values_per_frame,
14759 char *type)
14761 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
14762 int64_t block_index;
14763 int size;
14764 size_t len;
14765 tng_non_particle_data_t data;
14766 tng_trajectory_frame_set_t frame_set;
14767 tng_gen_block_t block;
14768 tng_function_status stat;
14770 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14771 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14772 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14773 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14775 block_index = -1;
14777 frame_set = &tng_data->current_trajectory_frame_set;
14778 first_frame = frame_set->first_frame;
14780 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14781 if(stat != TNG_SUCCESS)
14783 return(stat);
14787 /* Do not re-read the frame set. */
14788 if(first_frame != frame_set->first_frame ||
14789 frame_set->n_data_blocks <= 0)
14791 tng_block_init(&block);
14792 file_pos = ftell(tng_data->input_file);
14793 /* Read all blocks until next frame set block */
14794 stat = tng_block_header_read(tng_data, block);
14795 while(file_pos < tng_data->input_file_len &&
14796 stat != TNG_CRITICAL &&
14797 block->id != TNG_TRAJECTORY_FRAME_SET)
14799 stat = tng_block_read_next(tng_data, block,
14800 hash_mode);
14801 if(stat != TNG_CRITICAL)
14803 file_pos = ftell(tng_data->input_file);
14804 if(file_pos < tng_data->input_file_len)
14806 stat = tng_block_header_read(tng_data, block);
14810 tng_block_destroy(&block);
14811 if(stat == TNG_CRITICAL)
14813 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14814 file_pos, __FILE__, __LINE__);
14815 return(stat);
14820 /* See if there is a data block of this ID.
14821 * Start checking the last read frame set */
14822 for(i = frame_set->n_data_blocks; i-- ;)
14824 data = &frame_set->tr_data[i];
14825 if(data->block_id == block_id)
14827 block_index = i;
14828 break;
14832 if(block_index < 0)
14834 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
14835 block_id, __FILE__, __LINE__);
14836 return(TNG_FAILURE);
14839 n_frames = end_frame_nr - start_frame_nr + 1;
14840 *n_values_per_frame = data->n_values_per_frame;
14841 *type = data->datatype;
14843 if(*values == 0)
14845 if(tng_data_values_alloc(tng_data, values, n_frames,
14846 *n_values_per_frame,
14847 *type) != TNG_SUCCESS)
14849 return(TNG_CRITICAL);
14853 current_frame_pos = start_frame_nr - frame_set->first_frame;
14854 /* It's not very elegant to reuse so much of the code in the different case
14855 * statements, but it's unnecessarily slow to have the switch-case block
14856 * inside the for loops. */
14857 switch(*type)
14859 case TNG_CHAR_DATA:
14860 for(i=0; i<n_frames; i++)
14862 if(current_frame_pos == frame_set->n_frames)
14864 stat = tng_frame_set_read_next(tng_data, hash_mode);
14865 if(stat != TNG_SUCCESS)
14867 return(stat);
14869 current_frame_pos = 0;
14871 for(j=*n_values_per_frame; j--;)
14873 len = strlen(data->strings[current_frame_pos][j]) + 1;
14874 (*values)[i][j].c = malloc(len);
14875 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
14877 current_frame_pos++;
14879 break;
14880 case TNG_INT_DATA:
14881 size = sizeof(int);
14882 for(i=0; i<n_frames; i++)
14884 if(current_frame_pos == frame_set->n_frames)
14886 stat = tng_frame_set_read_next(tng_data, hash_mode);
14887 if(stat != TNG_SUCCESS)
14889 return(stat);
14891 current_frame_pos = 0;
14893 for(j=*n_values_per_frame; j--;)
14895 (*values)[i][j].i = *(int *)((char *)data->values + size *
14896 (current_frame_pos *
14897 (*n_values_per_frame) + j));
14899 current_frame_pos++;
14901 break;
14902 case TNG_FLOAT_DATA:
14903 size = sizeof(float);
14904 for(i=0; i<n_frames; i++)
14906 if(current_frame_pos == frame_set->n_frames)
14908 stat = tng_frame_set_read_next(tng_data, hash_mode);
14909 if(stat != TNG_SUCCESS)
14911 return(stat);
14913 current_frame_pos = 0;
14915 for(j=*n_values_per_frame; j--;)
14917 (*values)[i][j].f = *(float *)((char *)data->values + size *
14918 (current_frame_pos *
14919 (*n_values_per_frame) + j));
14921 current_frame_pos++;
14923 break;
14924 case TNG_DOUBLE_DATA:
14925 default:
14926 size = sizeof(double);
14927 for(i=0; i<n_frames; i++)
14929 if(current_frame_pos == frame_set->n_frames)
14931 stat = tng_frame_set_read_next(tng_data, hash_mode);
14932 if(stat != TNG_SUCCESS)
14934 return(stat);
14936 current_frame_pos = 0;
14938 for(j=*n_values_per_frame; j--;)
14940 (*values)[i][j].d = *(double *)((char *)data->values + size *
14941 (current_frame_pos *
14942 (*n_values_per_frame) + j));
14944 current_frame_pos++;
14948 data->last_retrieved_frame = end_frame_nr;
14950 return(TNG_SUCCESS);
14953 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14954 (tng_trajectory_t tng_data,
14955 const int64_t block_id,
14956 const int64_t start_frame_nr,
14957 const int64_t end_frame_nr,
14958 const char hash_mode,
14959 void **values,
14960 int64_t *stride_length,
14961 int64_t *n_values_per_frame,
14962 char *type)
14964 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14965 int64_t file_pos, current_frame_pos, data_size, frame_size;
14966 int64_t last_frame_pos;
14967 int size;
14968 tng_trajectory_frame_set_t frame_set;
14969 tng_non_particle_data_t np_data;
14970 tng_gen_block_t block;
14971 void *current_values = 0, *temp;
14972 tng_function_status stat;
14974 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14975 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14976 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14977 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14978 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14980 frame_set = &tng_data->current_trajectory_frame_set;
14981 first_frame = frame_set->first_frame;
14983 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14984 if(stat != TNG_SUCCESS)
14986 return(stat);
14989 /* Do not re-read the frame set and only need the requested block. */
14990 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
14991 stat = tng_data_find(tng_data, block_id, &np_data);
14992 if(first_frame != frame_set->first_frame ||
14993 stat != TNG_SUCCESS)
14995 tng_block_init(&block);
14996 if(stat != TNG_SUCCESS)
14998 fseek(tng_data->input_file,
14999 (long)tng_data->current_trajectory_frame_set_input_file_pos,
15000 SEEK_SET);
15001 stat = tng_block_header_read(tng_data, block);
15002 if(stat != TNG_SUCCESS)
15004 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15005 __FILE__, __LINE__);
15006 return(stat);
15009 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15011 file_pos = ftell(tng_data->input_file);
15012 /* Read until next frame set block */
15013 stat = tng_block_header_read(tng_data, block);
15014 while(file_pos < tng_data->input_file_len &&
15015 stat != TNG_CRITICAL &&
15016 block->id != TNG_TRAJECTORY_FRAME_SET)
15018 if(block->id == block_id)
15020 stat = tng_block_read_next(tng_data, block,
15021 hash_mode);
15022 if(stat != TNG_CRITICAL)
15024 file_pos = ftell(tng_data->input_file);
15025 if(file_pos < tng_data->input_file_len)
15027 stat = tng_block_header_read(tng_data, block);
15031 else
15033 file_pos += block->block_contents_size + block->header_contents_size;
15034 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15035 if(file_pos < tng_data->input_file_len)
15037 stat = tng_block_header_read(tng_data, block);
15041 tng_block_destroy(&block);
15042 if(stat == TNG_CRITICAL)
15044 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15045 file_pos, __FILE__, __LINE__);
15046 return(stat);
15050 stat = tng_data_find(tng_data, block_id, &np_data);
15051 if(stat != TNG_SUCCESS)
15053 return(stat);
15056 stat = tng_data_vector_get(tng_data, block_id, &current_values,
15057 &n_frames, stride_length,
15058 n_values_per_frame, type);
15060 if(stat != TNG_SUCCESS)
15062 if(current_values)
15064 free(current_values);
15066 return(stat);
15069 if(n_frames == 1 && n_frames < frame_set->n_frames)
15071 tot_n_frames = 1;
15073 else
15075 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15078 switch(*type)
15080 case TNG_CHAR_DATA:
15081 return(TNG_FAILURE);
15082 case TNG_INT_DATA:
15083 size = sizeof(int64_t);
15084 break;
15085 case TNG_FLOAT_DATA:
15086 size = sizeof(float);
15087 break;
15088 case TNG_DOUBLE_DATA:
15089 default:
15090 size = sizeof(double);
15093 n_frames_div = (tot_n_frames % *stride_length) ?
15094 tot_n_frames / *stride_length + 1:
15095 tot_n_frames / *stride_length;
15096 data_size = n_frames_div * size * (*n_values_per_frame);
15098 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15099 size, n_frames_div, data_size);
15101 temp = realloc(*values, data_size);
15102 if(!temp)
15104 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15105 data_size, __FILE__, __LINE__);
15106 free(*values);
15107 *values = 0;
15108 return(TNG_CRITICAL);
15111 *values = temp;
15113 if( n_frames == 1 && n_frames < frame_set->n_frames)
15115 memcpy(*values, current_values, size * (*n_values_per_frame));
15117 else
15119 current_frame_pos = start_frame_nr - frame_set->first_frame;
15121 frame_size = size * (*n_values_per_frame);
15123 last_frame_pos = tng_min_i64(n_frames,
15124 end_frame_nr - start_frame_nr);
15126 n_frames_div = current_frame_pos / *stride_length;
15127 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15128 last_frame_pos / *stride_length + 1:
15129 last_frame_pos / *stride_length;
15130 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15132 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15133 n_frames_div_2 * frame_size);
15135 current_frame_pos += n_frames - current_frame_pos;
15137 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15139 stat = tng_frame_set_read_next(tng_data, hash_mode);
15140 if(stat != TNG_SUCCESS)
15142 if(current_values)
15144 free(current_values);
15146 free(*values);
15147 *values = 0;
15148 return(stat);
15151 stat = tng_data_vector_get(tng_data, block_id, &current_values,
15152 &n_frames, stride_length,
15153 n_values_per_frame, type);
15155 if(stat != TNG_SUCCESS)
15157 if(current_values)
15159 free(current_values);
15161 free(*values);
15162 *values = 0;
15163 return(stat);
15166 last_frame_pos = tng_min_i64(n_frames,
15167 end_frame_nr - current_frame_pos);
15169 n_frames_div = current_frame_pos / *stride_length;
15170 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15171 last_frame_pos / *stride_length + 1:
15172 last_frame_pos / *stride_length;
15173 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15175 memcpy(((char *)*values) + n_frames_div * frame_size,
15176 current_values,
15177 n_frames_div_2 * frame_size);
15179 current_frame_pos += n_frames;
15183 if(current_values)
15185 free(current_values);
15188 np_data->last_retrieved_frame = end_frame_nr;
15190 return(TNG_SUCCESS);
15193 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15194 (tng_trajectory_t tng_data,
15195 const int64_t block_id,
15196 union data_values ****values,
15197 int64_t *n_frames,
15198 int64_t *n_particles,
15199 int64_t *n_values_per_frame,
15200 char *type)
15202 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15203 int size;
15204 size_t len;
15205 tng_particle_data_t data;
15206 tng_trajectory_frame_set_t frame_set;
15207 tng_gen_block_t block;
15208 char block_type_flag;
15209 tng_function_status stat;
15211 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15212 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15213 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15214 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15215 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15217 frame_set = &tng_data->current_trajectory_frame_set;
15219 block_index = -1;
15220 data = 0;
15222 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15224 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15226 block_type_flag = TNG_TRAJECTORY_BLOCK;
15228 else
15230 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15233 tng_block_init(&block);
15234 file_pos = ftell(tng_data->input_file);
15235 /* Read all blocks until next frame set block */
15236 stat = tng_block_header_read(tng_data, block);
15237 while(file_pos < tng_data->input_file_len &&
15238 stat != TNG_CRITICAL &&
15239 block->id != TNG_TRAJECTORY_FRAME_SET)
15241 /* Use hash by default */
15242 stat = tng_block_read_next(tng_data, block,
15243 TNG_USE_HASH);
15244 if(stat != TNG_CRITICAL)
15246 file_pos = ftell(tng_data->input_file);
15247 if(file_pos < tng_data->input_file_len)
15249 stat = tng_block_header_read(tng_data, block);
15253 tng_block_destroy(&block);
15254 if(stat == TNG_CRITICAL)
15256 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15257 file_pos, __FILE__, __LINE__);
15258 return(stat);
15261 for(i = frame_set->n_particle_data_blocks; i-- ;)
15263 data = &frame_set->tr_particle_data[i];
15264 if(data->block_id == block_id)
15266 block_index = i;
15267 block_type_flag = TNG_TRAJECTORY_BLOCK;
15268 break;
15271 if(block_index < 0)
15273 return(TNG_FAILURE);
15276 else
15278 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15280 block_type_flag = TNG_TRAJECTORY_BLOCK;
15282 else
15284 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15288 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15289 tng_data->var_num_atoms_flag)
15291 *n_particles = frame_set->n_particles;
15293 else
15295 *n_particles = tng_data->n_particles;
15298 *n_frames = tng_max_i64(1, data->n_frames);
15299 *n_values_per_frame = data->n_values_per_frame;
15300 *type = data->datatype;
15302 if(*values == 0)
15304 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
15305 *n_particles, *n_values_per_frame,
15306 *type)
15307 != TNG_SUCCESS)
15309 return(TNG_CRITICAL);
15313 /* It's not very elegant to reuse so much of the code in the different case
15314 * statements, but it's unnecessarily slow to have the switch-case block
15315 * inside the for loops. */
15316 switch(*type)
15318 case TNG_CHAR_DATA:
15319 for(i=*n_frames; i--;)
15321 for(j=*n_particles; j--;)
15323 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15324 for(k=*n_values_per_frame; k--;)
15326 len = strlen(data->strings[i][j][k]) + 1;
15327 (*values)[i][mapping][k].c = malloc(len);
15328 strncpy((*values)[i][mapping][k].c,
15329 data->strings[i][j][k], len);
15333 break;
15334 case TNG_INT_DATA:
15335 size = sizeof(int);
15336 i_step = (*n_particles) * (*n_values_per_frame);
15337 for(i=*n_frames; i--;)
15339 for(j=*n_particles; j--;)
15341 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15342 for(k=*n_values_per_frame; k--;)
15344 (*values)[i][mapping][k].i = *(int *)
15345 ((char *)data->values + size *
15346 (i * i_step + j *
15347 (*n_values_per_frame) + k));
15351 break;
15352 case TNG_FLOAT_DATA:
15353 size = sizeof(float);
15354 i_step = (*n_particles) * (*n_values_per_frame);
15355 for(i=*n_frames; i--;)
15357 for(j=*n_particles; j--;)
15359 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15360 for(k=*n_values_per_frame; k--;)
15362 (*values)[i][mapping][k].f = *(float *)
15363 ((char *)data->values + size *
15364 (i * i_step + j *
15365 (*n_values_per_frame) + k));
15369 break;
15370 case TNG_DOUBLE_DATA:
15371 default:
15372 size = sizeof(double);
15373 i_step = (*n_particles) * (*n_values_per_frame);
15374 for(i=*n_frames; i--;)
15376 for(j=*n_particles; j--;)
15378 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15379 for(k=*n_values_per_frame; k--;)
15381 (*values)[i][mapping][k].d = *(double *)
15382 ((char *)data->values + size *
15383 (i * i_step + j *
15384 (*n_values_per_frame) + k));
15390 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15392 return(TNG_SUCCESS);
15395 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
15396 (tng_trajectory_t tng_data,
15397 const int64_t block_id,
15398 void **values,
15399 int64_t *n_frames,
15400 int64_t *stride_length,
15401 int64_t *n_particles,
15402 int64_t *n_values_per_frame,
15403 char *type)
15405 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
15406 int64_t block_index;
15407 int size;
15408 tng_particle_data_t data;
15409 tng_trajectory_frame_set_t frame_set;
15410 tng_gen_block_t block;
15411 void *temp;
15412 char block_type_flag;
15413 tng_function_status stat;
15415 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15416 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15417 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15418 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15419 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15421 frame_set = &tng_data->current_trajectory_frame_set;
15423 block_index = -1;
15424 data = 0;
15426 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15428 tng_block_init(&block);
15429 file_pos = ftell(tng_data->input_file);
15430 /* Read all blocks until next frame set block */
15431 stat = tng_block_header_read(tng_data, block);
15432 while(file_pos < tng_data->input_file_len &&
15433 stat != TNG_CRITICAL &&
15434 block->id != TNG_TRAJECTORY_FRAME_SET)
15436 /* Use hash by default */
15437 stat = tng_block_read_next(tng_data, block,
15438 TNG_USE_HASH);
15439 if(stat != TNG_CRITICAL)
15441 file_pos = ftell(tng_data->input_file);
15442 if(file_pos < tng_data->input_file_len)
15444 stat = tng_block_header_read(tng_data, block);
15448 tng_block_destroy(&block);
15449 if(stat == TNG_CRITICAL)
15451 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15452 file_pos, __FILE__, __LINE__);
15453 return(stat);
15456 for(i = frame_set->n_particle_data_blocks; i-- ;)
15458 data = &frame_set->tr_particle_data[i];
15459 if(data->block_id == block_id)
15461 block_index = i;
15462 break;
15465 if(block_index < 0)
15467 return(TNG_FAILURE);
15471 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15473 block_type_flag = TNG_TRAJECTORY_BLOCK;
15475 else
15477 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15480 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15481 tng_data->var_num_atoms_flag)
15483 *n_particles = frame_set->n_particles;
15485 else
15487 *n_particles = tng_data->n_particles;
15490 *type = data->datatype;
15492 switch(*type)
15494 case TNG_CHAR_DATA:
15495 return(TNG_FAILURE);
15496 case TNG_INT_DATA:
15497 size = sizeof(int64_t);
15498 break;
15499 case TNG_FLOAT_DATA:
15500 size = sizeof(float);
15501 break;
15502 case TNG_DOUBLE_DATA:
15503 default:
15504 size = sizeof(double);
15507 *n_frames = tng_max_i64(1, data->n_frames);
15508 *n_values_per_frame = data->n_values_per_frame;
15509 *stride_length = data->stride_length;
15511 n_frames_div = (*n_frames % *stride_length) ?
15512 *n_frames / *stride_length + 1:
15513 *n_frames / *stride_length;
15515 data_size = n_frames_div * size * (*n_particles) *
15516 (*n_values_per_frame);
15518 temp = realloc(*values, data_size);
15519 if(!temp)
15521 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15522 data_size, __FILE__, __LINE__);
15523 free(*values);
15524 *values = 0;
15525 return(TNG_CRITICAL);
15528 *values = temp;
15530 if(frame_set->n_mapping_blocks <= 0)
15532 memcpy(*values, data->values, data_size);
15534 else
15536 i_step = (*n_particles) * (*n_values_per_frame);
15537 for(i = *n_frames; i--;)
15539 for(j = *n_particles; j--;)
15541 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15542 memcpy(((char *)*values) + size * (i * i_step + mapping *
15543 (*n_values_per_frame)),
15544 (char *)data->values + size *
15545 (i * i_step + j * (*n_values_per_frame)),
15546 size * (*n_values_per_frame));
15551 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15553 return(TNG_SUCCESS);
15556 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15557 (tng_trajectory_t tng_data,
15558 const int64_t block_id,
15559 const int64_t start_frame_nr,
15560 const int64_t end_frame_nr,
15561 const char hash_mode,
15562 union data_values ****values,
15563 int64_t *n_particles,
15564 int64_t *n_values_per_frame,
15565 char *type)
15567 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
15568 int64_t first_frame, block_index;
15569 int size;
15570 size_t len;
15571 tng_particle_data_t data;
15572 tng_trajectory_frame_set_t frame_set;
15573 tng_gen_block_t block;
15574 char block_type_flag;
15575 tng_function_status stat;
15577 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15578 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15579 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15580 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15581 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15583 block_index = -1;
15585 frame_set = &tng_data->current_trajectory_frame_set;
15586 first_frame = frame_set->first_frame;
15588 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15589 if(stat != TNG_SUCCESS)
15591 return(stat);
15594 /* Do not re-read the frame set. */
15595 if(first_frame != frame_set->first_frame ||
15596 frame_set->n_particle_data_blocks <= 0)
15598 tng_block_init(&block);
15599 file_pos = ftell(tng_data->input_file);
15600 /* Read all blocks until next frame set block */
15601 stat = tng_block_header_read(tng_data, block);
15602 while(file_pos < tng_data->input_file_len &&
15603 stat != TNG_CRITICAL &&
15604 block->id != TNG_TRAJECTORY_FRAME_SET)
15606 stat = tng_block_read_next(tng_data, block,
15607 hash_mode);
15608 if(stat != TNG_CRITICAL)
15610 file_pos = ftell(tng_data->input_file);
15611 if(file_pos < tng_data->input_file_len)
15613 stat = tng_block_header_read(tng_data, block);
15617 tng_block_destroy(&block);
15618 if(stat == TNG_CRITICAL)
15620 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15621 file_pos, __FILE__, __LINE__);
15622 return(stat);
15626 /* See if there is already a data block of this ID.
15627 * Start checking the last read frame set */
15628 for(i = frame_set->n_particle_data_blocks; i-- ;)
15630 data = &frame_set->tr_particle_data[i];
15631 if(data->block_id == block_id)
15633 block_index = i;
15634 block_type_flag = TNG_TRAJECTORY_BLOCK;
15635 break;
15639 if(block_index < 0)
15641 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
15642 block_id, __FILE__, __LINE__);
15643 return(TNG_FAILURE);
15646 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15647 tng_data->var_num_atoms_flag)
15649 *n_particles = frame_set->n_particles;
15651 else
15653 *n_particles = tng_data->n_particles;
15656 n_frames = end_frame_nr - start_frame_nr + 1;
15657 *n_values_per_frame = data->n_values_per_frame;
15658 *type = data->datatype;
15660 if(*values == 0)
15662 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
15663 *n_particles, *n_values_per_frame,
15664 *type)
15665 != TNG_SUCCESS)
15667 return(TNG_CRITICAL);
15671 current_frame_pos = start_frame_nr - frame_set->first_frame;
15672 /* It's not very elegant to reuse so much of the code in the different case
15673 * statements, but it's unnecessarily slow to have the switch-case block
15674 * inside the for loops. */
15675 switch(*type)
15677 case TNG_CHAR_DATA:
15678 for(i=0; i<n_frames; i++)
15680 if(current_frame_pos == frame_set->n_frames)
15682 stat = tng_frame_set_read_next(tng_data, hash_mode);
15683 if(stat != TNG_SUCCESS)
15685 return(stat);
15687 current_frame_pos = 0;
15689 for(j=*n_particles; j--;)
15691 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15692 for(k=*n_values_per_frame; k--;)
15694 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
15695 (*values)[i][mapping][k].c = malloc(len);
15696 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
15699 current_frame_pos++;
15701 break;
15702 case TNG_INT_DATA:
15703 size = sizeof(int);
15704 i_step = (*n_particles) * (*n_values_per_frame);
15705 for(i=0; i<n_frames; i++)
15707 if(current_frame_pos == frame_set->n_frames)
15709 stat = tng_frame_set_read_next(tng_data, hash_mode);
15710 if(stat != TNG_SUCCESS)
15712 return(stat);
15714 current_frame_pos = 0;
15716 for(j=*n_particles; j--;)
15718 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15719 for(k=*n_values_per_frame; k--;)
15721 (*values)[i][mapping][k].i = *(int *)
15722 ((char *)data->values + size *
15723 (current_frame_pos *
15724 i_step + j *
15725 (*n_values_per_frame) + k));
15728 current_frame_pos++;
15730 break;
15731 case TNG_FLOAT_DATA:
15732 size = sizeof(float);
15733 i_step = (*n_particles) * (*n_values_per_frame);
15734 for(i=0; i<n_frames; i++)
15736 if(current_frame_pos == frame_set->n_frames)
15738 stat = tng_frame_set_read_next(tng_data, hash_mode);
15739 if(stat != TNG_SUCCESS)
15741 return(stat);
15743 current_frame_pos = 0;
15745 for(j=*n_particles; j--;)
15747 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15748 for(k=*n_values_per_frame; k--;)
15750 (*values)[i][mapping][k].f = *(float *)
15751 ((char *)data->values + size *
15752 (current_frame_pos *
15753 i_step + j *
15754 (*n_values_per_frame) + k));
15757 current_frame_pos++;
15759 break;
15760 case TNG_DOUBLE_DATA:
15761 default:
15762 size = sizeof(double);
15763 i_step = (*n_particles) * (*n_values_per_frame);
15764 for(i=0; i<n_frames; i++)
15766 if(current_frame_pos == frame_set->n_frames)
15768 stat = tng_frame_set_read_next(tng_data, hash_mode);
15769 if(stat != TNG_SUCCESS)
15771 return(stat);
15773 current_frame_pos = 0;
15775 for(j=*n_particles; j--;)
15777 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15778 for(k=*n_values_per_frame; k--;)
15780 (*values)[i][mapping][k].d = *(double *)
15781 ((char *)data->values + size *
15782 (current_frame_pos *
15783 i_step + j *
15784 (*n_values_per_frame) + k));
15787 current_frame_pos++;
15791 data->last_retrieved_frame = end_frame_nr;
15793 return(TNG_SUCCESS);
15796 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15797 (tng_trajectory_t tng_data,
15798 const int64_t block_id,
15799 const int64_t start_frame_nr,
15800 const int64_t end_frame_nr,
15801 const char hash_mode,
15802 void **values,
15803 int64_t *n_particles,
15804 int64_t *stride_length,
15805 int64_t *n_values_per_frame,
15806 char *type)
15808 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15809 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
15810 int size;
15811 tng_trajectory_frame_set_t frame_set;
15812 tng_particle_data_t p_data;
15813 tng_gen_block_t block;
15814 void *current_values = 0, *temp;
15815 tng_function_status stat;
15817 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15818 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15819 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15820 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15821 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15822 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15824 frame_set = &tng_data->current_trajectory_frame_set;
15825 first_frame = frame_set->first_frame;
15827 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15828 if(stat != TNG_SUCCESS)
15830 return(stat);
15833 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
15834 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
15835 stat = tng_particle_data_find(tng_data, block_id, &p_data);
15836 if(first_frame != frame_set->first_frame ||
15837 stat != TNG_SUCCESS)
15839 tng_block_init(&block);
15840 if(stat != TNG_SUCCESS)
15842 fseek(tng_data->input_file,
15843 (long)tng_data->current_trajectory_frame_set_input_file_pos,
15844 SEEK_SET);
15845 stat = tng_block_header_read(tng_data, block);
15846 if(stat != TNG_SUCCESS)
15848 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15849 __FILE__, __LINE__);
15850 return(stat);
15853 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15855 file_pos = ftell(tng_data->input_file);
15856 /* Read until next frame set block */
15857 stat = tng_block_header_read(tng_data, block);
15858 while(file_pos < tng_data->input_file_len &&
15859 stat != TNG_CRITICAL &&
15860 block->id != TNG_TRAJECTORY_FRAME_SET)
15862 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
15864 stat = tng_block_read_next(tng_data, block,
15865 hash_mode);
15866 if(stat != TNG_CRITICAL)
15868 file_pos = ftell(tng_data->input_file);
15869 if(file_pos < tng_data->input_file_len)
15871 stat = tng_block_header_read(tng_data, block);
15875 else
15877 file_pos += block->block_contents_size + block->header_contents_size;
15878 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15879 if(file_pos < tng_data->input_file_len)
15881 stat = tng_block_header_read(tng_data, block);
15885 tng_block_destroy(&block);
15886 if(stat == TNG_CRITICAL)
15888 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15889 file_pos, __FILE__, __LINE__);
15890 return(stat);
15893 stat = tng_particle_data_find(tng_data, block_id, &p_data);
15894 if(stat != TNG_SUCCESS)
15896 return(stat);
15899 stat = tng_particle_data_vector_get(tng_data, block_id, &current_values,
15900 &n_frames, stride_length, n_particles,
15901 n_values_per_frame, type);
15903 if(stat != TNG_SUCCESS || *n_particles == 0)
15905 if(current_values)
15907 free(current_values);
15909 return(stat);
15912 if(n_frames == 1 && n_frames < frame_set->n_frames)
15914 tot_n_frames = 1;
15916 else
15918 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15921 switch(*type)
15923 case TNG_CHAR_DATA:
15924 return(TNG_FAILURE);
15925 case TNG_INT_DATA:
15926 size = sizeof(int64_t);
15927 break;
15928 case TNG_FLOAT_DATA:
15929 size = sizeof(float);
15930 break;
15931 case TNG_DOUBLE_DATA:
15932 default:
15933 size = sizeof(double);
15936 n_frames_div = (tot_n_frames % *stride_length) ?
15937 tot_n_frames / *stride_length + 1:
15938 tot_n_frames / *stride_length;
15940 data_size = n_frames_div * size * (*n_particles) *
15941 (*n_values_per_frame);
15943 temp = realloc(*values, data_size);
15944 if(!temp)
15946 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15947 data_size, __FILE__, __LINE__);
15948 free(*values);
15949 *values = 0;
15950 return(TNG_CRITICAL);
15953 *values = temp;
15955 if( n_frames == 1 && n_frames < frame_set->n_frames)
15957 memcpy(*values, current_values, size * (*n_particles) *
15958 (*n_values_per_frame));
15960 else
15962 current_frame_pos = start_frame_nr - frame_set->first_frame;
15964 frame_size = size * (*n_particles) * (*n_values_per_frame);
15966 last_frame_pos = tng_min_i64(n_frames,
15967 end_frame_nr - start_frame_nr);
15969 n_frames_div = current_frame_pos / *stride_length;
15970 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15971 last_frame_pos / *stride_length + 1:
15972 last_frame_pos / *stride_length;
15973 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
15975 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15976 n_frames_div_2 * frame_size);
15978 current_frame_pos += n_frames - current_frame_pos;
15980 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15982 stat = tng_frame_set_read_next(tng_data, hash_mode);
15983 if(stat != TNG_SUCCESS)
15985 if(current_values)
15987 free(current_values);
15989 free(*values);
15990 *values = 0;
15991 return(stat);
15994 stat = tng_particle_data_vector_get(tng_data, block_id, &current_values,
15995 &n_frames, stride_length, n_particles,
15996 n_values_per_frame, type);
15998 if(stat != TNG_SUCCESS)
16000 if(current_values)
16002 free(current_values);
16004 free(*values);
16005 *values = 0;
16006 return(stat);
16009 last_frame_pos = tng_min_i64(n_frames,
16010 end_frame_nr - current_frame_pos);
16012 n_frames_div = current_frame_pos / *stride_length;
16013 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16014 last_frame_pos / *stride_length + 1:
16015 last_frame_pos / *stride_length;
16016 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16018 memcpy(((char *)*values) + n_frames_div * frame_size,
16019 current_values,
16020 n_frames_div_2 * frame_size);
16022 current_frame_pos += n_frames;
16026 if(current_values)
16028 free(current_values);
16031 p_data->last_retrieved_frame = end_frame_nr;
16033 return(TNG_SUCCESS);
16036 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16037 (const tng_trajectory_t tng_data,
16038 const int64_t block_id,
16039 int64_t frame,
16040 int64_t *stride_length)
16042 tng_function_status stat;
16043 tng_non_particle_data_t np_data;
16044 tng_particle_data_t p_data;
16045 long orig_file_pos, file_pos;
16046 int is_particle_data;
16048 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16050 frame = 0;
16053 if(frame >= 0)
16055 stat = tng_frame_set_of_frame_find(tng_data, frame);
16056 if(stat != TNG_SUCCESS)
16058 return(stat);
16061 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16062 stat = tng_data_find(tng_data, block_id, &np_data);
16063 if(stat != TNG_SUCCESS)
16065 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16066 if(stat != TNG_SUCCESS)
16068 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16069 /* If no specific frame was required read until this data block is found */
16070 if(frame < 0)
16072 file_pos = ftell(tng_data->input_file);
16073 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16075 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16076 file_pos = ftell(tng_data->input_file);
16079 if(stat != TNG_SUCCESS)
16081 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16083 return(stat);
16085 stat = tng_data_find(tng_data, block_id, &np_data);
16086 if(stat != TNG_SUCCESS)
16088 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16089 if(stat != TNG_SUCCESS)
16091 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16093 return(stat);
16095 else
16097 is_particle_data = 1;
16100 else
16102 is_particle_data = 0;
16105 else
16107 is_particle_data = 1;
16110 else
16112 is_particle_data = 0;
16114 if(is_particle_data)
16116 *stride_length = p_data->stride_length;
16118 else
16120 *stride_length = np_data->stride_length;
16122 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16124 return(TNG_SUCCESS);
16127 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16128 (const tng_trajectory_t tng_data,
16129 char *time)
16131 struct tm *time_data;
16132 time_t secs;
16134 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16135 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16137 secs = tng_data->time;
16139 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16140 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16141 "%4d-%02d-%02d %02d:%02d:%02d",
16142 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16143 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16145 return(TNG_SUCCESS);
16149 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16150 (const char *filename,
16151 const char mode,
16152 tng_trajectory_t *tng_data_p)
16154 tng_function_status stat;
16156 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16158 if(mode != 'r' && mode != 'w' && mode != 'a')
16160 return(TNG_FAILURE);
16163 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16165 tng_trajectory_destroy(tng_data_p);
16166 return(TNG_CRITICAL);
16169 if(mode == 'r' || mode == 'a')
16171 tng_input_file_set(*tng_data_p, filename);
16173 /* Read the file headers */
16174 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16176 tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16179 if(mode == 'w')
16181 tng_output_file_set(*tng_data_p, filename);
16183 else if(mode == 'a')
16185 fseek((*tng_data_p)->input_file,
16186 (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16187 SEEK_SET);
16189 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16190 if(stat != TNG_SUCCESS)
16192 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16193 __FILE__, __LINE__);
16196 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16197 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16198 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16199 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16200 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16201 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16202 (*tng_data_p)->first_trajectory_frame_set_input_file_pos = -1;
16203 (*tng_data_p)->last_trajectory_frame_set_input_file_pos = -1;
16204 (*tng_data_p)->current_trajectory_frame_set_input_file_pos = -1;
16205 if((*tng_data_p)->input_file)
16207 fclose((*tng_data_p)->input_file);
16208 (*tng_data_p)->input_file = 0;
16210 if((*tng_data_p)->input_file_path)
16212 free((*tng_data_p)->input_file_path);
16213 (*tng_data_p)->input_file_path = 0;
16215 tng_output_append_file_set(*tng_data_p, filename);
16217 fseek((*tng_data_p)->output_file, 0, SEEK_END);
16220 return(TNG_SUCCESS);
16223 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
16224 (tng_trajectory_t *tng_data_p)
16226 tng_trajectory_frame_set_t frame_set;
16228 if(tng_data_p == 0)
16230 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
16231 __FILE__, __LINE__);
16232 return(TNG_FAILURE);
16235 if(*tng_data_p == 0)
16237 return(TNG_SUCCESS);
16240 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
16242 if(frame_set->n_unwritten_frames > 0)
16244 frame_set->n_frames = frame_set->n_unwritten_frames;
16245 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
16248 return(tng_trajectory_destroy(tng_data_p));
16251 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
16252 (tng_trajectory_t tng_data,
16253 const int64_t frame_nr,
16254 double *time)
16256 int64_t first_frame;
16257 tng_trajectory_frame_set_t frame_set;
16258 tng_function_status stat;
16260 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16261 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16263 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
16264 if(stat != TNG_SUCCESS)
16266 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
16267 frame_nr, __FILE__, __LINE__);
16268 return(stat);
16271 frame_set = &tng_data->current_trajectory_frame_set;
16272 first_frame = frame_set->first_frame;
16274 if(tng_data->time_per_frame <= 0)
16276 return(TNG_FAILURE);
16279 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
16281 return(TNG_SUCCESS);
16285 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
16286 (tng_trajectory_t tng_data,
16287 int64_t *n_mols,
16288 int64_t **molecule_cnt_list,
16289 tng_molecule_t *mols)
16291 tng_trajectory_frame_set_t frame_set;
16293 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16294 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
16296 *n_mols = tng_data->n_molecules;
16298 frame_set = &tng_data->current_trajectory_frame_set;
16299 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
16301 *molecule_cnt_list = frame_set->molecule_cnt_list;
16303 else
16305 *molecule_cnt_list = tng_data->molecule_cnt_list;
16308 *mols = tng_data->molecules;
16310 return(TNG_SUCCESS);
16314 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
16315 (tng_trajectory_t tng_data,
16316 const char *name,
16317 const int64_t cnt,
16318 tng_molecule_t *mol)
16320 tng_function_status stat;
16322 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
16323 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
16325 stat = tng_molecule_add(tng_data, name, mol);
16326 if(stat != TNG_SUCCESS)
16328 return(stat);
16330 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
16332 return(stat);
16335 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
16336 (tng_trajectory_t tng_data,
16337 const tng_molecule_t mol,
16338 int64_t *n_particles,
16339 char ***names,
16340 char ***types,
16341 char ***res_names,
16342 int64_t **res_ids,
16343 char ***chain_names,
16344 int64_t **chain_ids)
16346 tng_atom_t atom;
16347 tng_residue_t res;
16348 tng_chain_t chain;
16349 int64_t i;
16350 (void)tng_data;
16352 *n_particles = mol->n_atoms;
16354 *names = malloc(sizeof(char *) * *n_particles);
16355 *types = malloc(sizeof(char *) * *n_particles);
16356 *res_names = malloc(sizeof(char *) * *n_particles);
16357 *chain_names = malloc(sizeof(char *) * *n_particles);
16358 *res_ids = malloc(sizeof(int64_t) * *n_particles);
16359 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
16361 for(i = 0; i < *n_particles; i++)
16363 atom = &mol->atoms[i];
16364 res = atom->residue;
16365 chain = res->chain;
16366 (*names)[i] = malloc(strlen(atom->name));
16367 strcpy(*names[i], atom->name);
16368 (*types)[i] = malloc(strlen(atom->atom_type));
16369 strcpy(*types[i], atom->atom_type);
16370 (*res_names)[i] = malloc(strlen(res->name));
16371 strcpy(*res_names[i], res->name);
16372 (*chain_names)[i] = malloc(strlen(chain->name));
16373 strcpy(*chain_names[i], chain->name);
16374 (*res_ids)[i] = res->id;
16375 (*chain_ids)[i] = chain->id;
16378 return(TNG_SUCCESS);
16381 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
16382 (tng_trajectory_t tng_data,
16383 tng_molecule_t mol,
16384 const int64_t n_particles,
16385 const char **names,
16386 const char **types,
16387 const char **res_names,
16388 const int64_t *res_ids,
16389 const char **chain_names,
16390 const int64_t *chain_ids)
16392 int64_t i;
16393 tng_chain_t chain;
16394 tng_residue_t residue;
16395 tng_atom_t atom;
16396 tng_function_status stat;
16398 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16399 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
16400 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
16401 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
16402 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
16403 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
16404 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
16406 for(i = 0; i < n_particles; i++)
16408 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
16409 &chain) == TNG_FAILURE)
16411 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
16412 &chain);
16413 if(stat != TNG_SUCCESS)
16415 return(stat);
16418 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
16419 &residue) == TNG_FAILURE)
16421 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
16422 &residue);
16423 if(stat != TNG_SUCCESS)
16425 return(stat);
16428 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
16429 if(stat != TNG_SUCCESS)
16431 return(stat);
16434 return(TNG_SUCCESS);
16437 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
16438 (tng_trajectory_t tng_data,
16439 float **positions, int64_t *stride_length)
16441 int64_t n_frames, n_particles, n_values_per_frame;
16442 char type;
16443 tng_function_status stat;
16445 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16446 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16447 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16449 stat = tng_num_frames_get(tng_data, &n_frames);
16450 if(stat != TNG_SUCCESS)
16452 return(stat);
16455 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
16456 0, n_frames - 1, TNG_USE_HASH,
16457 (void **)positions,
16458 &n_particles,
16459 stride_length,
16460 &n_values_per_frame,
16461 &type);
16463 return(stat);
16466 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
16467 (tng_trajectory_t tng_data,
16468 float **velocities, int64_t *stride_length)
16470 int64_t n_frames, n_particles, n_values_per_frame;
16471 char type;
16472 tng_function_status stat;
16474 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16475 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16476 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16478 stat = tng_num_frames_get(tng_data, &n_frames);
16479 if(stat != TNG_SUCCESS)
16481 return(stat);
16484 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
16485 0, n_frames - 1, TNG_USE_HASH,
16486 (void **)velocities,
16487 &n_particles,
16488 stride_length,
16489 &n_values_per_frame,
16490 &type);
16492 return(stat);
16495 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
16496 (tng_trajectory_t tng_data,
16497 float **forces, int64_t *stride_length)
16499 int64_t n_frames, n_particles, n_values_per_frame;
16500 char type;
16501 tng_function_status stat;
16503 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16504 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16505 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16507 stat = tng_num_frames_get(tng_data, &n_frames);
16508 if(stat != TNG_SUCCESS)
16510 return(stat);
16513 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16514 0, n_frames - 1, TNG_USE_HASH,
16515 (void **)forces,
16516 &n_particles,
16517 stride_length,
16518 &n_values_per_frame,
16519 &type);
16521 return(stat);
16524 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
16525 (tng_trajectory_t tng_data,
16526 float **box_shape,
16527 int64_t *stride_length)
16529 int64_t n_frames, n_values_per_frame;
16530 char type;
16531 tng_function_status stat;
16533 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16534 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16535 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16537 stat = tng_num_frames_get(tng_data, &n_frames);
16538 if(stat != TNG_SUCCESS)
16540 return(stat);
16543 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16544 0, n_frames - 1, TNG_USE_HASH,
16545 (void **)box_shape,
16546 stride_length,
16547 &n_values_per_frame,
16548 &type);
16550 return(stat);
16553 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
16554 (tng_trajectory_t tng_data,
16555 const int64_t block_id,
16556 void **values,
16557 char *data_type,
16558 int64_t *retrieved_frame_number,
16559 double *retrieved_time)
16561 tng_trajectory_frame_set_t frame_set;
16562 tng_particle_data_t data = 0;
16563 tng_function_status stat;
16564 int size;
16565 int64_t i, data_size, n_particles;
16566 void *temp;
16567 long file_pos;
16569 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16570 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
16571 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
16572 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
16573 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
16575 frame_set = &tng_data->current_trajectory_frame_set;
16577 stat = tng_particle_data_find(tng_data, block_id, &data);
16578 if(stat != TNG_SUCCESS)
16580 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16581 file_pos = ftell(tng_data->input_file);
16582 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16584 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16585 file_pos = ftell(tng_data->input_file);
16587 if(stat != TNG_SUCCESS)
16589 return(stat);
16591 stat = tng_particle_data_find(tng_data, block_id, &data);
16592 if(stat != TNG_SUCCESS)
16594 return(stat);
16597 if(data->last_retrieved_frame < 0)
16599 fseek(tng_data->input_file,
16600 (long)tng_data->first_trajectory_frame_set_input_file_pos,
16601 SEEK_SET);
16602 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
16603 if(stat != TNG_SUCCESS)
16605 return(stat);
16607 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16608 if(stat != TNG_SUCCESS)
16610 return(stat);
16613 i = data->first_frame_with_data;
16615 else
16617 if(data->n_frames == 1)
16619 i = data->last_retrieved_frame + 1;
16621 else
16623 i = data->last_retrieved_frame + data->stride_length;
16625 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
16627 stat = tng_frame_set_of_frame_find(tng_data, i);
16628 if(stat != TNG_SUCCESS)
16630 /* If the frame set search found the frame set after the starting
16631 * frame set there is a gap in the frame sets. So, even if the frame
16632 * was not found the next frame with data is still in the found
16633 * frame set. */
16634 if(stat == TNG_CRITICAL)
16636 return(stat);
16638 i = frame_set->first_frame;
16641 if(data->last_retrieved_frame < frame_set->first_frame)
16643 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16644 if(stat != TNG_SUCCESS)
16646 return(stat);
16650 data->last_retrieved_frame = i;
16651 *retrieved_frame_number = i;
16652 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
16654 *retrieved_time = frame_set->first_frame_time +
16655 (i - frame_set->first_frame) *
16656 tng_data->time_per_frame;
16658 else
16660 *retrieved_time = 0;
16663 if(data->stride_length > 1)
16665 i = (i - data->first_frame_with_data) / data->stride_length;
16667 else
16669 i = (i - frame_set->first_frame);
16672 tng_num_particles_get(tng_data, &n_particles);
16674 *data_type = data->datatype;
16676 switch(*data_type)
16678 case TNG_CHAR_DATA:
16679 return(TNG_FAILURE);
16680 case TNG_INT_DATA:
16681 size = sizeof(int64_t);
16682 break;
16683 case TNG_FLOAT_DATA:
16684 size = sizeof(float);
16685 break;
16686 case TNG_DOUBLE_DATA:
16687 default:
16688 size = sizeof(double);
16691 data_size = size * n_particles * data->n_values_per_frame;
16693 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
16694 // i, data_size, size, n_particles, data->n_values_per_frame);
16696 temp = realloc(*values, data_size);
16697 if(!temp)
16699 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16700 data_size, __FILE__, __LINE__);
16701 free(*values);
16702 *values = 0;
16703 return(TNG_CRITICAL);
16706 *values = temp;
16708 memcpy(*values, (char *)data->values + i * data_size, data_size);
16710 return(TNG_SUCCESS);
16713 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
16714 (tng_trajectory_t tng_data,
16715 const int64_t block_id,
16716 void **values,
16717 char *data_type,
16718 int64_t *retrieved_frame_number,
16719 double *retrieved_time)
16721 tng_trajectory_frame_set_t frame_set;
16722 tng_non_particle_data_t data = 0;
16723 tng_function_status stat;
16724 int size;
16725 int64_t i, data_size;
16726 void *temp;
16727 long file_pos;
16729 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16730 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
16731 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
16732 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
16733 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
16735 frame_set = &tng_data->current_trajectory_frame_set;
16737 stat = tng_data_find(tng_data, block_id, &data);
16738 if(stat != TNG_SUCCESS)
16740 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16741 file_pos = ftell(tng_data->input_file);
16742 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16744 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16745 file_pos = ftell(tng_data->input_file);
16747 if(stat != TNG_SUCCESS)
16749 return(stat);
16751 stat = tng_data_find(tng_data, block_id, &data);
16752 if(stat != TNG_SUCCESS)
16754 return(stat);
16757 if(data->last_retrieved_frame < 0)
16759 fseek(tng_data->input_file,
16760 (long)tng_data->first_trajectory_frame_set_input_file_pos,
16761 SEEK_SET);
16762 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
16763 if(stat != TNG_SUCCESS)
16765 return(stat);
16767 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16768 if(stat != TNG_SUCCESS)
16770 return(stat);
16773 i = data->first_frame_with_data;
16775 else
16777 if(data->n_frames == 1)
16779 i = data->last_retrieved_frame + 1;
16781 else
16783 i = data->last_retrieved_frame + data->stride_length;
16785 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
16787 stat = tng_frame_set_of_frame_find(tng_data, i);
16788 if(stat != TNG_SUCCESS)
16790 /* If the frame set search found the frame set after the starting
16791 * frame set there is a gap in the frame sets. So, even if the frame
16792 * was not found the next frame with data is still in the found
16793 * frame set. */
16794 if(stat == TNG_CRITICAL)
16796 return(stat);
16798 i = frame_set->first_frame;
16801 if(data->last_retrieved_frame < frame_set->first_frame)
16803 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16804 if(stat != TNG_SUCCESS)
16806 return(stat);
16810 data->last_retrieved_frame = i;
16811 *retrieved_frame_number = i;
16812 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
16814 *retrieved_time = frame_set->first_frame_time +
16815 (i - frame_set->first_frame) *
16816 tng_data->time_per_frame;
16818 else
16820 *retrieved_time = 0;
16823 if(data->stride_length > 1)
16825 i = (i - data->first_frame_with_data) / data->stride_length;
16827 else
16829 i = (i - frame_set->first_frame);
16832 *data_type = data->datatype;
16834 switch(*data_type)
16836 case TNG_CHAR_DATA:
16837 return(TNG_FAILURE);
16838 case TNG_INT_DATA:
16839 size = sizeof(int64_t);
16840 break;
16841 case TNG_FLOAT_DATA:
16842 size = sizeof(float);
16843 break;
16844 case TNG_DOUBLE_DATA:
16845 default:
16846 size = sizeof(double);
16849 data_size = size * data->n_values_per_frame;
16851 temp = realloc(*values, data_size);
16852 if(!temp)
16854 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16855 data_size, __FILE__, __LINE__);
16856 free(*values);
16857 *values = 0;
16858 return(TNG_CRITICAL);
16861 *values = temp;
16863 memcpy(*values, (char *)data->values + i * data_size, data_size);
16865 return(TNG_SUCCESS);
16868 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
16869 (tng_trajectory_t tng_data,
16870 const int64_t first_frame,
16871 const int64_t last_frame,
16872 float **positions,
16873 int64_t *stride_length)
16875 int64_t n_particles, n_values_per_frame;
16876 char type;
16877 tng_function_status stat;
16879 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16880 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16881 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16882 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16884 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
16885 first_frame, last_frame,
16886 TNG_USE_HASH,
16887 (void **)positions,
16888 &n_particles,
16889 stride_length,
16890 &n_values_per_frame,
16891 &type);
16893 return(stat);
16896 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
16897 (tng_trajectory_t tng_data,
16898 const int64_t first_frame,
16899 const int64_t last_frame,
16900 float **velocities,
16901 int64_t *stride_length)
16903 int64_t n_particles, n_values_per_frame;
16904 char type;
16905 tng_function_status stat;
16907 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16908 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16909 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16910 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16912 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
16913 first_frame, last_frame,
16914 TNG_USE_HASH,
16915 (void **)velocities,
16916 &n_particles,
16917 stride_length,
16918 &n_values_per_frame,
16919 &type);
16921 return(stat);
16924 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
16925 (tng_trajectory_t tng_data,
16926 const int64_t first_frame,
16927 const int64_t last_frame,
16928 float **forces,
16929 int64_t *stride_length)
16931 int64_t n_particles, n_values_per_frame;
16932 char type;
16933 tng_function_status stat;
16935 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16936 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16937 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16938 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16940 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16941 first_frame, last_frame,
16942 TNG_USE_HASH,
16943 (void **)forces,
16944 &n_particles,
16945 stride_length,
16946 &n_values_per_frame,
16947 &type);
16949 return(stat);
16952 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16953 (tng_trajectory_t tng_data,
16954 const int64_t first_frame,
16955 const int64_t last_frame,
16956 float **box_shape,
16957 int64_t *stride_length)
16959 int64_t n_values_per_frame;
16960 char type;
16961 tng_function_status stat;
16963 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16964 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16965 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16966 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16968 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16969 first_frame, last_frame,
16970 TNG_USE_HASH,
16971 (void **)box_shape,
16972 stride_length,
16973 &n_values_per_frame,
16974 &type);
16976 return(stat);
16979 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16980 (tng_trajectory_t tng_data,
16981 const int64_t i,
16982 const int64_t n_values_per_frame,
16983 const int64_t block_id,
16984 const char *block_name,
16985 const char particle_dependency,
16986 const char compression)
16988 tng_trajectory_frame_set_t frame_set;
16989 tng_particle_data_t p_data;
16990 tng_non_particle_data_t np_data;
16991 int64_t n_particles, n_frames;
16992 tng_function_status stat;
16994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16995 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16997 if(i <= 0)
16999 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17000 i, __FILE__, __LINE__);
17001 return(TNG_FAILURE);
17004 frame_set = &tng_data->current_trajectory_frame_set;
17006 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17008 n_frames = tng_data->frame_set_n_frames;
17010 stat = tng_frame_set_new(tng_data, 0, n_frames);
17011 if(stat != TNG_SUCCESS)
17013 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17014 __LINE__);
17015 return(stat);
17018 else
17020 n_frames = frame_set->n_frames;
17023 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17025 tng_num_particles_get(tng_data, &n_particles);
17026 if(n_particles <= 0)
17028 return(TNG_FAILURE);
17031 if(tng_particle_data_find(tng_data, block_id, &p_data)
17032 != TNG_SUCCESS)
17034 stat = tng_particle_data_block_add(tng_data, block_id,
17035 block_name,
17036 TNG_FLOAT_DATA,
17037 TNG_TRAJECTORY_BLOCK,
17038 n_frames, n_values_per_frame, i,
17039 0, n_particles,
17040 compression, 0);
17041 if(stat != TNG_SUCCESS)
17043 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17044 __FILE__, __LINE__);
17045 return(stat);
17047 p_data = &frame_set->tr_particle_data[frame_set->
17048 n_particle_data_blocks - 1];
17049 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17050 i, n_particles,
17051 n_values_per_frame);
17052 if(stat != TNG_SUCCESS)
17054 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17055 __FILE__, __LINE__);
17056 return(stat);
17059 else
17061 if(p_data->stride_length != i)
17063 p_data->stride_length = i;
17064 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17065 i, n_particles,
17066 n_values_per_frame);
17067 if(stat != TNG_SUCCESS)
17069 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17070 __FILE__, __LINE__);
17071 return(stat);
17076 else
17078 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17080 stat = tng_data_block_add(tng_data, block_id, block_name,
17081 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17082 n_frames, n_values_per_frame,
17083 i, compression, 0);
17084 if(stat != TNG_SUCCESS)
17086 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17087 __FILE__, __LINE__);
17088 return(stat);
17090 np_data = &frame_set->tr_data[frame_set->
17091 n_data_blocks - 1];
17092 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17093 i, n_values_per_frame);
17094 if(stat != TNG_SUCCESS)
17096 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17097 __FILE__, __LINE__);
17098 return(stat);
17101 else
17103 if(np_data->stride_length != i)
17105 np_data->stride_length = i;
17106 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17107 i, n_values_per_frame);
17108 if(stat != TNG_SUCCESS)
17110 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17111 __FILE__, __LINE__);
17112 return(stat);
17118 return(TNG_SUCCESS);
17121 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17122 (tng_trajectory_t tng_data,
17123 const int64_t i,
17124 const int64_t n_values_per_frame,
17125 const int64_t block_id,
17126 const char *block_name,
17127 const char particle_dependency,
17128 const char compression)
17130 tng_trajectory_frame_set_t frame_set;
17131 tng_particle_data_t p_data;
17132 tng_non_particle_data_t np_data;
17133 int64_t n_particles, n_frames;
17134 tng_function_status stat;
17136 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17137 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17139 if(i <= 0)
17141 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17142 i, __FILE__, __LINE__);
17143 return(TNG_FAILURE);
17146 frame_set = &tng_data->current_trajectory_frame_set;
17148 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17150 n_frames = tng_data->frame_set_n_frames;
17152 stat = tng_frame_set_new(tng_data, 0, n_frames);
17153 if(stat != TNG_SUCCESS)
17155 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17156 __LINE__);
17157 return(stat);
17160 else
17162 n_frames = frame_set->n_frames;
17165 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17167 tng_num_particles_get(tng_data, &n_particles);
17169 if(n_particles <= 0)
17171 return(TNG_FAILURE);
17174 if(tng_particle_data_find(tng_data, block_id, &p_data)
17175 != TNG_SUCCESS)
17177 stat = tng_particle_data_block_add(tng_data, block_id,
17178 block_name,
17179 TNG_DOUBLE_DATA,
17180 TNG_TRAJECTORY_BLOCK,
17181 n_frames, n_values_per_frame, i,
17182 0, n_particles,
17183 compression, 0);
17184 if(stat != TNG_SUCCESS)
17186 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17187 __FILE__, __LINE__);
17188 return(stat);
17190 p_data = &frame_set->tr_particle_data[frame_set->
17191 n_particle_data_blocks - 1];
17192 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17193 i, n_particles,
17194 n_values_per_frame);
17195 if(stat != TNG_SUCCESS)
17197 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17198 __FILE__, __LINE__);
17199 return(stat);
17202 else
17204 p_data->stride_length = i;
17207 else
17209 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17211 stat = tng_data_block_add(tng_data, block_id, block_name,
17212 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
17213 n_frames, n_values_per_frame,
17214 i, compression, 0);
17215 if(stat != TNG_SUCCESS)
17217 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17218 __FILE__, __LINE__);
17219 return(stat);
17221 np_data = &frame_set->tr_data[frame_set->
17222 n_data_blocks - 1];
17223 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17224 i, n_values_per_frame);
17225 if(stat != TNG_SUCCESS)
17227 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17228 __FILE__, __LINE__);
17229 return(stat);
17232 else
17234 np_data->stride_length = i;
17238 return(TNG_SUCCESS);
17241 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
17242 (tng_trajectory_t tng_data,
17243 const int64_t i,
17244 const int64_t n_values_per_frame,
17245 const int64_t block_id,
17246 const char *block_name,
17247 const char particle_dependency,
17248 const char compression)
17250 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
17251 "See documentation. %s: %d", __FILE__, __LINE__);
17252 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
17253 block_id, block_name,
17254 particle_dependency,
17255 compression));
17257 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
17258 (tng_trajectory_t tng_data,
17259 const int64_t i)
17261 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17262 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17264 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17265 TNG_TRAJ_POSITIONS,
17266 "POSITIONS",
17267 TNG_PARTICLE_BLOCK_DATA,
17268 TNG_TNG_COMPRESSION));
17271 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
17272 (tng_trajectory_t tng_data,
17273 const int64_t i)
17275 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17276 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17278 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17279 TNG_TRAJ_POSITIONS,
17280 "POSITIONS",
17281 TNG_PARTICLE_BLOCK_DATA,
17282 TNG_TNG_COMPRESSION));
17285 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
17286 (tng_trajectory_t tng_data,
17287 const int64_t i)
17289 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
17290 "See documentation. %s: %d", __FILE__, __LINE__);
17291 return(tng_util_pos_write_interval_set(tng_data, i));
17294 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
17295 (tng_trajectory_t tng_data,
17296 const int64_t i)
17298 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17299 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17301 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17302 TNG_TRAJ_VELOCITIES,
17303 "VELOCITIES",
17304 TNG_PARTICLE_BLOCK_DATA,
17305 TNG_TNG_COMPRESSION));
17308 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
17309 (tng_trajectory_t tng_data,
17310 const int64_t i)
17312 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17313 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17315 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17316 TNG_TRAJ_VELOCITIES,
17317 "VELOCITIES",
17318 TNG_PARTICLE_BLOCK_DATA,
17319 TNG_TNG_COMPRESSION));
17322 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
17323 (tng_trajectory_t tng_data,
17324 const int64_t i)
17326 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
17327 "See documentation. %s: %d", __FILE__, __LINE__);
17328 return(tng_util_vel_write_interval_set(tng_data, i));
17331 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
17332 (tng_trajectory_t tng_data,
17333 const int64_t i)
17335 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17336 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17338 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17339 TNG_TRAJ_FORCES,
17340 "FORCES",
17341 TNG_PARTICLE_BLOCK_DATA,
17342 TNG_GZIP_COMPRESSION));
17345 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
17346 (tng_trajectory_t tng_data,
17347 const int64_t i)
17349 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17350 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17352 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17353 TNG_TRAJ_FORCES,
17354 "FORCES",
17355 TNG_PARTICLE_BLOCK_DATA,
17356 TNG_GZIP_COMPRESSION));
17359 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
17360 (tng_trajectory_t tng_data,
17361 const int64_t i)
17363 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
17364 "See documentation. %s: %d", __FILE__, __LINE__);
17365 return(tng_util_force_write_interval_set(tng_data, i));
17368 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
17369 (tng_trajectory_t tng_data,
17370 const int64_t i)
17372 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17373 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17375 return(tng_util_generic_write_interval_set(tng_data, i, 9,
17376 TNG_TRAJ_BOX_SHAPE,
17377 "BOX SHAPE",
17378 TNG_NON_PARTICLE_BLOCK_DATA,
17379 TNG_GZIP_COMPRESSION));
17382 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
17383 (tng_trajectory_t tng_data,
17384 const int64_t i)
17386 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17387 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17389 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
17390 TNG_TRAJ_BOX_SHAPE,
17391 "BOX SHAPE",
17392 TNG_NON_PARTICLE_BLOCK_DATA,
17393 TNG_GZIP_COMPRESSION));
17396 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
17397 (tng_trajectory_t tng_data,
17398 const int64_t i)
17400 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
17401 "See documentation. %s: %d", __FILE__, __LINE__);
17402 return(tng_util_box_shape_write_interval_set(tng_data, i));
17405 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
17406 (tng_trajectory_t tng_data,
17407 const int64_t frame_nr,
17408 const float *values,
17409 const int64_t n_values_per_frame,
17410 const int64_t block_id,
17411 const char *block_name,
17412 const char particle_dependency,
17413 const char compression)
17415 tng_trajectory_frame_set_t frame_set;
17416 tng_particle_data_t p_data;
17417 tng_non_particle_data_t np_data;
17418 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
17419 int64_t last_frame;
17420 int is_first_frame_flag = 0;
17421 char block_type_flag;
17422 tng_function_status stat;
17424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17425 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17426 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17428 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17430 tng_num_particles_get(tng_data, &n_particles);
17431 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
17434 if(values == 0)
17436 return(TNG_FAILURE);
17439 frame_set = &tng_data->current_trajectory_frame_set;
17441 if(frame_nr < 0)
17443 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
17444 n_frames = stride_length = 1;
17446 else
17448 block_type_flag = TNG_TRAJECTORY_BLOCK;
17450 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17452 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
17453 if(stat != TNG_SUCCESS)
17455 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17456 __LINE__);
17457 return(stat);
17460 last_frame = frame_set->first_frame +
17461 frame_set->n_frames - 1;
17462 if(frame_nr > last_frame)
17464 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
17465 if(stat != TNG_SUCCESS)
17467 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
17468 __LINE__);
17469 return(stat);
17471 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
17473 last_frame = frame_nr - 1;
17475 stat = tng_frame_set_new(tng_data, last_frame + 1,
17476 tng_data->frame_set_n_frames);
17477 if(stat != TNG_SUCCESS)
17479 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17480 __LINE__);
17481 return(stat);
17484 if(frame_set->n_unwritten_frames == 0)
17486 is_first_frame_flag = 1;
17488 frame_set->n_unwritten_frames = frame_nr -
17489 frame_set->first_frame + 1;
17491 n_frames = frame_set->n_frames;
17494 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17496 if(tng_particle_data_find(tng_data, block_id, &p_data)
17497 != TNG_SUCCESS)
17499 stat = tng_particle_data_block_add(tng_data, block_id,
17500 block_name,
17501 TNG_FLOAT_DATA,
17502 block_type_flag,
17503 n_frames, n_values_per_frame,
17504 stride_length,
17505 0, n_particles,
17506 compression, 0);
17507 if(stat != TNG_SUCCESS)
17509 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17510 __FILE__, __LINE__);
17511 return(stat);
17513 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17515 p_data = &frame_set->tr_particle_data[frame_set->
17516 n_particle_data_blocks - 1];
17518 else
17520 p_data = &tng_data->non_tr_particle_data[tng_data->
17521 n_particle_data_blocks - 1];
17523 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17524 stride_length, n_particles,
17525 n_values_per_frame);
17526 if(stat != TNG_SUCCESS)
17528 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17529 __FILE__, __LINE__);
17530 return(stat);
17534 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17536 stride_length = p_data->stride_length;
17538 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
17540 p_data->first_frame_with_data = frame_nr;
17541 frame_pos = 0;
17543 else
17545 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17548 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
17549 n_values_per_frame, values, sizeof(float) *
17550 n_particles * n_values_per_frame);
17552 else
17554 memcpy(p_data->values, values, sizeof(float) * n_particles *
17555 n_values_per_frame);
17558 else
17560 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17562 stat = tng_data_block_add(tng_data, block_id, block_name,
17563 TNG_FLOAT_DATA, block_type_flag,
17564 n_frames, n_values_per_frame,
17565 stride_length, compression, 0);
17566 if(stat != TNG_SUCCESS)
17568 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17569 __FILE__, __LINE__);
17570 return(stat);
17572 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17574 np_data = &frame_set->tr_data[frame_set->
17575 n_data_blocks - 1];
17577 else
17579 np_data = &tng_data->non_tr_data[tng_data->
17580 n_data_blocks - 1];
17582 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17583 stride_length, n_values_per_frame);
17584 if(stat != TNG_SUCCESS)
17586 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17587 __FILE__, __LINE__);
17588 return(stat);
17592 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17594 stride_length = np_data->stride_length;
17596 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
17598 np_data->first_frame_with_data = frame_nr;
17599 frame_pos = 0;
17601 else
17603 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17606 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
17607 n_values_per_frame, values, sizeof(float) *
17608 n_values_per_frame);
17610 else
17612 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
17616 return(TNG_SUCCESS);
17619 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
17620 (tng_trajectory_t tng_data,
17621 const int64_t frame_nr,
17622 const double *values,
17623 const int64_t n_values_per_frame,
17624 const int64_t block_id,
17625 const char *block_name,
17626 const char particle_dependency,
17627 const char compression)
17629 tng_trajectory_frame_set_t frame_set;
17630 tng_particle_data_t p_data;
17631 tng_non_particle_data_t np_data;
17632 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
17633 int64_t last_frame;
17634 int is_first_frame_flag = 0;
17635 char block_type_flag;
17636 tng_function_status stat;
17638 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17639 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17640 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17642 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17644 tng_num_particles_get(tng_data, &n_particles);
17645 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
17648 if(values == 0)
17650 return(TNG_FAILURE);
17653 frame_set = &tng_data->current_trajectory_frame_set;
17655 if(frame_nr < 0)
17657 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
17658 n_frames = stride_length = 1;
17660 else
17662 block_type_flag = TNG_TRAJECTORY_BLOCK;
17664 n_frames = tng_data->frame_set_n_frames;
17666 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17668 stat = tng_frame_set_new(tng_data, 0, n_frames);
17669 if(stat != TNG_SUCCESS)
17671 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17672 __LINE__);
17673 return(stat);
17676 else
17678 n_frames = frame_set->n_frames;
17680 last_frame = frame_set->first_frame +
17681 frame_set->n_frames - 1;
17682 if(frame_nr > last_frame)
17684 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
17685 if(stat != TNG_SUCCESS)
17687 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
17688 __LINE__);
17689 return(stat);
17691 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
17693 last_frame = frame_nr - 1;
17695 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
17696 if(stat != TNG_SUCCESS)
17698 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17699 __LINE__);
17700 return(stat);
17703 if(frame_set->n_unwritten_frames == 0)
17705 is_first_frame_flag = 1;
17707 frame_set->n_unwritten_frames = frame_nr -
17708 frame_set->first_frame + 1;
17711 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17713 if(tng_particle_data_find(tng_data, block_id, &p_data)
17714 != TNG_SUCCESS)
17716 stat = tng_particle_data_block_add(tng_data, block_id,
17717 block_name,
17718 TNG_DOUBLE_DATA,
17719 block_type_flag,
17720 n_frames, n_values_per_frame,
17721 stride_length,
17722 0, n_particles,
17723 compression, 0);
17724 if(stat != TNG_SUCCESS)
17726 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17727 __FILE__, __LINE__);
17728 return(stat);
17730 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17732 p_data = &frame_set->tr_particle_data[frame_set->
17733 n_particle_data_blocks - 1];
17735 else
17737 p_data = &tng_data->non_tr_particle_data[tng_data->
17738 n_particle_data_blocks - 1];
17740 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17741 stride_length, n_particles,
17742 n_values_per_frame);
17743 if(stat != TNG_SUCCESS)
17745 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17746 __FILE__, __LINE__);
17747 return(stat);
17751 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17753 stride_length = p_data->stride_length;
17755 if(is_first_frame_flag)
17757 p_data->first_frame_with_data = frame_nr;
17758 frame_pos = 0;
17760 else
17762 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17765 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
17766 n_values_per_frame, values, sizeof(double) *
17767 n_particles * n_values_per_frame);
17769 else
17771 memcpy(p_data->values, values, sizeof(double) * n_particles *
17772 n_values_per_frame);
17775 else
17777 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17779 stat = tng_data_block_add(tng_data, block_id, block_name,
17780 TNG_DOUBLE_DATA, block_type_flag,
17781 n_frames, n_values_per_frame,
17782 stride_length, compression, 0);
17783 if(stat != TNG_SUCCESS)
17785 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17786 __FILE__, __LINE__);
17787 return(stat);
17789 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17791 np_data = &frame_set->tr_data[frame_set->
17792 n_data_blocks - 1];
17794 else
17796 np_data = &tng_data->non_tr_data[tng_data->
17797 n_data_blocks - 1];
17799 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17800 stride_length, n_values_per_frame);
17801 if(stat != TNG_SUCCESS)
17803 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17804 __FILE__, __LINE__);
17805 return(stat);
17809 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17811 stride_length = np_data->stride_length;
17813 if(is_first_frame_flag)
17815 np_data->first_frame_with_data = frame_nr;
17816 frame_pos = 0;
17818 else
17820 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17823 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
17824 n_values_per_frame, values, sizeof(double) *
17825 n_values_per_frame);
17827 else
17829 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
17833 return(TNG_SUCCESS);
17836 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
17837 (tng_trajectory_t tng_data,
17838 const int64_t frame_nr,
17839 const float *positions)
17841 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17842 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17843 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17845 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
17846 TNG_TRAJ_POSITIONS, "POSITIONS",
17847 TNG_PARTICLE_BLOCK_DATA,
17848 TNG_TNG_COMPRESSION));
17851 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
17852 (tng_trajectory_t tng_data,
17853 const int64_t frame_nr,
17854 const double *positions)
17856 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17857 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17858 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17860 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
17861 TNG_TRAJ_POSITIONS, "POSITIONS",
17862 TNG_PARTICLE_BLOCK_DATA,
17863 TNG_TNG_COMPRESSION));
17866 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
17867 (tng_trajectory_t tng_data,
17868 const int64_t frame_nr,
17869 const float *velocities)
17871 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17872 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17873 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17875 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
17876 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17877 TNG_PARTICLE_BLOCK_DATA,
17878 TNG_TNG_COMPRESSION));
17881 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
17882 (tng_trajectory_t tng_data,
17883 const int64_t frame_nr,
17884 const double *velocities)
17886 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17887 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17888 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17890 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
17891 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17892 TNG_PARTICLE_BLOCK_DATA,
17893 TNG_TNG_COMPRESSION));
17896 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17897 (tng_trajectory_t tng_data,
17898 const int64_t frame_nr,
17899 const float *forces)
17901 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17902 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17903 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17905 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17906 TNG_TRAJ_FORCES, "FORCES",
17907 TNG_PARTICLE_BLOCK_DATA,
17908 TNG_GZIP_COMPRESSION));
17911 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17912 (tng_trajectory_t tng_data,
17913 const int64_t frame_nr,
17914 const double *forces)
17916 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17917 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17918 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17920 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17921 TNG_TRAJ_FORCES, "FORCES",
17922 TNG_PARTICLE_BLOCK_DATA,
17923 TNG_GZIP_COMPRESSION));
17926 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17927 (tng_trajectory_t tng_data,
17928 const int64_t frame_nr,
17929 const float *box_shape)
17931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17932 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17933 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17935 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17936 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17937 TNG_NON_PARTICLE_BLOCK_DATA,
17938 TNG_GZIP_COMPRESSION));
17941 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17942 (tng_trajectory_t tng_data,
17943 const int64_t frame_nr,
17944 const double *box_shape)
17946 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17947 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17948 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17950 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17951 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17952 TNG_NON_PARTICLE_BLOCK_DATA,
17953 TNG_GZIP_COMPRESSION));
17956 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17957 (tng_trajectory_t tng_data,
17958 const int64_t frame_nr,
17959 const double time,
17960 const float *values,
17961 const int64_t n_values_per_frame,
17962 const int64_t block_id,
17963 const char *block_name,
17964 const char particle_dependency,
17965 const char compression)
17967 tng_trajectory_frame_set_t frame_set;
17968 tng_function_status stat;
17970 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17971 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17972 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17973 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17975 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17976 block_id, block_name,
17977 particle_dependency,
17978 compression);
17980 if(stat != TNG_SUCCESS)
17982 return(stat);
17985 frame_set = &tng_data->current_trajectory_frame_set;
17987 /* first_frame_time is -1 when it is not yet set. */
17988 if(frame_set->first_frame_time < -0.1)
17990 if(frame_nr > frame_set->first_frame)
17992 stat = tng_frame_set_first_frame_time_set(tng_data,
17993 time -
17994 (frame_nr -
17995 frame_set->first_frame) *
17996 tng_data->time_per_frame);
17998 else
18000 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18003 return(stat);
18006 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18007 (tng_trajectory_t tng_data,
18008 const int64_t frame_nr,
18009 const double time,
18010 const double *values,
18011 const int64_t n_values_per_frame,
18012 const int64_t block_id,
18013 const char *block_name,
18014 const char particle_dependency,
18015 const char compression)
18017 tng_trajectory_frame_set_t frame_set;
18018 tng_function_status stat;
18020 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18021 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18022 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18023 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18025 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18026 block_id, block_name,
18027 particle_dependency,
18028 compression);
18030 if(stat != TNG_SUCCESS)
18032 return(stat);
18035 frame_set = &tng_data->current_trajectory_frame_set;
18037 /* first_frame_time is -1 when it is not yet set. */
18038 if(frame_set->first_frame_time < -0.1)
18040 if(frame_nr > frame_set->first_frame)
18042 stat = tng_frame_set_first_frame_time_set(tng_data,
18043 time -
18044 (frame_nr -
18045 frame_set->first_frame) *
18046 tng_data->time_per_frame);
18048 else
18050 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18053 return(stat);
18056 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18057 (tng_trajectory_t tng_data,
18058 const int64_t frame_nr,
18059 const double time,
18060 const float *positions)
18062 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18063 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18064 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18065 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18067 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18068 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18069 TNG_PARTICLE_BLOCK_DATA,
18070 TNG_TNG_COMPRESSION));
18073 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18074 (tng_trajectory_t tng_data,
18075 const int64_t frame_nr,
18076 const double time,
18077 const double *positions)
18079 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18080 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18081 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18082 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18084 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18085 positions, 3,
18086 TNG_TRAJ_POSITIONS,
18087 "POSITIONS",
18088 TNG_PARTICLE_BLOCK_DATA,
18089 TNG_TNG_COMPRESSION));
18092 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18093 (tng_trajectory_t tng_data,
18094 const int64_t frame_nr,
18095 const double time,
18096 const float *velocities)
18098 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18099 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18100 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18101 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18103 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18104 velocities, 3,
18105 TNG_TRAJ_VELOCITIES,
18106 "VELOCITIES",
18107 TNG_PARTICLE_BLOCK_DATA,
18108 TNG_TNG_COMPRESSION));
18111 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18112 (tng_trajectory_t tng_data,
18113 const int64_t frame_nr,
18114 const double time,
18115 const double *velocities)
18117 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18118 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18119 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18120 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18122 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18123 velocities, 3,
18124 TNG_TRAJ_VELOCITIES,
18125 "VELOCITIES",
18126 TNG_PARTICLE_BLOCK_DATA,
18127 TNG_TNG_COMPRESSION));
18130 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18131 (tng_trajectory_t tng_data,
18132 const int64_t frame_nr,
18133 const double time,
18134 const float *forces)
18136 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18137 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18138 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18139 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18141 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18142 3, TNG_TRAJ_FORCES, "FORCES",
18143 TNG_PARTICLE_BLOCK_DATA,
18144 TNG_GZIP_COMPRESSION));
18147 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18148 (tng_trajectory_t tng_data,
18149 const int64_t frame_nr,
18150 const double time,
18151 const double *forces)
18153 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18154 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18155 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18156 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18158 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18159 forces, 3,
18160 TNG_TRAJ_FORCES, "FORCES",
18161 TNG_PARTICLE_BLOCK_DATA,
18162 TNG_GZIP_COMPRESSION));
18165 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18166 (tng_trajectory_t tng_data,
18167 const int64_t frame_nr,
18168 const double time,
18169 const float *box_shape)
18171 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18172 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18173 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18174 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18176 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18177 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18178 TNG_NON_PARTICLE_BLOCK_DATA,
18179 TNG_GZIP_COMPRESSION));
18182 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18183 (tng_trajectory_t tng_data,
18184 const int64_t frame_nr,
18185 const double time,
18186 const double *box_shape)
18188 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18189 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18190 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18191 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18193 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18194 time, box_shape, 9,
18195 TNG_TRAJ_BOX_SHAPE,
18196 "BOX SHAPE",
18197 TNG_NON_PARTICLE_BLOCK_DATA,
18198 TNG_GZIP_COMPRESSION));
18201 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18202 (tng_trajectory_t tng_data,
18203 const int64_t block_id,
18204 int64_t *codec_id,
18205 float *factor)
18207 tng_trajectory_frame_set_t frame_set;
18208 tng_particle_data_t p_data = 0;
18209 tng_non_particle_data_t np_data = 0;
18210 tng_function_status stat;
18211 int64_t i;
18212 int block_type = -1;
18214 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18215 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
18216 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
18218 frame_set = &tng_data->current_trajectory_frame_set;
18220 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18221 if(stat == TNG_SUCCESS)
18223 block_type = TNG_PARTICLE_BLOCK_DATA;
18225 else
18227 stat = tng_data_find(tng_data, block_id, &np_data);
18228 if(stat == TNG_SUCCESS)
18230 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18232 else
18234 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18235 if(stat != TNG_SUCCESS)
18237 return(stat);
18239 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18240 if(stat == TNG_SUCCESS)
18242 block_type = TNG_PARTICLE_BLOCK_DATA;
18244 else
18246 stat = tng_data_find(tng_data, block_id, &np_data);
18247 if(stat == TNG_SUCCESS)
18249 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18251 else
18253 return(stat);
18258 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18260 if(p_data->last_retrieved_frame < 0)
18262 i = p_data->first_frame_with_data;
18264 else
18266 i = p_data->last_retrieved_frame;
18269 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
18271 if(np_data->last_retrieved_frame < 0)
18273 i = np_data->first_frame_with_data;
18275 else
18277 i = np_data->last_retrieved_frame;
18280 else
18282 return(TNG_FAILURE);
18284 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
18286 stat = tng_frame_set_of_frame_find(tng_data, i);
18287 if(stat != TNG_SUCCESS)
18289 return(stat);
18291 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18292 if(stat != TNG_SUCCESS)
18294 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18295 __FILE__, __LINE__);
18296 return(stat);
18299 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18301 *codec_id = p_data->codec_id;
18302 *factor = (float)p_data->compression_multiplier;
18304 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
18306 *codec_id = np_data->codec_id;
18307 *factor = (float)np_data->compression_multiplier;
18309 return(TNG_SUCCESS);
18312 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
18313 (tng_trajectory_t tng_data,
18314 int64_t current_frame,
18315 const int64_t n_requested_data_block_ids,
18316 const int64_t *requested_data_block_ids,
18317 int64_t *next_frame,
18318 int64_t *n_data_blocks_in_next_frame,
18319 int64_t **data_block_ids_in_next_frame)
18321 tng_trajectory_frame_set_t frame_set;
18322 tng_function_status stat;
18323 tng_particle_data_t p_data;
18324 tng_non_particle_data_t np_data;
18325 tng_gen_block_t block;
18326 int64_t i, j, block_id, *temp;
18327 int64_t data_frame, frame_diff, min_diff;
18328 int64_t size, frame_set_file_pos;
18329 int found, read_all = 0;
18330 long file_pos;
18332 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18333 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
18334 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
18335 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
18337 if(n_requested_data_block_ids)
18339 TNG_ASSERT(requested_data_block_ids, "TNG library: If the number of requested data blocks is > 0 then the array of data block IDs must not be NULL.");
18340 size = sizeof(int64_t) * n_requested_data_block_ids;
18341 temp = realloc(*data_block_ids_in_next_frame, size);
18342 if(!temp)
18344 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
18345 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
18346 __FILE__, __LINE__);
18347 free(*data_block_ids_in_next_frame);
18348 *data_block_ids_in_next_frame = 0;
18349 return(TNG_CRITICAL);
18351 *data_block_ids_in_next_frame = temp;
18354 frame_set = &tng_data->current_trajectory_frame_set;
18356 current_frame += 1;
18358 if(current_frame < frame_set->first_frame ||
18359 current_frame >= frame_set->first_frame + frame_set->n_frames)
18361 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
18362 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
18363 if(stat != TNG_SUCCESS)
18365 /* If the frame set search found the frame set after the starting
18366 * frame set there is a gap in the frame sets. So, even if the frame
18367 * was not found the next frame with data is still in the found
18368 * frame set. */
18369 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
18370 frame_set_file_pos)
18372 return(stat);
18374 current_frame = frame_set->first_frame;
18378 /* If no data blocks have been found in the frame set check what data blocks
18379 * are present. If they have already been found do not read them again. */
18380 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
18382 file_pos = ftell(tng_data->input_file);
18383 /* Read all blocks until next frame set block */
18384 if(file_pos < tng_data->input_file_len)
18386 tng_block_init(&block);
18387 stat = tng_block_header_read(tng_data, block);
18388 while(file_pos < tng_data->input_file_len &&
18389 stat != TNG_CRITICAL &&
18390 block->id != TNG_TRAJECTORY_FRAME_SET)
18392 stat = tng_block_read_next(tng_data, block,
18393 TNG_USE_HASH);
18394 if(stat != TNG_CRITICAL)
18396 file_pos = ftell(tng_data->input_file);
18397 if(file_pos < tng_data->input_file_len)
18399 stat = tng_block_header_read(tng_data, block);
18403 tng_block_destroy(&block);
18404 if(stat == TNG_CRITICAL)
18406 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
18407 file_pos, __FILE__, __LINE__);
18408 return(stat);
18411 read_all = 1;
18414 min_diff = -1;
18416 *n_data_blocks_in_next_frame = 0;
18418 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
18420 p_data = &frame_set->tr_particle_data[i];
18421 block_id = p_data->block_id;
18423 if(n_requested_data_block_ids > 0)
18425 found = 0;
18426 for(j = 0; j < n_requested_data_block_ids; j++)
18428 if(block_id == requested_data_block_ids[j])
18430 found = 1;
18431 break;
18434 if(!found)
18436 continue;
18440 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
18441 p_data->last_retrieved_frame >=
18442 frame_set->first_frame + frame_set->n_frames))
18444 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
18445 TNG_USE_HASH, block_id);
18446 if(stat == TNG_CRITICAL)
18448 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18449 __FILE__, __LINE__);
18450 return(stat);
18452 if(stat == TNG_FAILURE)
18454 continue;
18457 if(frame_set->first_frame != current_frame &&
18458 p_data->last_retrieved_frame >= 0)
18460 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
18462 else
18464 data_frame = p_data->first_frame_with_data;
18466 frame_diff = data_frame - current_frame;
18467 if(frame_diff < 0)
18469 continue;
18471 if(min_diff == -1 || frame_diff <= min_diff)
18473 if(frame_diff < min_diff)
18475 *n_data_blocks_in_next_frame = 1;
18477 else
18479 *n_data_blocks_in_next_frame += 1;
18481 if(n_requested_data_block_ids <= 0)
18483 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
18484 temp = realloc(*data_block_ids_in_next_frame, size);
18485 if(!temp)
18487 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
18488 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
18489 __FILE__, __LINE__);
18490 free(*data_block_ids_in_next_frame);
18491 *data_block_ids_in_next_frame = 0;
18492 return(TNG_CRITICAL);
18494 *data_block_ids_in_next_frame = temp;
18496 else
18498 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
18500 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
18502 min_diff = frame_diff;
18505 for(i = 0; i < frame_set->n_data_blocks; i++)
18507 np_data = &frame_set->tr_data[i];
18508 block_id = np_data->block_id;
18510 if(n_requested_data_block_ids > 0)
18512 found = 0;
18513 for(j = 0; j < n_requested_data_block_ids; j++)
18515 if(block_id == requested_data_block_ids[j])
18517 found = 1;
18518 break;
18521 if(!found)
18523 continue;
18527 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
18528 np_data->last_retrieved_frame >=
18529 frame_set->first_frame + frame_set->n_frames))
18531 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
18532 TNG_USE_HASH, block_id);
18533 if(stat == TNG_CRITICAL)
18535 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18536 __FILE__, __LINE__);
18537 return(stat);
18539 if(stat == TNG_FAILURE)
18541 continue;
18544 if(frame_set->first_frame != current_frame &&
18545 np_data->last_retrieved_frame >= 0)
18547 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
18549 else
18551 data_frame = np_data->first_frame_with_data;
18553 frame_diff = data_frame - current_frame;
18554 if(frame_diff < 0)
18556 continue;
18558 if(min_diff == -1 || frame_diff <= min_diff)
18560 if(frame_diff < min_diff)
18562 *n_data_blocks_in_next_frame = 1;
18564 else
18566 *n_data_blocks_in_next_frame += 1;
18568 if(n_requested_data_block_ids <= 0)
18570 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
18571 temp = realloc(*data_block_ids_in_next_frame, size);
18572 if(!temp)
18574 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
18575 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
18576 __FILE__, __LINE__);
18577 free(*data_block_ids_in_next_frame);
18578 *data_block_ids_in_next_frame = 0;
18579 return(TNG_CRITICAL);
18581 *data_block_ids_in_next_frame = temp;
18583 else
18585 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
18587 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
18589 min_diff = frame_diff;
18592 if(min_diff < 0)
18594 return(TNG_FAILURE);
18596 *next_frame = current_frame + min_diff;
18598 return(TNG_SUCCESS);
18602 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
18603 (tng_trajectory_t tng_data,
18604 int64_t *n_data_blocks,
18605 int64_t **data_block_ids,
18606 char ***data_block_names,
18607 int64_t **stride_lengths,
18608 int64_t **n_values_per_frame,
18609 char **block_types,
18610 char **dependencies,
18611 char **compressions)
18613 tng_gen_block_t block;
18614 long orig_file_pos, file_pos;
18616 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18617 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
18618 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
18619 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
18620 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
18622 orig_file_pos = ftell(tng_data->input_file);
18624 if(!tng_data->input_file_len)
18626 fseek(tng_data->input_file, 0, SEEK_END);
18627 tng_data->input_file_len = ftell(tng_data->input_file);
18630 fseek(tng_data->input_file, 0, SEEK_SET);
18631 file_pos = 0;
18633 *n_data_blocks = 0;
18635 tng_block_init(&block);
18637 while(file_pos < tng_data->input_file_len &&
18638 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
18640 if(block->id > TNG_TRAJECTORY_FRAME_SET)
18644 file_pos += (long)(block->block_contents_size + block->header_contents_size);
18645 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
18648 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
18650 return(TNG_SUCCESS);
18653 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
18654 (tng_trajectory_t tng_data,
18655 const int64_t prev_frame)
18657 tng_function_status stat;
18658 FILE *temp = tng_data->input_file;
18660 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18661 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
18663 tng_data->input_file = tng_data->output_file;
18665 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
18666 if(stat != TNG_SUCCESS)
18668 return(stat);
18671 tng_data->current_trajectory_frame_set_output_file_pos =
18672 tng_data->current_trajectory_frame_set_input_file_pos;
18674 tng_data->input_file = temp;
18676 return(TNG_SUCCESS);