1 /* This code is part of the tng binary trajectory format.
3 * Written by Magnus Lundborg
4 * Copyright (c) 2012-2014, The GROMACS development team.
5 * Check out http://www.gromacs.org for more information.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the Revised BSD License.
12 #ifdef USE_STD_INTTYPES_H
25 #include "tng/tng_io.h"
27 #include "compression/tng_compress.h"
28 #include "tng/version.h"
32 /** One of the atoms of the bond */
34 /** The other atom of the bond */
39 /** The residue containing this atom */
40 tng_residue_t residue;
41 /** A unique (per molecule) ID number of the atom */
43 /** The atom_type (depending on the forcefield) */
45 /** The name of the atom */
50 /** The chain containing this residue */
52 /** A unique (per chain) ID number of the residue */
54 /** The name of the residue */
56 /** The number of atoms in the residue */
58 /** A list of atoms in the residue */
63 /** The molecule containing this chain */
64 tng_molecule_t molecule;
65 /** A unique (per molecule) ID number of the chain */
67 /** The name of the chain */
69 /** The number of residues in the chain */
71 /** A list of residues in the chain */
72 tng_residue_t residues;
76 /** A unique ID number of the molecule */
78 /** Quaternary structure of the molecule.
83 int64_t quaternary_str;
84 /** The number of chains in the molecule */
86 /** The number of residues in the molecule */
88 /** The number of atoms in the molecule */
90 /** The number of bonds in the molecule. If the bonds are not specified this
93 /** The name of the molecule */
95 /** A list of chains in the molecule */
97 /** A list of residues in the molecule */
98 tng_residue_t residues;
99 /** A list of the atoms in the molecule */
101 /** A list of the bonds in the molecule */
105 struct tng_gen_block {
106 /** The size of the block header in bytes */
107 int64_t header_contents_size;
108 /** The size of the block contents in bytes */
109 int64_t block_contents_size;
110 /** The ID of the block to determine its type */
112 /** The MD5 hash of the block to verify integrity */
113 char md5_hash[TNG_MD5_HASH_LEN];
114 /** The name of the block */
116 /** The library version used to write the block */
117 int64_t block_version;
118 int64_t alt_hash_type;
119 int64_t alt_hash_len;
121 int64_t signature_type;
122 int64_t signature_len;
124 /** The full block header contents */
125 char *header_contents;
126 /** The full block contents */
127 char *block_contents;
130 struct tng_particle_mapping {
131 /** The index number of the first particle in this mapping block */
132 int64_t num_first_particle;
133 /** The number of particles list in this mapping block */
135 /** the mapping of index numbers to the real particle numbers in the
136 * trajectory. real_particle_numbers[0] is the real particle number
137 * (as it is numbered in the molecular system) of the first particle
138 * in the data blocks covered by this particle mapping block */
139 int64_t *real_particle_numbers;
142 struct tng_trajectory_frame_set {
143 /** The number of different particle mapping blocks present. */
144 int64_t n_mapping_blocks;
145 /** The atom mappings of this frame set */
146 struct tng_particle_mapping *mappings;
147 /** The first frame of this frame set */
149 /** The number of frames in this frame set */
151 /** The number of written frames in this frame set (used when writing one
152 * frame at a time). */
153 int64_t n_written_frames;
154 /** The number of frames not yet written to file in this frame set
155 * (used from the utility functions to finish the writing properly. */
156 int64_t n_unwritten_frames;
159 /** A list of the number of each molecule type - only used when using
160 * variable number of atoms */
161 int64_t *molecule_cnt_list;
162 /** The number of particles/atoms - only used when using variable number
165 /** The file position of the next frame set */
166 int64_t next_frame_set_file_pos;
167 /** The file position of the previous frame set */
168 int64_t prev_frame_set_file_pos;
169 /** The file position of the frame set one long stride step ahead */
170 int64_t medium_stride_next_frame_set_file_pos;
171 /** The file position of the frame set one long stride step behind */
172 int64_t medium_stride_prev_frame_set_file_pos;
173 /** The file position of the frame set one long stride step ahead */
174 int64_t long_stride_next_frame_set_file_pos;
175 /** The file position of the frame set one long stride step behind */
176 int64_t long_stride_prev_frame_set_file_pos;
177 /** Time stamp (in seconds) of first frame in frame set */
178 double first_frame_time;
180 /* The data blocks in a frame set are trajectory data blocks */
181 /** The number of trajectory data blocks of particle dependent data */
182 int n_particle_data_blocks;
183 /** A list of data blocks containing particle dependent data */
184 struct tng_particle_data *tr_particle_data;
185 /** The number of trajectory data blocks independent of particles */
187 /** A list of data blocks containing particle indepdendent data */
188 struct tng_non_particle_data *tr_data;
191 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
192 /* FIXME: Make only one data block struct */
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 */
197 /** The name of the data block. This is used to determine the kind of
198 * data that is stored */
200 /** The type of data stored. */
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 */
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. */
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 */
220 /** If storing character data store it in a 3-dimensional array */
224 struct tng_non_particle_data {
225 /** The ID of the data block */
227 /** The name of the data block. This is used to determine the kind of
228 * data that is stored */
230 /** The type of data stored. */
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 */
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. */
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 */
251 /** If storing character data store it in a 2-dimensional array */
257 struct tng_trajectory {
258 /** The path of the input trajectory file */
259 char *input_file_path;
260 /** A handle to the input file */
262 /** The length of the input file */
264 /** The path of the output trajectory file */
265 char *output_file_path;
266 /** A handle to the output file */
268 /** Function to swap 32 bit values to and from the endianness of the
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
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
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
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 */
282 /** The endianness of 64 bit values of the current computer */
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
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
304 char *last_pgp_signature;
305 /** The time (n seconds since 1970) when the file was created */
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 */
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 */
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 /* These data blocks are non-trajectory data blocks */
356 /** The number of non-frame dependent particle dependent data blocks */
357 int n_particle_data_blocks;
358 /** A list of data blocks containing particle dependent data */
359 struct tng_particle_data *non_tr_particle_data;
361 /** The number of frame and particle independent data blocks */
363 /** A list of frame and particle indepdendent data blocks */
364 struct tng_non_particle_data *non_tr_data;
366 /** TNG compression algorithm for compressing positions */
367 int *compress_algo_pos;
368 /** TNG compression algorithm for compressing velocities */
369 int *compress_algo_vel;
370 /** The precision used for lossy compression */
371 double compression_precision;
375 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
377 #endif /* win32... */
378 #endif /* not defined USE_WINDOWS */
381 #define TNG_INLINE __inline
382 #define TNG_SNPRINTF _snprintf
384 #define TNG_INLINE inline
385 #define TNG_SNPRINTF snprintf
388 static TNG_INLINE int tng_min_i(int a, int b)
390 return (a < b ? a : b);
394 static TNG_INLINE int tng_max_i(int a, int b)
396 return (a > b ? a : b);
399 static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
401 return (a < b ? a : b);
404 static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
406 return (a > b ? a : b);
410 static TNG_INLINE float tng_min_f(float a, float b)
412 return (a < b ? a : b);
415 static TNG_INLINE float tng_max_f(float a, float b)
417 return (a > b ? a : b);
420 static TNG_INLINE double tng_min_d(double a, double b)
422 return (a < b ? a : b);
425 static TNG_INLINE double tng_max_d(double a, double b)
427 return (a > b ? a : b);
431 /** This function swaps the byte order of a 32 bit numerical variable
433 * It does not only work with integer, but e.g. floats need casting.
434 * If the byte order is already big endian no change is needed.
435 * @param tng_data is a trajectory data container.
436 * @param v is a pointer to a 32 bit numerical value (float or integer).
437 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
438 * byte order is not recognised.
440 static tng_function_status tng_swap_byte_order_big_endian_32
441 (const tng_trajectory_t tng_data, int32_t *v)
443 switch(tng_data->endianness_32)
445 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
446 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
447 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
448 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
449 ((*v & 0x000000FF) << 24); /* Move last byte to first */
453 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
454 *v = ((*v & 0xFFFF0000) >> 16) |
455 ((*v & 0x0000FFFF) << 16);
459 case TNG_BIG_ENDIAN_32: /* Already correct */
467 /** This function swaps the byte order of a 64 bit numerical variable
469 * It does not only work with integer, but e.g. floats need casting.
470 * The byte order swapping routine can convert four different byte
471 * orders to big endian.
472 * If the byte order is already big endian no change is needed.
473 * @param tng_data is a trajectory data container.
474 * @param v is a pointer to a 64 bit numerical value (double or integer).
475 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
476 * byte order is not recognised.
478 static tng_function_status tng_swap_byte_order_big_endian_64
479 (const tng_trajectory_t tng_data, int64_t *v)
481 switch(tng_data->endianness_64)
483 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
484 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
485 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
486 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
487 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
488 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
489 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
490 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
491 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
495 case TNG_QUAD_SWAP_64: /* Byte quad swap */
496 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
497 ((*v & 0x00000000FFFFFFFFLL) << 32);
501 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
502 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
503 ((*v & 0x0000FFFF0000FFFFLL) << 16);
507 case TNG_BYTE_SWAP_64: /* Byte swap */
508 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
509 ((*v & 0x00FF00FF00FF00FFLL) << 8);
513 case TNG_BIG_ENDIAN_64: /* Already correct */
521 /** This function swaps the byte order of a 32 bit numerical variable
523 * It does not only work with integer, but e.g. floats need casting.
524 * If the byte order is already little endian no change is needed.
525 * @param tng_data is a trajectory data container.
526 * @param v is a pointer to a 32 bit numerical value (float or integer).
527 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
528 * byte order is not recognised.
530 static tng_function_status tng_swap_byte_order_little_endian_32
531 (const tng_trajectory_t tng_data, int32_t *v)
533 switch(tng_data->endianness_32)
535 case TNG_LITTLE_ENDIAN_32: /* Already correct */
538 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
539 *v = ((*v & 0xFF00FF00) >> 8) |
540 ((*v & 0x00FF00FF) << 8);
544 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
545 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
546 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
547 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
548 ((*v & 0x000000FF) << 24); /* Move last byte to first */
557 /** This function swaps the byte order of a 64 bit numerical variable
559 * It does not only work with integer, but e.g. floats need casting.
560 * The byte order swapping routine can convert four different byte
561 * orders to little endian.
562 * If the byte order is already little endian no change is needed.
563 * @param tng_data is a trajectory data container.
564 * @param v is a pointer to a 64 bit numerical value (double or integer).
565 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
566 * byte order is not recognised.
568 static tng_function_status tng_swap_byte_order_little_endian_64
569 (const tng_trajectory_t tng_data, int64_t *v)
571 switch(tng_data->endianness_64)
573 case TNG_LITTLE_ENDIAN_64: /* Already correct */
576 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
577 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
578 ((*v & 0x00FF000000FF0000LL) >> 8) |
579 ((*v & 0x0000FF000000FF00LL) << 8) |
580 ((*v & 0x000000FF000000FFLL) << 24);
584 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
585 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
586 ((*v & 0x00FF00FF00000000LL) >> 24) |
587 ((*v & 0x00000000FF00FF00LL) << 24) |
588 ((*v & 0x0000000000FF00FFLL) << 40);
592 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
593 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
594 ((*v & 0x0000FFFF00000000LL) >> 16) |
595 ((*v & 0x00000000FFFF0000LL) << 16) |
596 ((*v & 0x000000000000FFFFLL) << 48);
600 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
601 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
602 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
603 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
604 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
605 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
606 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
607 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
608 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
616 /** Generate the md5 hash of a block.
617 * The hash is created based on the actual block contents.
618 * @param block is a general block container.
619 * @return TNG_SUCCESS (0) if successful.
621 static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
623 md5_state_t md5_state;
625 md5_init(&md5_state);
626 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
627 (int)block->block_contents_size);
628 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
633 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
634 * calculated from the current contents.
635 * If the current md5 hash is not set skip the comparison.
636 * @param block is a general block container.
637 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
638 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
639 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
642 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
645 md5_state_t md5_state;
646 char hash[TNG_MD5_HASH_LEN];
648 TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
651 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
655 md5_init(&md5_state);
656 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
657 (int)block->block_contents_size);
658 md5_finish(&md5_state, (md5_byte_t *)hash);
660 if(strncmp(block->md5_hash, hash, 16) != 0)
662 *results = TNG_FALSE;
668 /** Open the input file if it is not already opened.
669 * @param tng_data is a trajectory data container.
670 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
673 static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
675 if(!tng_data->input_file)
677 if(!tng_data->input_file_path)
679 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
681 return(TNG_CRITICAL);
683 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
684 if(!tng_data->input_file)
686 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
687 tng_data->input_file_path, __FILE__, __LINE__);
688 return(TNG_CRITICAL);
694 /** Open the output file if it is not already opened
695 * @param tng_data is a trajectory data container.
696 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
699 static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
701 if(!tng_data->output_file)
703 if(!tng_data->output_file_path)
705 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
707 return(TNG_CRITICAL);
710 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
712 if(!tng_data->output_file)
714 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
715 tng_data->output_file_path, __FILE__, __LINE__);
716 return(TNG_CRITICAL);
722 /** Setup a file block container.
723 * @param block_p a pointer to memory to initialise as a file block container.
724 * @details Memory is allocated during initialisation.
725 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
728 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
730 tng_gen_block_t block;
732 *block_p = malloc(sizeof(struct tng_gen_block));
735 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
736 sizeof(struct tng_gen_block), __FILE__, __LINE__);
737 return(TNG_CRITICAL);
743 /* Reset the md5_hash */
744 memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
746 block->block_version = TNG_API_VERSION;
747 block->header_contents = 0;
748 block->header_contents_size = 0;
749 block->block_contents = 0;
750 block->block_contents_size = 0;
756 * @brief Clean up a file block container.
757 * @param block_p a pointer to the file block container to destroy.
758 * @details All allocated memory in the data structure is freed, as well as
760 * @return TNG_SUCCESS (0) if successful.
762 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
764 tng_gen_block_t block = *block_p;
771 /* fprintf(stderr, "TNG library: Destroying block\n"); */
777 if(block->header_contents)
779 free(block->header_contents);
780 block->header_contents = 0;
782 if(block->block_contents)
784 free(block->block_contents);
785 block->block_contents = 0;
794 /** Read the header of a data block, regardless of its type
795 * @param tng_data is a trajectory data container.
796 * @param block is a general block container.
797 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
798 * error has occured (not able to read the header size, thus skipping
799 * the block) or TNG_CRITICAL (2) if a major error has occured.
801 static tng_function_status tng_block_header_read
802 (tng_trajectory_t tng_data, tng_gen_block_t block)
806 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
808 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
810 return(TNG_CRITICAL);
813 /* First read the header size to be able to read the whole header. */
814 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
815 1, tng_data->input_file) == 0)
817 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
819 return(TNG_CRITICAL);
822 if(block->header_contents_size == 0)
828 /* If this was the size of the general info block check the endianness */
829 if(ftell(tng_data->input_file) < 9)
831 /* File is little endian */
832 if ( *((const char*)&block->header_contents_size) != 0x00 &&
833 *((const char*)(&block->header_contents_size) + 7) == 0x00)
835 /* If the architecture endianness is little endian no byte swap
836 * will be needed. Otherwise use the functions to swap to little
838 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
840 tng_data->input_endianness_swap_func_32 = 0;
844 tng_data->input_endianness_swap_func_32 =
845 &tng_swap_byte_order_little_endian_32;
847 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
849 tng_data->input_endianness_swap_func_64 = 0;
853 tng_data->input_endianness_swap_func_64 =
854 &tng_swap_byte_order_little_endian_64;
857 /* File is big endian */
860 /* If the architecture endianness is big endian no byte swap
861 * will be needed. Otherwise use the functions to swap to big
863 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
865 tng_data->input_endianness_swap_func_32 = 0;
869 tng_data->input_endianness_swap_func_32 =
870 &tng_swap_byte_order_big_endian_32;
872 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
874 tng_data->input_endianness_swap_func_64 = 0;
878 tng_data->input_endianness_swap_func_64 =
879 &tng_swap_byte_order_big_endian_64;
884 if(tng_data->input_endianness_swap_func_64)
886 if(tng_data->input_endianness_swap_func_64(tng_data,
887 &block->header_contents_size)
890 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
895 /* Move the reading position to the beginning of the header. */
896 fseek(tng_data->input_file, -(long)sizeof(block->header_contents_size),
899 /* If there is already memory allocated for the contents free it (we do not
900 * know if the size is correct). */
901 if(block->header_contents)
903 free(block->header_contents);
906 block->header_contents = malloc(block->header_contents_size);
907 if(!block->header_contents)
909 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
910 block->header_contents_size, __FILE__, __LINE__);
911 return(TNG_CRITICAL);
914 /* Read the whole header into header_contents. This way it can be saved
915 * even if it cannot be interpreted
916 * for one reason or another. */
917 if(fread(block->header_contents, block->header_contents_size, 1,
918 tng_data->input_file) == 0)
920 fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
921 return(TNG_CRITICAL);
924 /* The header contents size has already been read. Skip ahead. */
925 offset = sizeof(block->header_contents_size);
928 /* Copy the respective parameters from the header contents block */
929 memcpy(&block->block_contents_size, block->header_contents+offset,
930 sizeof(block->block_contents_size));
931 if(tng_data->input_endianness_swap_func_64)
933 if(tng_data->input_endianness_swap_func_64(tng_data,
934 &block->block_contents_size)
937 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
942 offset += sizeof(block->block_contents_size);
944 memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
945 if(tng_data->input_endianness_swap_func_64)
947 if(tng_data->input_endianness_swap_func_64(tng_data,
951 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
956 offset += sizeof(block->id);
958 memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
959 offset += TNG_MD5_HASH_LEN;
961 if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
966 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
969 block->name = malloc(len);
972 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
974 return(TNG_CRITICAL);
976 strncpy(block->name, block->header_contents+offset, len);
980 memcpy(&block->block_version, block->header_contents+offset,
981 sizeof(block->block_version));
982 if(tng_data->input_endianness_swap_func_64)
984 if(tng_data->input_endianness_swap_func_64(tng_data,
985 &block->block_version)
988 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
996 /** Write a whole block, both header and contents, regardless of it type
997 * @param tng_data is a trajectory data container.
998 * @param block is a general block container.
999 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1000 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1002 /* Disabled until it is used.*/
1004 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1005 // tng_gen_block_t block)
1007 // if(!block->header_contents)
1009 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1010 // return(TNG_FAILURE);
1012 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1013 // tng_data->output_file) != 1)
1015 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1016 // __FILE__, __LINE__);
1017 // return(TNG_CRITICAL);
1020 // if(!block->block_contents)
1022 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1023 // __FILE__, __LINE__);
1024 // return(TNG_FAILURE);
1026 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1027 // tng_data->output_file) != 1)
1029 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1030 // __FILE__, __LINE__);
1031 // return(TNG_CRITICAL);
1033 // return(TNG_SUCCESS);
1037 /** Update the md5 hash of a block already written to the file
1038 * @param tng_data is a trajectory data container.
1039 * @param block is the block, of which to update the md5 hash.
1040 * @param header_start_pos is the file position where the block header starts.
1041 * @param contents_start_pos is the file position where the block contents
1043 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1044 * error has occured.
1046 static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
1047 tng_gen_block_t block,
1048 const int64_t header_start_pos,
1049 const int64_t contents_start_pos)
1051 if(block->block_contents)
1053 free(block->block_contents);
1056 block->block_contents = malloc(block->block_contents_size);
1057 if(!block->block_contents)
1059 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1060 block->block_contents_size, __FILE__, __LINE__);
1061 return(TNG_CRITICAL);
1064 fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
1065 if(fread(block->block_contents, block->block_contents_size, 1,
1066 tng_data->output_file) == 0)
1068 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1069 return(TNG_CRITICAL);
1072 tng_block_md5_hash_generate(block);
1074 fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
1076 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
1078 return(TNG_SUCCESS);
1081 /** Update the frame set pointers in the file header (general info block),
1082 * already written to disk
1083 * @param tng_data is a trajectory data container.
1084 * @param hash_mode specifies whether to update the block md5 hash when
1085 * updating the pointers.
1086 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1087 * error has occured.
1089 static tng_function_status tng_header_pointers_update
1090 (tng_trajectory_t tng_data, const char hash_mode)
1092 tng_gen_block_t block;
1093 FILE *temp = tng_data->input_file;
1094 int64_t output_file_pos, pos, contents_start_pos;
1096 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1098 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1099 __FILE__, __LINE__);
1100 return(TNG_CRITICAL);
1103 tng_data->input_file = tng_data->output_file;
1105 tng_block_init(&block);
1107 output_file_pos = ftell(tng_data->output_file);
1108 fseek(tng_data->output_file, 0, SEEK_SET);
1110 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1112 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
1113 __FILE__, __LINE__);
1114 tng_data->input_file = temp;
1115 tng_block_destroy(&block);
1116 return(TNG_CRITICAL);
1119 contents_start_pos = ftell(tng_data->output_file);
1121 fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
1122 sizeof(int64_t), SEEK_CUR);
1124 tng_data->input_file = temp;
1126 pos = tng_data->first_trajectory_frame_set_output_file_pos;
1128 if(tng_data->input_endianness_swap_func_64)
1130 if(tng_data->input_endianness_swap_func_64(tng_data,
1134 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1135 __FILE__, __LINE__);
1139 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1141 tng_block_destroy(&block);
1142 return(TNG_CRITICAL);
1145 pos = tng_data->last_trajectory_frame_set_output_file_pos;
1147 if(tng_data->input_endianness_swap_func_64)
1149 if(tng_data->input_endianness_swap_func_64(tng_data,
1153 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1154 __FILE__, __LINE__);
1159 sizeof(int64_t), 1, tng_data->output_file) != 1)
1161 tng_block_destroy(&block);
1162 return(TNG_CRITICAL);
1165 if(hash_mode == TNG_USE_HASH)
1167 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
1170 tng_block_destroy(&block);
1172 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1174 return(TNG_SUCCESS);
1177 /** Update the frame set pointers in the current frame set block, already
1178 * written to disk. It also updates the pointers of the blocks pointing to
1179 * the current frame set block.
1180 * @param tng_data is a trajectory data container.
1181 * @param hash_mode specifies whether to update the block md5 hash when
1182 * updating the pointers.
1183 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1184 * error has occured.
1186 static tng_function_status tng_frame_set_pointers_update
1187 (tng_trajectory_t tng_data, const char hash_mode)
1189 tng_gen_block_t block;
1190 tng_trajectory_frame_set_t frame_set;
1191 FILE *temp = tng_data->input_file;
1192 int64_t pos, output_file_pos, contents_start_pos;
1194 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1196 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1197 __FILE__, __LINE__);
1198 return(TNG_CRITICAL);
1201 tng_block_init(&block);
1202 output_file_pos = ftell(tng_data->output_file);
1204 tng_data->input_file = tng_data->output_file;
1206 frame_set = &tng_data->current_trajectory_frame_set;
1208 pos = tng_data->current_trajectory_frame_set_output_file_pos;
1210 /* Update next frame set */
1211 if(frame_set->next_frame_set_file_pos > 0)
1213 fseek(tng_data->output_file, (long)frame_set->next_frame_set_file_pos,
1216 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1218 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1219 __FILE__, __LINE__);
1220 tng_data->input_file = temp;
1221 tng_block_destroy(&block);
1222 return(TNG_CRITICAL);
1225 contents_start_pos = ftell(tng_data->output_file);
1227 fseek(tng_data->output_file, (long)block->block_contents_size - (5 *
1228 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1230 if(tng_data->input_endianness_swap_func_64)
1232 if(tng_data->input_endianness_swap_func_64(tng_data,
1236 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1237 __FILE__, __LINE__);
1241 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1243 tng_data->input_file = temp;
1244 tng_block_destroy(&block);
1245 return(TNG_CRITICAL);
1248 if(hash_mode == TNG_USE_HASH)
1250 tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
1251 contents_start_pos);
1253 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1255 /* Update previous frame set */
1256 if(frame_set->prev_frame_set_file_pos > 0)
1258 fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
1261 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1263 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1264 __FILE__, __LINE__);
1265 tng_data->input_file = temp;
1266 tng_block_destroy(&block);
1267 return(TNG_CRITICAL);
1270 contents_start_pos = ftell(tng_data->output_file);
1272 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
1273 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1275 if(tng_data->input_endianness_swap_func_64)
1277 if(tng_data->input_endianness_swap_func_64(tng_data,
1281 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1282 __FILE__, __LINE__);
1286 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1288 tng_data->input_file = temp;
1289 tng_block_destroy(&block);
1290 return(TNG_CRITICAL);
1293 if(hash_mode == TNG_USE_HASH)
1295 tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
1296 contents_start_pos);
1298 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1301 /* Update the frame set one medium stride step after */
1302 if(frame_set->medium_stride_next_frame_set_file_pos > 0)
1304 fseek(tng_data->output_file,
1305 (long)frame_set->medium_stride_next_frame_set_file_pos,
1308 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1310 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1311 __FILE__, __LINE__);
1312 tng_data->input_file = temp;
1313 tng_block_destroy(&block);
1314 return(TNG_CRITICAL);
1317 contents_start_pos = ftell(tng_data->output_file);
1319 fseek(tng_data->output_file, (long)block->block_contents_size - (3 *
1320 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1322 if(tng_data->input_endianness_swap_func_64)
1324 if(tng_data->input_endianness_swap_func_64(tng_data,
1328 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1329 __FILE__, __LINE__);
1333 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1335 tng_data->input_file = temp;
1336 tng_block_destroy(&block);
1337 return(TNG_CRITICAL);
1340 if(hash_mode == TNG_USE_HASH)
1342 tng_md5_hash_update(tng_data, block,
1343 frame_set->medium_stride_next_frame_set_file_pos,
1344 contents_start_pos);
1347 /* Update the frame set one medium stride step before */
1348 if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
1350 fseek(tng_data->output_file,
1351 (long)frame_set->medium_stride_prev_frame_set_file_pos,
1354 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1356 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1357 __FILE__, __LINE__);
1358 tng_data->input_file = temp;
1359 tng_block_destroy(&block);
1360 return(TNG_CRITICAL);
1363 contents_start_pos = ftell(tng_data->output_file);
1365 fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
1366 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1368 if(tng_data->input_endianness_swap_func_64)
1370 if(tng_data->input_endianness_swap_func_64(tng_data,
1374 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1375 __FILE__, __LINE__);
1379 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1381 tng_data->input_file = temp;
1382 tng_block_destroy(&block);
1383 return(TNG_CRITICAL);
1386 if(hash_mode == TNG_USE_HASH)
1388 tng_md5_hash_update(tng_data, block,
1389 frame_set->medium_stride_prev_frame_set_file_pos,
1390 contents_start_pos);
1394 /* Update the frame set one long stride step after */
1395 if(frame_set->long_stride_next_frame_set_file_pos > 0)
1397 fseek(tng_data->output_file,
1398 (long)frame_set->long_stride_next_frame_set_file_pos,
1401 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1403 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1404 __FILE__, __LINE__);
1405 tng_data->input_file = temp;
1406 tng_block_destroy(&block);
1407 return(TNG_CRITICAL);
1410 contents_start_pos = ftell(tng_data->output_file);
1412 fseek(tng_data->output_file, (long)block->block_contents_size - (1 *
1413 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1415 if(tng_data->input_endianness_swap_func_64)
1417 if(tng_data->input_endianness_swap_func_64(tng_data,
1421 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1422 __FILE__, __LINE__);
1426 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1428 tng_data->input_file = temp;
1429 tng_block_destroy(&block);
1430 return(TNG_CRITICAL);
1433 if(hash_mode == TNG_USE_HASH)
1435 tng_md5_hash_update(tng_data, block,
1436 frame_set->long_stride_next_frame_set_file_pos,
1437 contents_start_pos);
1440 /* Update the frame set one long stride step before */
1441 if(frame_set->long_stride_prev_frame_set_file_pos > 0)
1443 fseek(tng_data->output_file,
1444 (long)frame_set->long_stride_prev_frame_set_file_pos,
1447 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1449 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1450 __FILE__, __LINE__);
1451 tng_data->input_file = temp;
1452 tng_block_destroy(&block);
1453 return(TNG_CRITICAL);
1456 contents_start_pos = ftell(tng_data->output_file);
1458 fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
1459 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1461 if(tng_data->input_endianness_swap_func_64)
1463 if(tng_data->input_endianness_swap_func_64(tng_data,
1467 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1468 __FILE__, __LINE__);
1472 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1474 tng_data->input_file = temp;
1475 tng_block_destroy(&block);
1476 return(TNG_CRITICAL);
1479 if(hash_mode == TNG_USE_HASH)
1481 tng_md5_hash_update(tng_data, block,
1482 frame_set->long_stride_prev_frame_set_file_pos,
1483 contents_start_pos);
1487 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1489 tng_data->input_file = temp;
1491 tng_block_destroy(&block);
1493 return(TNG_SUCCESS);
1496 static tng_function_status tng_reread_frame_set_at_file_pos
1497 (tng_trajectory_t tng_data,
1500 tng_gen_block_t block;
1501 tng_function_status stat;
1503 tng_block_init(&block);
1505 fseek(tng_data->input_file, pos, SEEK_SET);
1508 stat = tng_block_header_read(tng_data, block);
1509 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1511 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
1512 __FILE__, __LINE__);
1513 tng_block_destroy(&block);
1514 return(TNG_FAILURE);
1517 if(tng_block_read_next(tng_data, block,
1518 TNG_SKIP_HASH) != TNG_SUCCESS)
1520 tng_block_destroy(&block);
1521 return(TNG_CRITICAL);
1525 tng_block_destroy(&block);
1527 return(TNG_SUCCESS);
1530 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1531 (tng_trajectory_t tng_data,
1534 int64_t orig_pos, curr_frame_set_pos;
1535 tng_gen_block_t block;
1536 tng_function_status stat;
1537 tng_trajectory_frame_set_t frame_set =
1538 &tng_data->current_trajectory_frame_set;
1540 orig_pos = ftell(tng_data->input_file);
1541 curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
1543 *pos = tng_data->first_trajectory_frame_set_input_file_pos;
1547 return(TNG_SUCCESS);
1550 fseek(tng_data->input_file, *pos, SEEK_SET);
1552 tng_block_init(&block);
1553 /* Read block headers first to see that a frame set block is found. */
1554 stat = tng_block_header_read(tng_data, block);
1555 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1557 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1558 __FILE__, __LINE__);
1559 tng_block_destroy(&block);
1560 return(TNG_FAILURE);
1563 if(tng_block_read_next(tng_data, block,
1564 TNG_SKIP_HASH) != TNG_SUCCESS)
1566 tng_block_destroy(&block);
1567 return(TNG_CRITICAL);
1570 /* Read all frame set blocks (not the blocks between them) */
1571 while(frame_set->next_frame_set_file_pos > 0)
1573 fseek(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1574 stat = tng_block_header_read(tng_data, block);
1575 if(stat == TNG_CRITICAL)
1577 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1578 __FILE__, __LINE__);
1579 tng_block_destroy(&block);
1580 return(TNG_CRITICAL);
1582 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1584 return(TNG_FAILURE);
1587 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
1588 if(stat != TNG_SUCCESS)
1590 tng_block_destroy(&block);
1593 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1594 if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
1595 tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
1597 *pos = tng_data->current_trajectory_frame_set_input_file_pos;
1601 /* Re-read the frame set that used to be the current one */
1602 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1604 fseek(tng_data->input_file, orig_pos, SEEK_SET);
1606 tng_block_destroy(&block);
1608 return(TNG_SUCCESS);
1611 static tng_function_status tng_frame_set_complete_migrate
1612 (tng_trajectory_t tng_data,
1613 int64_t block_start_pos,
1618 tng_bool updated = TNG_FALSE;
1622 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1624 return(TNG_CRITICAL);
1627 fseek(tng_data->input_file, block_start_pos, SEEK_SET);
1629 contents = malloc(block_len);
1632 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1633 block_len, __FILE__, __LINE__);
1634 return(TNG_CRITICAL);
1637 if(fread(contents, block_len, 1, tng_data->input_file) == 0)
1639 fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1640 __FILE__, __LINE__);
1642 return(TNG_CRITICAL);
1644 fseek(tng_data->output_file, new_pos, SEEK_SET);
1646 if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
1648 fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1649 __FILE__, __LINE__);
1651 return(TNG_CRITICAL);
1654 tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
1656 tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
1658 /* Update the general info block if needed */
1659 if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
1661 tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
1664 if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
1666 tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
1671 tng_header_pointers_update(tng_data, TNG_USE_HASH);
1674 /* Fill the block with NULL to avoid confusion. */
1675 for(i = 0; i < block_len; i++)
1679 fseek(tng_data->output_file, block_start_pos, SEEK_SET);
1681 /* FIXME: casting block_len to size_t is dangerous */
1682 fwrite(contents, 1, block_len, tng_data->output_file);
1686 return(TNG_SUCCESS);
1689 static tng_function_status tng_length_of_current_frame_set_contents_get
1690 (tng_trajectory_t tng_data,
1693 int64_t orig_pos, pos, curr_frame_set_pos;
1694 tng_gen_block_t block;
1695 tng_function_status stat;
1697 orig_pos = ftell(tng_data->input_file);
1698 curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
1702 fseek(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
1704 tng_block_init(&block);
1705 /* Read block headers first to see that a frame set block is found. */
1706 stat = tng_block_header_read(tng_data, block);
1707 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1709 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
1710 curr_frame_set_pos, __FILE__, __LINE__);
1711 tng_block_destroy(&block);
1712 return(TNG_FAILURE);
1715 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1716 while(stat == TNG_SUCCESS)
1718 fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
1719 *len += block->header_contents_size + block->block_contents_size;
1720 pos += block->header_contents_size + block->block_contents_size;
1721 if(pos >= tng_data->input_file_len)
1725 stat = tng_block_header_read(tng_data, block);
1726 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1732 /* Re-read the frame set that used to be the current one */
1733 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1735 fseek(tng_data->input_file, orig_pos, SEEK_SET);
1737 tng_block_destroy(&block);
1739 return(TNG_SUCCESS);
1742 /** Migrate blocks in the file to make room for new data in a block. This
1743 * is required e.g. when adding data to a block or extending strings in a
1745 * @param tng_data is a trajectory data container.
1746 * @param start_pos is the position from which to start moving data, usually
1747 * the byte after the end of the block to which data was added.
1748 * @param offset is the number of bytes that were inserted.
1749 * @details Trajectory blocks (frame sets and their related blocks) are moved
1750 * to the end of the file (if needed) in order to make room for non-trajectory
1753 static tng_function_status tng_migrate_data_in_file
1754 (tng_trajectory_t tng_data,
1758 int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
1759 tng_gen_block_t block;
1760 tng_function_status stat;
1765 return(TNG_SUCCESS);
1768 temp = tng_data->input_file;
1770 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1771 if(stat != TNG_SUCCESS)
1773 tng_data->input_file = temp;
1777 tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
1779 empty_space = traj_start_pos - (start_pos - 1);
1781 if(empty_space >= offset)
1783 return(TNG_SUCCESS);
1786 orig_file_pos = ftell(tng_data->input_file);
1787 tng_block_init(&block);
1789 while(empty_space < offset)
1791 fseek(tng_data->input_file, traj_start_pos, SEEK_SET);
1792 stat = tng_block_header_read(tng_data, block);
1793 if(stat == TNG_CRITICAL)
1795 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
1796 __FILE__, __LINE__);
1797 tng_block_destroy(&block);
1798 tng_data->input_file = temp;
1799 return(TNG_CRITICAL);
1801 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1803 tng_data->input_file = temp;
1804 tng_block_destroy(&block);
1805 return(TNG_FAILURE);
1807 stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
1808 if(stat != TNG_SUCCESS)
1810 tng_data->input_file = temp;
1811 tng_block_destroy(&block);
1814 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1815 frame_set_length, tng_data->input_file_len);
1816 if(stat != TNG_SUCCESS)
1818 tng_data->input_file = temp;
1819 tng_block_destroy(&block);
1823 empty_space += frame_set_length;
1825 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
1826 tng_block_destroy(&block);
1828 return(TNG_SUCCESS);
1831 static tng_function_status tng_block_header_len_calculate
1832 (const tng_trajectory_t tng_data,
1833 tng_gen_block_t block,
1839 /* If the string is unallocated allocate memory for just string
1843 block->name = malloc(1);
1846 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1847 __FILE__, __LINE__);
1848 return(TNG_CRITICAL);
1853 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1855 /* Calculate the size of the header to write */
1856 *len = sizeof(block->header_contents_size) +
1857 sizeof(block->block_contents_size) +
1859 sizeof(block->block_version) +
1863 return (TNG_SUCCESS);
1866 /** Write the header of a data block, regardless of its type
1867 * @param tng_data is a trajectory data container.
1868 * @param block is a general block container.
1869 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1870 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1871 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1872 * error has occured.
1874 static tng_function_status tng_block_header_write
1875 (tng_trajectory_t tng_data,
1876 tng_gen_block_t block,
1877 const char hash_mode)
1879 int name_len, offset = 0;
1881 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1883 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1885 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1886 __FILE__, __LINE__);
1887 return(TNG_CRITICAL);
1890 if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
1893 fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
1894 __FILE__, __LINE__);
1895 return(TNG_CRITICAL);
1898 if(hash_mode == TNG_USE_HASH)
1900 tng_block_md5_hash_generate(block);
1903 if(block->header_contents)
1905 free(block->header_contents);
1908 block->header_contents = malloc(block->header_contents_size);
1909 if(!block->header_contents)
1911 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1912 block->header_contents_size, __FILE__, __LINE__);
1913 return(TNG_CRITICAL);
1916 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1918 /* First copy all data into the header_contents block and finally write
1919 * the whole block at once. */
1920 memcpy(block->header_contents, &block->header_contents_size,
1921 sizeof(block->header_contents_size));
1922 if(tng_data->output_endianness_swap_func_64)
1924 if(tng_data->output_endianness_swap_func_64(tng_data,
1925 (int64_t *)block->header_contents+offset)
1928 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1929 __FILE__, __LINE__);
1932 offset += sizeof(block->header_contents_size);
1934 memcpy(block->header_contents+offset, &block->block_contents_size,
1935 sizeof(block->block_contents_size));
1936 if(tng_data->output_endianness_swap_func_64)
1938 if(tng_data->output_endianness_swap_func_64(tng_data,
1939 (int64_t *)block->header_contents+offset)
1942 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1943 __FILE__, __LINE__);
1946 offset += sizeof(block->block_contents_size);
1948 memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
1949 if(tng_data->output_endianness_swap_func_64)
1951 if(tng_data->output_endianness_swap_func_64(tng_data,
1952 (int64_t *)block->header_contents+offset)
1955 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1956 __FILE__, __LINE__);
1959 offset += sizeof(block->id);
1961 memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
1962 offset += TNG_MD5_HASH_LEN;
1964 strncpy(block->header_contents+offset, block->name, name_len);
1967 memcpy(block->header_contents+offset, &block->block_version,
1968 sizeof(block->block_version));
1969 if(tng_data->output_endianness_swap_func_64)
1971 if(tng_data->output_endianness_swap_func_64(tng_data,
1972 (int64_t *)block->header_contents+offset)
1975 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1976 __FILE__, __LINE__);
1980 if(fwrite(block->header_contents, block->header_contents_size,
1981 1, tng_data->output_file) != 1)
1983 fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
1984 return(TNG_CRITICAL);
1986 return(TNG_SUCCESS);
1989 static tng_function_status tng_general_info_block_len_calculate
1990 (tng_trajectory_t tng_data,
1993 int first_program_name_len, first_user_name_len;
1994 int first_computer_name_len, first_pgp_signature_len;
1995 int last_program_name_len, last_user_name_len;
1996 int last_computer_name_len, last_pgp_signature_len;
1997 int forcefield_name_len;
1999 /* If the strings are unallocated allocate memory for just string
2001 if(!tng_data->first_program_name)
2003 tng_data->first_program_name = malloc(1);
2004 if(!tng_data->first_program_name)
2006 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2007 __FILE__, __LINE__);
2008 return(TNG_CRITICAL);
2010 tng_data->first_program_name[0] = 0;
2012 if(!tng_data->last_program_name)
2014 tng_data->last_program_name = malloc(1);
2015 if(!tng_data->last_program_name)
2017 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2018 __FILE__, __LINE__);
2019 return(TNG_CRITICAL);
2021 tng_data->last_program_name[0] = 0;
2023 if(!tng_data->first_user_name)
2025 tng_data->first_user_name = malloc(1);
2026 if(!tng_data->first_user_name)
2028 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2029 __FILE__, __LINE__);
2030 return(TNG_CRITICAL);
2032 tng_data->first_user_name[0] = 0;
2034 if(!tng_data->last_user_name)
2036 tng_data->last_user_name = malloc(1);
2037 if(!tng_data->last_user_name)
2039 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2040 __FILE__, __LINE__);
2041 return(TNG_CRITICAL);
2043 tng_data->last_user_name[0] = 0;
2045 if(!tng_data->first_computer_name)
2047 tng_data->first_computer_name = malloc(1);
2048 if(!tng_data->first_computer_name)
2050 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2051 __FILE__, __LINE__);
2052 return(TNG_CRITICAL);
2054 tng_data->first_computer_name[0] = 0;
2056 if(!tng_data->last_computer_name)
2058 tng_data->last_computer_name = malloc(1);
2059 if(!tng_data->last_computer_name)
2061 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2062 __FILE__, __LINE__);
2063 return(TNG_CRITICAL);
2065 tng_data->last_computer_name[0] = 0;
2067 if(!tng_data->first_pgp_signature)
2069 tng_data->first_pgp_signature = malloc(1);
2070 if(!tng_data->first_pgp_signature)
2072 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2073 __FILE__, __LINE__);
2074 return(TNG_CRITICAL);
2076 tng_data->first_pgp_signature[0] = 0;
2078 if(!tng_data->last_pgp_signature)
2080 tng_data->last_pgp_signature = malloc(1);
2081 if(!tng_data->last_pgp_signature)
2083 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2084 __FILE__, __LINE__);
2085 return(TNG_CRITICAL);
2087 tng_data->last_pgp_signature[0] = 0;
2089 if(!tng_data->forcefield_name)
2091 tng_data->forcefield_name = malloc(1);
2092 if(!tng_data->forcefield_name)
2094 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2095 __FILE__, __LINE__);
2096 return(TNG_CRITICAL);
2098 tng_data->forcefield_name[0] = 0;
2101 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2103 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2105 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2107 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2109 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2111 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2113 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2115 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2117 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2120 *len = sizeof(tng_data->time) +
2121 sizeof(tng_data->var_num_atoms_flag) +
2122 sizeof(tng_data->frame_set_n_frames) +
2123 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
2124 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
2125 sizeof(tng_data->medium_stride_length) +
2126 sizeof(tng_data->long_stride_length) +
2127 sizeof(tng_data->distance_unit_exponential) +
2128 first_program_name_len +
2129 last_program_name_len +
2130 first_user_name_len +
2131 last_user_name_len +
2132 first_computer_name_len +
2133 last_computer_name_len +
2134 first_pgp_signature_len +
2135 last_pgp_signature_len +
2136 forcefield_name_len;
2138 return(TNG_SUCCESS);
2141 /** Read a general info block. This is the first block of a TNG file.
2142 * Populate the fields in tng_data.
2143 * @param tng_data is a trajectory data container.
2144 * @param block is a general block container.
2145 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2146 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2147 * compared to the md5 hash of the read contents to ensure valid data.
2148 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2149 * error has occured.
2151 static tng_function_status tng_general_info_block_read
2152 (tng_trajectory_t tng_data, tng_gen_block_t block,
2153 const char hash_mode)
2155 int len, offset = 0;
2160 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2162 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2164 return(TNG_CRITICAL);
2167 temp = realloc(block->block_contents, block->block_contents_size);
2170 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2171 block->block_contents_size, __FILE__, __LINE__);
2172 free(block->block_contents);
2173 block->block_contents = 0;
2174 return(TNG_CRITICAL);
2176 block->block_contents = temp;
2178 /* Read the whole block into block_contents to be able to write it to disk
2179 * even if it cannot be interpreted. */
2180 if(fread(block->block_contents, block->block_contents_size, 1,
2181 tng_data->input_file) == 0)
2183 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
2184 return(TNG_CRITICAL);
2187 /* FIXME: Does not check if the size of the contents matches the expected
2188 * size or if the contents can be read. */
2190 if(hash_mode == TNG_USE_HASH)
2192 tng_md5_hash_match_verify(block, &same_hash);
2193 if(same_hash != TNG_TRUE)
2195 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
2197 __FILE__, __LINE__);
2198 /* return(TNG_FAILURE); */
2202 len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
2203 temp = realloc(tng_data->first_program_name, len);
2206 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2207 __FILE__, __LINE__);
2208 free(tng_data->first_program_name);
2209 tng_data->first_program_name = 0;
2210 return(TNG_CRITICAL);
2212 tng_data->first_program_name = temp;
2213 strncpy(tng_data->first_program_name, block->block_contents, len);
2216 len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
2217 temp = realloc(tng_data->last_program_name, len);
2220 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2221 __FILE__, __LINE__);
2222 free(tng_data->last_program_name);
2223 tng_data->last_program_name = 0;
2224 return(TNG_CRITICAL);
2226 tng_data->last_program_name = temp;
2227 strncpy(tng_data->last_program_name, block->block_contents + offset, len);
2230 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2231 temp = realloc(tng_data->first_user_name, len);
2234 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2235 __FILE__, __LINE__);
2236 free(tng_data->first_user_name);
2237 tng_data->first_user_name = 0;
2238 return(TNG_CRITICAL);
2240 tng_data->first_user_name = temp;
2241 strncpy(tng_data->first_user_name, block->block_contents+offset, len);
2244 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2245 temp = realloc(tng_data->last_user_name, len);
2248 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2249 __FILE__, __LINE__);
2250 free(tng_data->last_user_name);
2251 tng_data->last_user_name = 0;
2252 return(TNG_CRITICAL);
2254 tng_data->last_user_name = temp;
2255 strncpy(tng_data->last_user_name, block->block_contents+offset, len);
2258 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2259 temp = realloc(tng_data->first_computer_name, len);
2262 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2263 __FILE__, __LINE__);
2264 free(tng_data->first_computer_name);
2265 tng_data->first_computer_name = 0;
2266 return(TNG_CRITICAL);
2268 tng_data->first_computer_name = temp;
2269 strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
2272 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2273 temp = realloc(tng_data->last_computer_name, len);
2276 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2277 __FILE__, __LINE__);
2278 free(tng_data->last_computer_name);
2279 tng_data->last_computer_name = 0;
2280 return(TNG_CRITICAL);
2282 tng_data->last_computer_name = temp;
2283 strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
2286 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2287 temp = realloc(tng_data->first_pgp_signature, len);
2290 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2291 __FILE__, __LINE__);
2292 free(tng_data->first_pgp_signature);
2293 tng_data->first_pgp_signature = 0;
2294 return(TNG_CRITICAL);
2296 tng_data->first_pgp_signature = temp;
2297 strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
2300 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2301 temp = realloc(tng_data->last_pgp_signature, len);
2304 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2305 __FILE__, __LINE__);
2306 free(tng_data->last_pgp_signature);
2307 tng_data->last_pgp_signature = 0;
2308 return(TNG_CRITICAL);
2310 tng_data->last_pgp_signature = temp;
2311 strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
2314 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2315 temp = realloc(tng_data->forcefield_name, len);
2318 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2319 __FILE__, __LINE__);
2320 free(tng_data->forcefield_name);
2321 tng_data->forcefield_name = 0;
2322 return(TNG_CRITICAL);
2324 tng_data->forcefield_name = temp;
2325 strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
2328 memcpy(&tng_data->time, block->block_contents+offset,
2329 sizeof(tng_data->time));
2330 if(tng_data->input_endianness_swap_func_64)
2332 if(tng_data->input_endianness_swap_func_64(tng_data,
2336 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2337 __FILE__, __LINE__);
2340 offset += sizeof(tng_data->time);
2342 memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
2343 sizeof(tng_data->var_num_atoms_flag));
2344 offset += sizeof(tng_data->var_num_atoms_flag);
2346 memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
2347 sizeof(tng_data->frame_set_n_frames));
2348 if(tng_data->input_endianness_swap_func_64)
2350 if(tng_data->input_endianness_swap_func_64(tng_data,
2351 &tng_data->frame_set_n_frames)
2354 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2355 __FILE__, __LINE__);
2358 offset += sizeof(tng_data->frame_set_n_frames);
2360 memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
2361 block->block_contents+offset,
2362 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
2363 if(tng_data->input_endianness_swap_func_64)
2365 if(tng_data->input_endianness_swap_func_64(tng_data,
2366 &tng_data->first_trajectory_frame_set_input_file_pos)
2369 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2370 __FILE__, __LINE__);
2373 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
2375 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
2376 tng_data->first_trajectory_frame_set_input_file_pos;
2379 memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
2380 block->block_contents+offset,
2381 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
2382 if(tng_data->input_endianness_swap_func_64)
2384 if(tng_data->input_endianness_swap_func_64(tng_data,
2385 &tng_data->last_trajectory_frame_set_input_file_pos)
2388 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2389 __FILE__, __LINE__);
2392 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
2394 memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
2395 sizeof(tng_data->medium_stride_length));
2396 if(tng_data->input_endianness_swap_func_64)
2398 if(tng_data->input_endianness_swap_func_64(tng_data,
2399 &tng_data->medium_stride_length)
2402 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2403 __FILE__, __LINE__);
2406 offset += sizeof(tng_data->medium_stride_length);
2408 memcpy(&tng_data->long_stride_length, block->block_contents+offset,
2409 sizeof(tng_data->long_stride_length));
2410 if(tng_data->input_endianness_swap_func_64)
2412 if(tng_data->input_endianness_swap_func_64(tng_data,
2413 &tng_data->long_stride_length)
2416 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2417 __FILE__, __LINE__);
2420 offset += sizeof(tng_data->long_stride_length);
2422 if(block->block_version >= 3)
2424 memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
2425 sizeof(tng_data->distance_unit_exponential));
2426 if(tng_data->input_endianness_swap_func_64)
2428 if(tng_data->input_endianness_swap_func_64(tng_data,
2429 &tng_data->distance_unit_exponential)
2432 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2433 __FILE__, __LINE__);
2438 return(TNG_SUCCESS);
2441 /** Write a general info block. This is the first block of a TNG file.
2442 * @param tng_data is a trajectory data container.
2443 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2444 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2445 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2446 * error has occured.
2448 static tng_function_status tng_general_info_block_write
2449 (tng_trajectory_t tng_data,
2450 const char hash_mode)
2452 int first_program_name_len, first_user_name_len;
2453 int first_computer_name_len, first_pgp_signature_len;
2454 int last_program_name_len, last_user_name_len;
2455 int last_computer_name_len, last_pgp_signature_len;
2456 int forcefield_name_len, name_len;
2458 tng_gen_block_t block;
2460 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2462 return(TNG_CRITICAL);
2465 fseek(tng_data->output_file, 0, SEEK_SET);
2467 tng_block_init(&block);
2469 name_len = (int)strlen("GENERAL INFO");
2471 block->name = malloc(name_len + 1);
2474 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2475 name_len+1, __FILE__, __LINE__);
2476 tng_block_destroy(&block);
2477 return(TNG_CRITICAL);
2480 strcpy(block->name, "GENERAL INFO");
2481 block->id = TNG_GENERAL_INFO;
2483 if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
2486 fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2487 __FILE__, __LINE__);
2488 tng_block_destroy(&block);
2489 return(TNG_CRITICAL);
2492 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2494 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2496 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2498 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2500 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2502 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2504 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2506 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2508 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2511 if(block->block_contents)
2513 free(block->block_contents);
2515 block->block_contents = malloc(block->block_contents_size);
2516 if(!block->block_contents)
2518 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2519 block->block_contents_size, __FILE__, __LINE__);
2520 tng_block_destroy(&block);
2521 return(TNG_CRITICAL);
2524 strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
2525 offset += first_program_name_len;
2527 strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
2528 offset += last_program_name_len;
2530 strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
2531 offset += first_user_name_len;
2533 strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
2534 offset += last_user_name_len;
2536 strncpy(block->block_contents+offset, tng_data->first_computer_name,
2537 first_computer_name_len);
2538 offset += first_computer_name_len;
2540 strncpy(block->block_contents+offset, tng_data->last_computer_name,
2541 last_computer_name_len);
2542 offset += last_computer_name_len;
2544 strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
2545 first_pgp_signature_len);
2546 offset += first_pgp_signature_len;
2548 strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
2549 last_pgp_signature_len);
2550 offset += last_pgp_signature_len;
2552 strncpy(block->block_contents+offset, tng_data->forcefield_name,
2553 forcefield_name_len);
2554 offset += forcefield_name_len;
2556 memcpy(block->block_contents+offset, &tng_data->time,
2557 sizeof(tng_data->time));
2558 if(tng_data->output_endianness_swap_func_64)
2560 if(tng_data->output_endianness_swap_func_64(tng_data,
2561 (int64_t *)block->header_contents+offset)
2564 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2565 __FILE__, __LINE__);
2568 offset += sizeof(tng_data->time);
2570 memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
2571 sizeof(tng_data->var_num_atoms_flag));
2572 offset += sizeof(tng_data->var_num_atoms_flag);
2574 memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
2575 sizeof(tng_data->frame_set_n_frames));
2576 if(tng_data->output_endianness_swap_func_64)
2578 if(tng_data->output_endianness_swap_func_64(tng_data,
2579 (int64_t *)block->header_contents+offset)
2582 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2583 __FILE__, __LINE__);
2586 offset += sizeof(tng_data->frame_set_n_frames);
2588 memcpy(block->block_contents+offset,
2589 &tng_data->first_trajectory_frame_set_output_file_pos,
2590 sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
2591 if(tng_data->output_endianness_swap_func_64)
2593 if(tng_data->output_endianness_swap_func_64(tng_data,
2594 (int64_t *)block->header_contents+offset)
2597 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2598 __FILE__, __LINE__);
2601 offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
2603 memcpy(block->block_contents+offset,
2604 &tng_data->last_trajectory_frame_set_output_file_pos,
2605 sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
2606 if(tng_data->output_endianness_swap_func_64)
2608 if(tng_data->output_endianness_swap_func_64(tng_data,
2609 (int64_t *)block->header_contents+offset)
2612 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2613 __FILE__, __LINE__);
2616 offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
2618 memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
2619 sizeof(tng_data->medium_stride_length));
2620 if(tng_data->output_endianness_swap_func_64)
2622 if(tng_data->output_endianness_swap_func_64(tng_data,
2623 (int64_t *)block->header_contents+offset)
2626 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2627 __FILE__, __LINE__);
2630 offset += sizeof(tng_data->medium_stride_length);
2632 memcpy(block->block_contents+offset, &tng_data->long_stride_length,
2633 sizeof(tng_data->long_stride_length));
2634 if(tng_data->output_endianness_swap_func_64)
2636 if(tng_data->output_endianness_swap_func_64(tng_data,
2637 (int64_t *)block->header_contents+offset)
2640 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2641 __FILE__, __LINE__);
2644 offset += sizeof(tng_data->long_stride_length);
2646 memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
2647 sizeof(tng_data->distance_unit_exponential));
2648 if(tng_data->output_endianness_swap_func_64)
2650 if(tng_data->output_endianness_swap_func_64(tng_data,
2651 (int64_t *)block->header_contents+offset)
2654 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2655 __FILE__, __LINE__);
2659 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
2661 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2662 tng_data->output_file_path, __FILE__, __LINE__);
2663 tng_block_destroy(&block);
2664 return(TNG_CRITICAL);
2667 if(fwrite(block->block_contents, block->block_contents_size, 1,
2668 tng_data->output_file) != 1)
2670 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
2671 tng_block_destroy(&block);
2672 return(TNG_CRITICAL);
2675 tng_block_destroy(&block);
2677 return(TNG_SUCCESS);
2680 /** Read the chain data of a molecules block.
2681 * @param tng_data is a trajectory data container.
2682 * @param block is a general block container.
2683 * @param chain is the chain data container.
2684 * @param offset is the offset of the block input and is updated when reading.
2685 * @return TNG_SUCCESS(0) is successful.
2687 static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
2688 tng_gen_block_t block,
2694 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2696 memcpy(&chain->id, block->block_contents+*offset,
2698 if(tng_data->input_endianness_swap_func_64)
2700 if(tng_data->input_endianness_swap_func_64(tng_data,
2704 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2705 __FILE__, __LINE__);
2708 *offset += sizeof(chain->id);
2710 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2712 chain->name = malloc(len);
2713 strncpy(chain->name,
2714 block->block_contents+*offset, len);
2717 memcpy(&chain->n_residues, block->block_contents+*offset,
2718 sizeof(chain->n_residues));
2719 if(tng_data->input_endianness_swap_func_64)
2721 if(tng_data->input_endianness_swap_func_64(tng_data,
2725 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2726 __FILE__, __LINE__);
2729 *offset += sizeof(chain->n_residues);
2731 return(TNG_SUCCESS);
2734 /** Write the chain data of a molecules block.
2735 * @param tng_data is a trajectory data container.
2736 * @param block is a general block container.
2737 * @param chain is the chain data container.
2738 * @param offset is the offset of the block output and is updated when writing.
2739 * @return TNG_SUCCESS(0) is successful.
2741 static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
2742 tng_gen_block_t block,
2748 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2750 memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
2751 if(tng_data->output_endianness_swap_func_64)
2753 if(tng_data->output_endianness_swap_func_64(tng_data,
2754 (int64_t *)block->header_contents+*offset)
2757 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2758 __FILE__, __LINE__);
2761 *offset += sizeof(chain->id);
2763 len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2764 strncpy(block->block_contents + *offset, chain->name, len);
2767 memcpy(block->block_contents+*offset, &chain->n_residues,
2768 sizeof(chain->n_residues));
2769 if(tng_data->output_endianness_swap_func_64)
2771 if(tng_data->output_endianness_swap_func_64(tng_data,
2772 (int64_t *)block->header_contents+*offset)
2775 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2776 __FILE__, __LINE__);
2779 *offset += sizeof(chain->n_residues);
2781 return(TNG_SUCCESS);
2784 /** Read the residue data of a molecules block.
2785 * @param tng_data is a trajectory data container.
2786 * @param block is a general block container.
2787 * @param residue is the residue data container.
2788 * @param offset is the offset of the block input and is updated when reading.
2789 * @return TNG_SUCCESS(0) is successful.
2791 static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
2792 tng_gen_block_t block,
2793 tng_residue_t residue,
2798 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2800 memcpy(&residue->id, block->block_contents+*offset,
2801 sizeof(residue->id));
2802 if(tng_data->input_endianness_swap_func_64)
2804 if(tng_data->input_endianness_swap_func_64(tng_data,
2808 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2809 __FILE__, __LINE__);
2812 *offset += sizeof(residue->id);
2814 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2816 residue->name = malloc(len);
2817 strncpy(residue->name,
2818 block->block_contents+*offset, len);
2821 memcpy(&residue->n_atoms, block->block_contents+*offset,
2822 sizeof(residue->n_atoms));
2823 if(tng_data->input_endianness_swap_func_64)
2825 if(tng_data->input_endianness_swap_func_64(tng_data,
2829 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2830 __FILE__, __LINE__);
2833 *offset += sizeof(residue->n_atoms);
2835 return(TNG_SUCCESS);
2838 /** Write the residue data of a molecules block.
2839 * @param tng_data is a trajectory data container.
2840 * @param block is a general block container.
2841 * @param residue is the residue data container.
2842 * @param offset is the offset of the block output and is updated when writing.
2843 * @return TNG_SUCCESS(0) is successful.
2845 static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
2846 tng_gen_block_t block,
2847 tng_residue_t residue,
2852 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2854 memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
2855 if(tng_data->output_endianness_swap_func_64)
2857 if(tng_data->output_endianness_swap_func_64(tng_data,
2858 (int64_t *)block->header_contents+*offset)
2861 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2862 __FILE__, __LINE__);
2865 *offset += sizeof(residue->id);
2867 len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2868 strncpy(block->block_contents + *offset, residue->name, len);
2871 memcpy(block->block_contents+*offset, &residue->n_atoms,
2872 sizeof(residue->n_atoms));
2873 if(tng_data->output_endianness_swap_func_64)
2875 if(tng_data->output_endianness_swap_func_64(tng_data,
2876 (int64_t *)block->header_contents+*offset)
2879 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2880 __FILE__, __LINE__);
2883 *offset += sizeof(residue->n_atoms);
2885 return(TNG_SUCCESS);
2888 /** Read the atom data of a molecules block.
2889 * @param tng_data is a trajectory data container.
2890 * @param block is a general block container.
2891 * @param atom is the atom data container.
2892 * @param offset is the offset of the block input and is updated when reading.
2893 * @return TNG_SUCCESS(0) is successful.
2895 static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
2896 tng_gen_block_t block,
2902 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2904 memcpy(&atom->id, block->block_contents+*offset,
2906 if(tng_data->input_endianness_swap_func_64)
2908 if(tng_data->input_endianness_swap_func_64(tng_data,
2912 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2913 __FILE__, __LINE__);
2916 *offset += sizeof(atom->id);
2918 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2920 atom->name = malloc(len);
2922 block->block_contents+*offset, len);
2925 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2927 atom->atom_type = malloc(len);
2928 strncpy(atom->atom_type,
2929 block->block_contents+*offset, len);
2932 return(TNG_SUCCESS);
2935 /** Write the atom data of a molecules block.
2936 * @param tng_data is a trajectory data container.
2937 * @param block is a general block container.
2938 * @param atom is the atom data container.
2939 * @param offset is the offset of the block output and is updated when writing.
2940 * @return TNG_SUCCESS(0) is successful.
2942 static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
2943 tng_gen_block_t block,
2949 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2951 memcpy(block->block_contents+*offset, &atom->id,
2953 if(tng_data->output_endianness_swap_func_64)
2955 if(tng_data->output_endianness_swap_func_64(tng_data,
2956 (int64_t *)block->header_contents+*offset)
2959 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2960 __FILE__, __LINE__);
2963 *offset += sizeof(atom->id);
2965 len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2966 strncpy(block->block_contents + *offset, atom->name, len);
2969 len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2970 strncpy(block->block_contents + *offset, atom->atom_type, len);
2973 return(TNG_SUCCESS);
2976 static tng_function_status tng_molecules_block_len_calculate
2977 (const tng_trajectory_t tng_data,
2981 tng_molecule_t molecule;
2983 tng_residue_t residue;
2989 for(i = 0; i < tng_data->n_molecules; i++)
2991 molecule = &tng_data->molecules[i];
2994 molecule->name = malloc(1);
2997 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2998 __FILE__, __LINE__);
2999 return(TNG_CRITICAL);
3001 molecule->name[0] = 0;
3003 *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3005 chain = molecule->chains;
3006 for(j = 0; j < molecule->n_chains; j++)
3008 *len += sizeof(chain->id);
3012 chain->name = malloc(1);
3015 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3016 __FILE__, __LINE__);
3017 return(TNG_CRITICAL);
3021 *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
3023 *len += sizeof(chain->n_residues);
3028 residue = molecule->residues;
3029 for(j = 0; j < molecule->n_residues; j++)
3031 *len += sizeof(residue->id);
3035 residue->name = malloc(1);
3038 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3039 __FILE__, __LINE__);
3040 return(TNG_CRITICAL);
3042 residue->name[0] = 0;
3044 *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
3046 *len += sizeof(residue->n_atoms);
3051 atom = molecule->atoms;
3052 for(j = 0; j < molecule->n_atoms; j++)
3054 *len += sizeof(atom->id);
3057 atom->name = malloc(1);
3060 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3061 __FILE__, __LINE__);
3062 return(TNG_CRITICAL);
3066 *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
3068 if(!atom->atom_type)
3070 atom->atom_type = malloc(1);
3071 if(!atom->atom_type)
3073 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3074 __FILE__, __LINE__);
3075 return(TNG_CRITICAL);
3077 atom->atom_type[0] = 0;
3079 *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
3084 for(j = 0; j < molecule->n_bonds; j++)
3086 *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
3089 *len += sizeof(tng_data->n_molecules) +
3090 (sizeof(molecule->id) +
3091 sizeof(molecule->quaternary_str) +
3092 sizeof(molecule->n_chains) +
3093 sizeof(molecule->n_residues) +
3094 sizeof(molecule->n_atoms) +
3095 sizeof(molecule->n_bonds)) *
3096 tng_data->n_molecules;
3098 if(!tng_data->var_num_atoms_flag)
3100 *len += tng_data->n_molecules * sizeof(int64_t);
3103 return(TNG_SUCCESS);
3106 /** Read a molecules block. Contains chain, residue and atom data
3107 * @param tng_data is a trajectory data container.
3108 * @param block is a general block container.
3109 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3110 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3111 * compared to the md5 hash of the read contents to ensure valid data.
3112 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3113 * error has occured.
3115 static tng_function_status tng_molecules_block_read
3116 (tng_trajectory_t tng_data,
3117 tng_gen_block_t block,
3118 const char hash_mode)
3121 int len, offset = 0;
3122 tng_molecule_t molecule;
3124 tng_residue_t residue;
3129 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3131 return(TNG_CRITICAL);
3134 if(block->block_contents)
3136 free(block->block_contents);
3139 block->block_contents = malloc(block->block_contents_size);
3140 if(!block->block_contents)
3142 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3143 block->block_contents_size, __FILE__, __LINE__);
3144 return(TNG_CRITICAL);
3147 /* Read the whole block into block_contents to be able to write it to disk
3148 * even if it cannot be interpreted. */
3149 if(fread(block->block_contents, block->block_contents_size, 1,
3150 tng_data->input_file) == 0)
3152 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3155 /* FIXME: Does not check if the size of the contents matches the expected
3156 * size or if the contents can be read. */
3158 if(hash_mode == TNG_USE_HASH)
3160 tng_md5_hash_match_verify(block, &same_hash);
3161 if(same_hash != TNG_TRUE)
3163 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3165 __FILE__, __LINE__);
3169 if(tng_data->molecules)
3171 for(i=0; i<tng_data->n_molecules; i++)
3173 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
3175 free(tng_data->molecules);
3176 tng_data->molecules = 0;
3177 tng_data->n_molecules = 0;
3180 memcpy(&tng_data->n_molecules, block->block_contents,
3181 sizeof(tng_data->n_molecules));
3182 if(tng_data->input_endianness_swap_func_64)
3184 if(tng_data->input_endianness_swap_func_64(tng_data,
3185 &tng_data->n_molecules)
3188 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3189 __FILE__, __LINE__);
3192 offset += sizeof(tng_data->n_molecules);
3194 if(tng_data->molecules)
3196 free(tng_data->molecules);
3199 tng_data->n_particles = 0;
3201 tng_data->molecules = malloc(tng_data->n_molecules *
3202 sizeof(struct tng_molecule));
3203 if(!tng_data->molecules)
3205 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3206 tng_data->n_molecules * sizeof(struct tng_molecule),
3207 __FILE__, __LINE__);
3208 return(TNG_CRITICAL);
3211 if(!tng_data->var_num_atoms_flag)
3213 if(tng_data->molecule_cnt_list)
3215 free(tng_data->molecule_cnt_list);
3217 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
3218 tng_data->n_molecules);
3219 if(!tng_data->molecule_cnt_list)
3221 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3222 tng_data->n_molecules * sizeof(struct tng_molecule),
3223 __FILE__, __LINE__);
3224 return(TNG_CRITICAL);
3228 /* Read each molecule from file */
3229 for(i=0; i < tng_data->n_molecules; i++)
3231 molecule = &tng_data->molecules[i];
3233 memcpy(&molecule->id, block->block_contents+offset,
3234 sizeof(molecule->id));
3235 if(tng_data->input_endianness_swap_func_64)
3237 if(tng_data->input_endianness_swap_func_64(tng_data,
3241 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3242 __FILE__, __LINE__);
3245 offset += sizeof(molecule->id);
3247 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
3248 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
3249 molecule->name = malloc(len);
3250 strncpy(molecule->name, block->block_contents+offset, len);
3253 memcpy(&molecule->quaternary_str, block->block_contents+offset,
3254 sizeof(molecule->quaternary_str));
3255 if(tng_data->input_endianness_swap_func_64)
3257 if(tng_data->input_endianness_swap_func_64(tng_data,
3258 &molecule->quaternary_str)
3261 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3262 __FILE__, __LINE__);
3265 offset += sizeof(molecule->quaternary_str);
3267 if(!tng_data->var_num_atoms_flag)
3269 memcpy(&tng_data->molecule_cnt_list[i],
3270 block->block_contents+offset,
3272 if(tng_data->input_endianness_swap_func_64)
3274 if(tng_data->input_endianness_swap_func_64(tng_data,
3275 &tng_data->molecule_cnt_list[i])
3278 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3279 __FILE__, __LINE__);
3282 offset += sizeof(int64_t);
3286 memcpy(&molecule->n_chains, block->block_contents+offset,
3287 sizeof(molecule->n_chains));
3288 if(tng_data->input_endianness_swap_func_64)
3290 if(tng_data->input_endianness_swap_func_64(tng_data,
3291 &molecule->n_chains)
3294 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3295 __FILE__, __LINE__);
3298 offset += sizeof(molecule->n_chains);
3300 memcpy(&molecule->n_residues, block->block_contents+offset,
3301 sizeof(molecule->n_residues));
3302 if(tng_data->input_endianness_swap_func_64)
3304 if(tng_data->input_endianness_swap_func_64(tng_data,
3305 &molecule->n_residues)
3308 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3309 __FILE__, __LINE__);
3312 offset += sizeof(molecule->n_residues);
3314 memcpy(&molecule->n_atoms, block->block_contents+offset,
3315 sizeof(molecule->n_atoms));
3316 if(tng_data->input_endianness_swap_func_64)
3318 if(tng_data->input_endianness_swap_func_64(tng_data,
3322 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3323 __FILE__, __LINE__);
3326 offset += sizeof(molecule->n_atoms);
3328 tng_data->n_particles += molecule->n_atoms *
3329 tng_data->molecule_cnt_list[i];
3331 if(molecule->n_chains > 0)
3333 molecule->chains = malloc(molecule->n_chains *
3334 sizeof(struct tng_chain));
3335 if(!molecule->chains)
3337 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3338 molecule->n_chains * sizeof(struct tng_chain),
3339 __FILE__, __LINE__);
3340 return(TNG_CRITICAL);
3343 chain = molecule->chains;
3350 if(molecule->n_residues > 0)
3352 molecule->residues = malloc(molecule->n_residues *
3353 sizeof(struct tng_residue));
3354 if(!molecule->residues)
3356 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3357 molecule->n_residues * sizeof(struct tng_residue),
3358 __FILE__, __LINE__);
3359 if(molecule->chains)
3361 free(molecule->chains);
3362 molecule->chains = 0;
3364 return(TNG_CRITICAL);
3367 residue = molecule->residues;
3374 molecule->atoms = malloc(molecule->n_atoms *
3375 sizeof(struct tng_atom));
3376 if(!molecule->atoms)
3378 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3379 molecule->n_atoms * sizeof(struct tng_atom),
3380 __FILE__, __LINE__);
3381 if(molecule->chains)
3383 free(molecule->chains);
3384 molecule->chains = 0;
3386 if(molecule->residues)
3388 free(molecule->residues);
3389 molecule->residues = 0;
3391 return(TNG_CRITICAL);
3394 atom = molecule->atoms;
3396 if(molecule->n_chains > 0)
3398 /* Read the chains of the molecule */
3399 for(j=0; j<molecule->n_chains; j++)
3401 chain->molecule = molecule;
3403 tng_chain_data_read(tng_data, block, chain, &offset);
3405 chain->residues = molecule->residues;
3406 residue = chain->residues;
3408 /* Read the residues of the chain */
3409 for(k=0; k<chain->n_residues; k++)
3411 residue->chain = chain;
3413 tng_residue_data_read(tng_data, block, residue, &offset);
3415 residue->atoms_offset = atom - molecule->atoms;
3416 /* Read the atoms of the residue */
3417 for(l=0; l<residue->n_atoms; l++)
3419 atom->residue = residue;
3421 tng_atom_data_read(tng_data, block, atom, &offset);
3432 if(molecule->n_residues > 0)
3434 for(k=0; k<molecule->n_residues; k++)
3438 tng_residue_data_read(tng_data, block, residue, &offset);
3440 residue->atoms_offset = atom - molecule->atoms;
3441 /* Read the atoms of the residue */
3442 for(l=0; l<residue->n_atoms; l++)
3444 atom->residue = residue;
3446 tng_atom_data_read(tng_data, block, atom, &offset);
3455 for(l=0; l<molecule->n_atoms; l++)
3459 tng_atom_data_read(tng_data, block, atom, &offset);
3466 memcpy(&molecule->n_bonds, block->block_contents+offset,
3467 sizeof(molecule->n_bonds));
3468 if(tng_data->input_endianness_swap_func_64)
3470 if(tng_data->input_endianness_swap_func_64(tng_data,
3474 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3475 __FILE__, __LINE__);
3478 offset += sizeof(molecule->n_bonds);
3480 if(molecule->n_bonds > 0)
3482 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
3483 sizeof(struct tng_bond));
3484 if(!molecule->bonds)
3486 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3487 molecule->n_bonds * sizeof(struct tng_bond),
3488 __FILE__, __LINE__);
3489 if(molecule->chains)
3491 free(molecule->chains);
3492 molecule->chains = 0;
3494 if(molecule->residues)
3496 free(molecule->residues);
3497 molecule->residues = 0;
3501 free(molecule->atoms);
3502 molecule->atoms = 0;
3504 return(TNG_CRITICAL);
3507 bond = molecule->bonds;
3509 for(j=0; j<molecule->n_bonds; j++)
3511 memcpy(&bond->from_atom_id, block->block_contents+offset,
3512 sizeof(bond->from_atom_id));
3513 if(tng_data->input_endianness_swap_func_64)
3515 if(tng_data->input_endianness_swap_func_64(tng_data,
3516 &bond->from_atom_id)
3519 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3520 __FILE__, __LINE__);
3523 offset += sizeof(bond->from_atom_id);
3525 memcpy(&bond->to_atom_id, block->block_contents+offset,
3526 sizeof(bond->to_atom_id));
3527 if(tng_data->input_endianness_swap_func_64)
3529 if(tng_data->input_endianness_swap_func_64(tng_data,
3533 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3534 __FILE__, __LINE__);
3537 offset += sizeof(bond->to_atom_id);
3544 molecule->bonds = 0;
3548 return(TNG_SUCCESS);
3551 /** Write a molecules block.
3552 * @param tng_data is a trajectory data container.
3553 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3554 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3555 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3556 * error has occured.
3558 static tng_function_status tng_molecules_block_write
3559 (tng_trajectory_t tng_data,
3560 const char hash_mode)
3562 int len = 0, name_len, offset = 0;
3564 tng_molecule_t molecule;
3566 tng_residue_t residue;
3569 tng_gen_block_t block;
3571 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3573 return(TNG_CRITICAL);
3576 tng_block_init(&block);
3578 name_len = (int)strlen("MOLECULES");
3580 block->name = malloc(name_len + 1);
3583 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3584 name_len+1, __FILE__, __LINE__);
3585 tng_block_destroy(&block);
3586 return(TNG_CRITICAL);
3589 strcpy(block->name, "MOLECULES");
3590 block->id = TNG_MOLECULES;
3592 if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
3595 fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3596 __FILE__, __LINE__);
3597 tng_block_destroy(&block);
3598 return(TNG_CRITICAL);
3601 block->block_contents = malloc(block->block_contents_size);
3602 if(!block->block_contents)
3604 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3605 block->block_contents_size, __FILE__, __LINE__);
3606 tng_block_destroy(&block);
3607 return(TNG_CRITICAL);
3610 memcpy(block->block_contents+offset, &tng_data->n_molecules,
3611 sizeof(tng_data->n_molecules));
3612 if(tng_data->output_endianness_swap_func_64)
3614 if(tng_data->output_endianness_swap_func_64(tng_data,
3615 (int64_t *)block->header_contents+offset)
3618 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3619 __FILE__, __LINE__);
3622 offset += sizeof(tng_data->n_molecules);
3624 for(i = 0; i < tng_data->n_molecules; i++)
3626 molecule = &tng_data->molecules[i];
3627 memcpy(block->block_contents+offset, &molecule->id,
3628 sizeof(molecule->id));
3629 if(tng_data->output_endianness_swap_func_64)
3631 if(tng_data->output_endianness_swap_func_64(tng_data,
3632 (int64_t *)block->header_contents+offset)
3635 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3636 __FILE__, __LINE__);
3639 offset += sizeof(molecule->id);
3641 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
3642 len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3643 strncpy(block->block_contents + offset, molecule->name, len);
3646 memcpy(block->block_contents+offset, &molecule->quaternary_str,
3647 sizeof(molecule->quaternary_str));
3648 if(tng_data->output_endianness_swap_func_64)
3650 if(tng_data->output_endianness_swap_func_64(tng_data,
3651 (int64_t *)block->header_contents+offset)
3654 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3655 __FILE__, __LINE__);
3658 offset += sizeof(molecule->quaternary_str);
3660 if(!tng_data->var_num_atoms_flag)
3662 memcpy(block->block_contents+offset,
3663 &tng_data->molecule_cnt_list[i], sizeof(int64_t));
3664 if(tng_data->output_endianness_swap_func_64)
3666 if(tng_data->output_endianness_swap_func_64(tng_data,
3667 (int64_t *)block->header_contents+offset)
3670 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3671 __FILE__, __LINE__);
3674 offset += sizeof(int64_t);
3677 memcpy(block->block_contents+offset, &molecule->n_chains,
3678 sizeof(molecule->n_chains));
3679 if(tng_data->output_endianness_swap_func_64)
3681 if(tng_data->output_endianness_swap_func_64(tng_data,
3682 (int64_t *)block->header_contents+offset)
3685 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3686 __FILE__, __LINE__);
3689 offset += sizeof(molecule->n_chains);
3691 memcpy(block->block_contents+offset, &molecule->n_residues,
3692 sizeof(molecule->n_residues));
3693 if(tng_data->output_endianness_swap_func_64)
3695 if(tng_data->output_endianness_swap_func_64(tng_data,
3696 (int64_t *)block->header_contents+offset)
3699 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3700 __FILE__, __LINE__);
3703 offset += sizeof(molecule->n_residues);
3705 memcpy(block->block_contents+offset, &molecule->n_atoms,
3706 sizeof(molecule->n_atoms));
3707 if(tng_data->output_endianness_swap_func_64)
3709 if(tng_data->output_endianness_swap_func_64(tng_data,
3710 (int64_t *)block->header_contents+offset)
3713 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3714 __FILE__, __LINE__);
3717 offset += sizeof(molecule->n_atoms);
3719 if(molecule->n_chains > 0)
3721 chain = molecule->chains;
3722 for(j = 0; j < molecule->n_chains; j++)
3724 tng_chain_data_write(tng_data, block, chain, &offset);
3726 residue = chain->residues;
3727 for(k = 0; k < chain->n_residues; k++)
3729 tng_residue_data_write(tng_data, block, residue, &offset);
3731 atom = molecule->atoms + residue->atoms_offset;
3732 for(l = 0; l < residue->n_atoms; l++)
3734 tng_atom_data_write(tng_data, block, atom, &offset);
3745 if(molecule->n_residues > 0)
3747 residue = molecule->residues;
3748 for(k = 0; k < molecule->n_residues; k++)
3750 tng_residue_data_write(tng_data, block, residue, &offset);
3752 atom = molecule->atoms + residue->atoms_offset;
3753 for(l = 0; l < residue->n_atoms; l++)
3755 tng_atom_data_write(tng_data, block, atom, &offset);
3764 atom = molecule->atoms;
3765 for(l = 0; l < molecule->n_atoms; l++)
3767 tng_atom_data_write(tng_data, block, atom, &offset);
3774 memcpy(block->block_contents+offset, &molecule->n_bonds,
3775 sizeof(molecule->n_bonds));
3776 if(tng_data->output_endianness_swap_func_64)
3778 if(tng_data->output_endianness_swap_func_64(tng_data,
3779 (int64_t *)block->header_contents+offset)
3782 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3783 __FILE__, __LINE__);
3786 offset += sizeof(molecule->n_bonds);
3788 bond = molecule->bonds;
3789 for(j = 0; j < molecule->n_bonds; j++)
3791 memcpy(block->block_contents+offset, &bond->from_atom_id,
3792 sizeof(bond->from_atom_id));
3793 if(tng_data->output_endianness_swap_func_64)
3795 if(tng_data->output_endianness_swap_func_64(tng_data,
3796 (int64_t *)block->header_contents+offset)
3799 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3800 __FILE__, __LINE__);
3803 offset += sizeof(bond->from_atom_id);
3805 memcpy(block->block_contents+offset, &bond->to_atom_id,
3806 sizeof(bond->to_atom_id));
3807 if(tng_data->output_endianness_swap_func_64)
3809 if(tng_data->output_endianness_swap_func_64(tng_data,
3810 (int64_t *)block->header_contents+offset)
3813 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3814 __FILE__, __LINE__);
3817 offset += sizeof(bond->to_atom_id);
3823 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3825 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3826 tng_data->output_file_path, __FILE__, __LINE__);
3827 tng_block_destroy(&block);
3828 return(TNG_CRITICAL);
3831 if(fwrite(block->block_contents, block->block_contents_size, 1,
3832 tng_data->output_file) != 1)
3834 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
3835 __FILE__, __LINE__);
3836 tng_block_destroy(&block);
3837 return(TNG_CRITICAL);
3840 tng_block_destroy(&block);
3842 return(TNG_SUCCESS);
3845 static tng_function_status tng_frame_set_block_len_calculate
3846 (const tng_trajectory_t tng_data,
3849 *len = sizeof(int64_t) * 8;
3850 *len += sizeof(double) * 2;
3852 if(tng_data->var_num_atoms_flag)
3854 *len += sizeof(int64_t) * tng_data->n_molecules;
3856 return(TNG_SUCCESS);
3859 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
3860 * @param tng_data is a trajectory data container.
3861 * @param block is a general block container.
3862 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3863 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3864 * compared to the md5 hash of the read contents to ensure valid data.
3865 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3866 * error has occured.
3868 static tng_function_status tng_frame_set_block_read
3869 (tng_trajectory_t tng_data,
3870 tng_gen_block_t block,
3871 const char hash_mode)
3875 int64_t i, prev_n_particles;
3877 tng_trajectory_frame_set_t frame_set =
3878 &tng_data->current_trajectory_frame_set;
3880 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3882 return(TNG_CRITICAL);
3885 if(block->block_contents)
3887 free(block->block_contents);
3890 block->block_contents = malloc(block->block_contents_size);
3891 if(!block->block_contents)
3893 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3894 block->block_contents_size, __FILE__, __LINE__);
3895 return(TNG_CRITICAL);
3898 /* Read the whole block into block_contents to be able to write it to
3899 * disk even if it cannot be interpreted. */
3900 if(fread(block->block_contents, block->block_contents_size, 1,
3901 tng_data->input_file) == 0)
3903 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3904 return(TNG_CRITICAL);
3907 /* FIXME: Does not check if the size of the contents matches the expected
3908 * size or if the contents can be read. */
3910 file_pos = (int64_t)ftell(tng_data->input_file) -
3911 (long)(block->block_contents_size + block->header_contents_size);
3913 if(hash_mode == TNG_USE_HASH)
3915 tng_md5_hash_match_verify(block, &same_hash);
3916 if(same_hash != TNG_TRUE)
3918 fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %ld Hashes do not match. "
3920 file_pos, __FILE__, __LINE__);
3921 /* return(TNG_FAILURE); */
3925 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3927 tng_frame_set_particle_mapping_free(tng_data);
3929 if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
3931 tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
3933 /* FIXME: Should check the frame number instead of the file_pos, in case
3934 * frame sets are not in order */
3935 if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
3937 tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
3940 memcpy(&frame_set->first_frame, block->block_contents,
3941 sizeof(frame_set->first_frame));
3942 if(tng_data->input_endianness_swap_func_64)
3944 if(tng_data->input_endianness_swap_func_64(tng_data,
3945 &frame_set->first_frame)
3948 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3949 __FILE__, __LINE__);
3952 offset += sizeof(frame_set->first_frame);
3954 memcpy(&frame_set->n_frames, block->block_contents + offset,
3955 sizeof(frame_set->n_frames));
3956 if(tng_data->input_endianness_swap_func_64)
3958 if(tng_data->input_endianness_swap_func_64(tng_data,
3959 &frame_set->n_frames)
3962 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3963 __FILE__, __LINE__);
3966 offset += sizeof(frame_set->n_frames);
3968 if(tng_data->var_num_atoms_flag)
3970 prev_n_particles = frame_set->n_particles;
3971 frame_set->n_particles = 0;
3972 /* If the list of molecule counts has already been created assume that
3973 * it is of correct size. */
3974 if(!frame_set->molecule_cnt_list)
3976 frame_set->molecule_cnt_list =
3977 malloc(sizeof(int64_t) * tng_data->n_molecules);
3979 if(!frame_set->molecule_cnt_list)
3981 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3982 sizeof(int64_t) * tng_data->n_molecules,
3983 __FILE__, __LINE__);
3984 return(TNG_CRITICAL);
3987 for(i = 0; i < tng_data->n_molecules; i++)
3989 memcpy(&frame_set->molecule_cnt_list[i],
3990 block->block_contents + offset,
3992 if(tng_data->input_endianness_swap_func_64)
3994 if(tng_data->input_endianness_swap_func_64(tng_data,
3995 &frame_set->molecule_cnt_list[i])
3998 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3999 __FILE__, __LINE__);
4002 offset += sizeof(int64_t);
4003 frame_set->n_particles += tng_data->molecules[i].n_atoms *
4004 frame_set->molecule_cnt_list[i];
4006 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
4008 /* FIXME: Particle dependent data memory management */
4012 memcpy(&frame_set->next_frame_set_file_pos,
4013 block->block_contents + offset,
4014 sizeof(frame_set->next_frame_set_file_pos));
4015 if(tng_data->input_endianness_swap_func_64)
4017 if(tng_data->input_endianness_swap_func_64(tng_data,
4018 &frame_set->next_frame_set_file_pos)
4021 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4022 __FILE__, __LINE__);
4025 offset += sizeof(frame_set->next_frame_set_file_pos);
4027 memcpy(&frame_set->prev_frame_set_file_pos,
4028 block->block_contents + offset,
4029 sizeof(frame_set->prev_frame_set_file_pos));
4030 if(tng_data->input_endianness_swap_func_64)
4032 if(tng_data->input_endianness_swap_func_64(tng_data,
4033 &frame_set->prev_frame_set_file_pos)
4036 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4037 __FILE__, __LINE__);
4040 offset += sizeof(frame_set->prev_frame_set_file_pos);
4042 memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
4043 block->block_contents + offset,
4044 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4045 if(tng_data->input_endianness_swap_func_64)
4047 if(tng_data->input_endianness_swap_func_64(tng_data,
4048 &frame_set->medium_stride_next_frame_set_file_pos)
4051 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4052 __FILE__, __LINE__);
4055 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4057 memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
4058 block->block_contents + offset,
4059 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4060 if(tng_data->input_endianness_swap_func_64)
4062 if(tng_data->input_endianness_swap_func_64(tng_data,
4063 &frame_set->medium_stride_prev_frame_set_file_pos)
4066 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4067 __FILE__, __LINE__);
4070 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4072 memcpy(&frame_set->long_stride_next_frame_set_file_pos,
4073 block->block_contents + offset,
4074 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4075 if(tng_data->input_endianness_swap_func_64)
4077 if(tng_data->input_endianness_swap_func_64(tng_data,
4078 &frame_set->long_stride_next_frame_set_file_pos)
4081 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4082 __FILE__, __LINE__);
4085 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4087 memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
4088 block->block_contents + offset,
4089 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4090 if(tng_data->input_endianness_swap_func_64)
4092 if(tng_data->input_endianness_swap_func_64(tng_data,
4093 &frame_set->long_stride_prev_frame_set_file_pos)
4096 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4097 __FILE__, __LINE__);
4100 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4102 if(block->block_version >= 3)
4104 memcpy(&frame_set->first_frame_time,
4105 block->block_contents + offset,
4106 sizeof(frame_set->first_frame_time));
4107 if(tng_data->input_endianness_swap_func_64)
4109 if(tng_data->input_endianness_swap_func_64(tng_data,
4110 (int64_t *)&frame_set->first_frame_time)
4113 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4114 __FILE__, __LINE__);
4117 offset += sizeof(frame_set->first_frame_time);
4119 memcpy(&tng_data->time_per_frame,
4120 block->block_contents + offset,
4121 sizeof(tng_data->time_per_frame));
4122 if(tng_data->input_endianness_swap_func_64)
4124 if(tng_data->input_endianness_swap_func_64(tng_data,
4125 (int64_t *)&tng_data->time_per_frame)
4128 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4129 __FILE__, __LINE__);
4135 frame_set->first_frame_time = -1;
4136 tng_data->time_per_frame = -1;
4139 /* If the output file and the input files are the same the number of
4140 * frames in the file are the same number as has just been read.
4141 * This is updated here to later on see if there have been new frames
4142 * added and thereby the frame set needs to be rewritten. */
4143 if(tng_data->output_file == tng_data->input_file)
4145 frame_set->n_written_frames = frame_set->n_frames;
4148 return(TNG_SUCCESS);
4151 /** Write tng_data->current_trajectory_frame_set to file
4152 * @param tng_data is a trajectory data container.
4153 * @param block is a general block container.
4154 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4155 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4156 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4157 * error has occured.
4159 static tng_function_status tng_frame_set_block_write
4160 (tng_trajectory_t tng_data,
4161 tng_gen_block_t block,
4162 const char hash_mode)
4167 unsigned int name_len;
4168 tng_trajectory_frame_set_t frame_set =
4169 &tng_data->current_trajectory_frame_set;
4171 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4173 return(TNG_CRITICAL);
4176 name_len = (int)strlen("TRAJECTORY FRAME SET");
4178 if(!block->name || strlen(block->name) < name_len)
4180 temp_name = realloc(block->name, name_len + 1);
4183 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4184 name_len+1, __FILE__, __LINE__);
4187 return(TNG_CRITICAL);
4189 block->name = temp_name;
4191 strcpy(block->name, "TRAJECTORY FRAME SET");
4192 block->id = TNG_TRAJECTORY_FRAME_SET;
4194 if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
4197 fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
4198 __FILE__, __LINE__);
4199 return(TNG_CRITICAL);
4202 if(block->block_contents)
4204 free(block->block_contents);
4206 block->block_contents = malloc(block->block_contents_size);
4207 if(!block->block_contents)
4209 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4210 block->block_contents_size, __FILE__, __LINE__);
4211 return(TNG_CRITICAL);
4214 memcpy(block->block_contents, &frame_set->first_frame,
4215 sizeof(frame_set->first_frame));
4216 if(tng_data->output_endianness_swap_func_64)
4218 if(tng_data->output_endianness_swap_func_64(tng_data,
4219 (int64_t *)block->header_contents+offset)
4222 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4223 __FILE__, __LINE__);
4226 offset += sizeof(frame_set->first_frame);
4228 memcpy(block->block_contents+offset, &frame_set->n_frames,
4229 sizeof(frame_set->n_frames));
4230 if(tng_data->output_endianness_swap_func_64)
4232 if(tng_data->output_endianness_swap_func_64(tng_data,
4233 (int64_t *)block->header_contents+offset)
4236 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4237 __FILE__, __LINE__);
4240 offset += sizeof(frame_set->n_frames);
4242 if(tng_data->var_num_atoms_flag)
4244 for(i = 0; i < tng_data->n_molecules; i++)
4246 memcpy(block->block_contents+offset,
4247 &frame_set->molecule_cnt_list[i],
4249 if(tng_data->output_endianness_swap_func_64)
4251 if(tng_data->output_endianness_swap_func_64(tng_data,
4252 (int64_t *)block->header_contents+offset)
4255 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4256 __FILE__, __LINE__);
4259 offset += sizeof(int64_t);
4264 memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
4265 sizeof(frame_set->next_frame_set_file_pos));
4266 if(tng_data->output_endianness_swap_func_64)
4268 if(tng_data->output_endianness_swap_func_64(tng_data,
4269 (int64_t *)block->header_contents+offset)
4272 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4273 __FILE__, __LINE__);
4276 offset += sizeof(frame_set->next_frame_set_file_pos);
4278 memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
4279 sizeof(frame_set->prev_frame_set_file_pos));
4280 if(tng_data->output_endianness_swap_func_64)
4282 if(tng_data->output_endianness_swap_func_64(tng_data,
4283 (int64_t *)block->header_contents+offset)
4286 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4287 __FILE__, __LINE__);
4290 offset += sizeof(frame_set->prev_frame_set_file_pos);
4292 memcpy(block->block_contents+offset,
4293 &frame_set->medium_stride_next_frame_set_file_pos,
4294 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4295 if(tng_data->output_endianness_swap_func_64)
4297 if(tng_data->output_endianness_swap_func_64(tng_data,
4298 (int64_t *)block->header_contents+offset)
4301 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4302 __FILE__, __LINE__);
4305 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4307 memcpy(block->block_contents+offset,
4308 &frame_set->medium_stride_prev_frame_set_file_pos,
4309 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4310 if(tng_data->output_endianness_swap_func_64)
4312 if(tng_data->output_endianness_swap_func_64(tng_data,
4313 (int64_t *)block->header_contents+offset)
4316 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4317 __FILE__, __LINE__);
4320 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4322 memcpy(block->block_contents+offset,
4323 &frame_set->long_stride_next_frame_set_file_pos,
4324 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4325 if(tng_data->output_endianness_swap_func_64)
4327 if(tng_data->output_endianness_swap_func_64(tng_data,
4328 (int64_t *)block->header_contents+offset)
4331 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4332 __FILE__, __LINE__);
4335 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4337 memcpy(block->block_contents+offset,
4338 &frame_set->long_stride_prev_frame_set_file_pos,
4339 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4340 if(tng_data->output_endianness_swap_func_64)
4342 if(tng_data->output_endianness_swap_func_64(tng_data,
4343 (int64_t *)block->header_contents+offset)
4346 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4347 __FILE__, __LINE__);
4350 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4352 memcpy(block->block_contents+offset,
4353 &frame_set->first_frame_time,
4354 sizeof(frame_set->first_frame_time));
4355 if(tng_data->output_endianness_swap_func_64)
4357 if(tng_data->output_endianness_swap_func_64(tng_data,
4358 (int64_t *)block->header_contents+offset)
4361 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4362 __FILE__, __LINE__);
4365 offset += sizeof(frame_set->first_frame_time);
4367 memcpy(block->block_contents+offset,
4368 &tng_data->time_per_frame,
4369 sizeof(tng_data->time_per_frame));
4370 if(tng_data->output_endianness_swap_func_64)
4372 if(tng_data->output_endianness_swap_func_64(tng_data,
4373 (int64_t *)block->header_contents+offset)
4376 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4377 __FILE__, __LINE__);
4381 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4383 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4384 tng_data->output_file_path, __FILE__, __LINE__);
4385 return(TNG_CRITICAL);
4388 if(fwrite(block->block_contents, block->block_contents_size, 1,
4389 tng_data->output_file) != 1)
4391 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4392 return(TNG_CRITICAL);
4395 return(TNG_SUCCESS);
4398 static tng_function_status tng_trajectory_mapping_block_len_calculate
4399 (const tng_trajectory_t tng_data,
4400 const int64_t n_particles,
4404 *len = sizeof(int64_t) * (2 + n_particles);
4406 return(TNG_SUCCESS);
4409 /** Read an atom mappings block (translating between real atom indexes and how
4410 * the atom info is written in this frame set).
4411 * @param tng_data is a trajectory data container.
4412 * @param block is a general block container.
4413 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4414 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
4415 * compared to the md5 hash of the read contents to ensure valid data.
4416 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4417 * error has occured.
4419 static tng_function_status tng_trajectory_mapping_block_read
4420 (tng_trajectory_t tng_data,
4421 tng_gen_block_t block,
4422 const char hash_mode)
4427 tng_trajectory_frame_set_t frame_set =
4428 &tng_data->current_trajectory_frame_set;
4430 tng_particle_mapping_t mapping, mappings;
4432 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
4434 return(TNG_CRITICAL);
4437 if(block->block_contents)
4439 free(block->block_contents);
4442 block->block_contents = malloc(block->block_contents_size);
4443 if(!block->block_contents)
4445 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4446 block->block_contents_size, __FILE__, __LINE__);
4447 return(TNG_CRITICAL);
4450 /* Read the whole block into block_contents to be able to write it to disk
4451 * even if it cannot be interpreted. */
4452 if(fread(block->block_contents, block->block_contents_size, 1,
4453 tng_data->input_file) == 0)
4455 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
4456 return(TNG_CRITICAL);
4459 /* FIXME: Does not check if the size of the contents matches the expected
4460 * size or if the contents can be read. */
4462 if(hash_mode == TNG_USE_HASH)
4464 tng_md5_hash_match_verify(block, &same_hash);
4465 if(same_hash != TNG_TRUE)
4467 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4469 __FILE__, __LINE__);
4470 /* return(TNG_FAILURE); */
4474 frame_set->n_mapping_blocks++;
4475 mappings = realloc(frame_set->mappings,
4476 sizeof(struct tng_particle_mapping) *
4477 frame_set->n_mapping_blocks);
4480 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4481 block->block_contents_size, __FILE__, __LINE__);
4482 free(frame_set->mappings);
4483 frame_set->mappings = 0;
4484 return(TNG_CRITICAL);
4486 frame_set->mappings = mappings;
4487 mapping = &mappings[frame_set->n_mapping_blocks - 1];
4490 memcpy(&mapping->num_first_particle, block->block_contents+offset,
4491 sizeof(mapping->num_first_particle));
4492 if(tng_data->input_endianness_swap_func_64)
4494 if(tng_data->input_endianness_swap_func_64(tng_data,
4495 &mapping->num_first_particle)
4498 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4499 __FILE__, __LINE__);
4502 offset += sizeof(mapping->num_first_particle);
4504 memcpy(&mapping->n_particles, block->block_contents+offset,
4505 sizeof(mapping->n_particles));
4506 if(tng_data->input_endianness_swap_func_64)
4508 if(tng_data->input_endianness_swap_func_64(tng_data,
4509 &mapping->n_particles)
4512 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4513 __FILE__, __LINE__);
4516 offset += sizeof(mapping->n_particles);
4518 mapping->real_particle_numbers = malloc(mapping->n_particles *
4520 if(!mapping->real_particle_numbers)
4522 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4523 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
4524 return(TNG_CRITICAL);
4527 /* If the byte order needs to be swapped the data must be read one value at
4528 * a time and swapped */
4529 if(tng_data->input_endianness_swap_func_64)
4531 for(i = 0; i < mapping->n_particles; i++)
4533 memcpy(&mapping->real_particle_numbers[i],
4534 block->block_contents + offset,
4536 if(tng_data->input_endianness_swap_func_64(tng_data,
4537 &mapping->real_particle_numbers[i])
4540 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4541 __FILE__, __LINE__);
4543 offset += sizeof(int64_t);
4546 /* Otherwise the data can be read all at once */
4549 memcpy(mapping->real_particle_numbers, block->block_contents + offset,
4550 mapping->n_particles * sizeof(int64_t));
4554 return(TNG_SUCCESS);
4557 /** Write the atom mappings of the current trajectory frame set
4558 * @param tng_data is a trajectory data container.
4559 * @param block is a general block container.
4560 * @param mapping_block_nr is the index of the mapping block to write.
4561 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4562 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4563 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4564 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4566 static tng_function_status tng_trajectory_mapping_block_write
4567 (tng_trajectory_t tng_data,
4568 tng_gen_block_t block,
4569 int mapping_block_nr,
4570 const char hash_mode)
4574 unsigned int name_len;
4575 tng_particle_mapping_t mapping =
4576 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
4578 if(mapping_block_nr >=
4579 tng_data->current_trajectory_frame_set.n_mapping_blocks)
4581 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
4582 __FILE__, __LINE__);
4583 return(TNG_FAILURE);
4586 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4588 return(TNG_CRITICAL);
4591 name_len = (int)strlen("PARTICLE MAPPING");
4593 if(!block->name || strlen(block->name) < name_len)
4595 temp_name = realloc(block->name, name_len + 1);
4598 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4599 name_len+1, __FILE__, __LINE__);
4602 return(TNG_CRITICAL);
4604 block->name = temp_name;
4606 strcpy(block->name, "PARTICLE MAPPING");
4607 block->id = TNG_PARTICLE_MAPPING;
4609 if(tng_trajectory_mapping_block_len_calculate(tng_data,
4610 mapping->n_particles,
4611 &block->block_contents_size) !=
4614 fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4615 __FILE__, __LINE__);
4616 return(TNG_CRITICAL);
4619 if(block->block_contents)
4621 free(block->block_contents);
4623 block->block_contents = malloc(block->block_contents_size);
4624 if(!block->block_contents)
4626 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4627 block->block_contents_size, __FILE__, __LINE__);
4628 return(TNG_CRITICAL);
4631 memcpy(block->block_contents, &mapping->num_first_particle,
4632 sizeof(mapping->num_first_particle));
4633 if(tng_data->output_endianness_swap_func_64)
4635 if(tng_data->output_endianness_swap_func_64(tng_data,
4636 (int64_t *)block->header_contents+offset)
4639 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4640 __FILE__, __LINE__);
4643 offset += sizeof(mapping->num_first_particle);
4645 memcpy(block->block_contents+offset, &mapping->n_particles,
4646 sizeof(mapping->n_particles));
4647 if(tng_data->output_endianness_swap_func_64)
4649 if(tng_data->output_endianness_swap_func_64(tng_data,
4650 (int64_t *)block->header_contents+offset)
4653 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4654 __FILE__, __LINE__);
4657 offset += sizeof(mapping->n_particles);
4659 if(tng_data->output_endianness_swap_func_64)
4661 for(i = 0; i < mapping->n_particles; i++)
4663 memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
4665 if(tng_data->output_endianness_swap_func_64(tng_data,
4666 (int64_t *)block->header_contents+offset)
4669 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4670 __FILE__, __LINE__);
4672 offset += sizeof(int64_t);
4677 memcpy(block->block_contents+offset, mapping->real_particle_numbers,
4678 mapping->n_particles * sizeof(int64_t));
4682 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4684 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4685 tng_data->output_file_path, __FILE__, __LINE__);
4686 return(TNG_CRITICAL);
4689 if(fwrite(block->block_contents, block->block_contents_size, 1,
4690 tng_data->output_file) != 1)
4692 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4693 return(TNG_CRITICAL);
4696 return(TNG_SUCCESS);
4699 /** Prepare a block for storing particle data
4700 * @param tng_data is a trajectory data container.
4701 * @param block_type_flag specifies if this is a trajectory block or a
4702 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4703 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4704 * error has occured.
4706 static tng_function_status tng_particle_data_block_create
4707 (tng_trajectory_t tng_data,
4708 const char block_type_flag)
4710 tng_trajectory_frame_set_t frame_set =
4711 &tng_data->current_trajectory_frame_set;
4713 tng_particle_data_t data;
4715 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4717 frame_set->n_particle_data_blocks++;
4718 data = realloc(frame_set->tr_particle_data,
4719 sizeof(struct tng_particle_data) *
4720 frame_set->n_particle_data_blocks);
4723 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4724 sizeof(struct tng_particle_data) *
4725 frame_set->n_particle_data_blocks,
4726 __FILE__, __LINE__);
4727 free(frame_set->tr_particle_data);
4728 frame_set->tr_particle_data = 0;
4729 return(TNG_CRITICAL);
4731 frame_set->tr_particle_data = data;
4735 tng_data->n_particle_data_blocks++;
4736 data = realloc(tng_data->non_tr_particle_data,
4737 sizeof(struct tng_particle_data) *
4738 tng_data->n_particle_data_blocks);
4741 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4742 sizeof(struct tng_particle_data) *
4743 tng_data->n_particle_data_blocks,
4744 __FILE__, __LINE__);
4745 free(tng_data->non_tr_particle_data);
4746 tng_data->non_tr_particle_data = 0;
4747 return(TNG_CRITICAL);
4749 tng_data->non_tr_particle_data = data;
4752 return(TNG_SUCCESS);
4755 static tng_function_status tng_compress(tng_trajectory_t tng_data,
4756 tng_gen_block_t block,
4757 const int64_t n_frames,
4758 const int64_t n_particles,
4766 int64_t algo_find_n_frames;
4767 unsigned long offset;
4771 if(block->id != TNG_TRAJ_POSITIONS &&
4772 block->id != TNG_TRAJ_VELOCITIES)
4774 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
4775 "TNG method. %s: %d\n", __FILE__, __LINE__);
4776 return(TNG_FAILURE);
4778 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4780 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
4781 return(TNG_FAILURE);
4784 if(n_frames <= 0 || n_particles <= 0)
4786 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
4787 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
4788 return(TNG_FAILURE);
4791 f_precision = 1/(float)tng_data->compression_precision;
4792 d_precision = 1/tng_data->compression_precision;
4794 if(block->id == TNG_TRAJ_POSITIONS)
4796 /* If there is only one frame in this frame set and there might be more
4797 * do not store the algorithm as the compression algorithm, but find
4798 * the best one without storing it */
4799 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4801 nalgo = tng_compress_nalgo();
4802 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4803 if(type == TNG_FLOAT_DATA)
4805 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
4814 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
4821 else if(!tng_data->compress_algo_pos)
4825 algo_find_n_frames = 5;
4829 algo_find_n_frames = n_frames;
4832 nalgo = tng_compress_nalgo();
4833 tng_data->compress_algo_pos=malloc(nalgo *
4834 sizeof *tng_data->compress_algo_pos);
4835 if(type == TNG_FLOAT_DATA)
4837 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
4838 (int)algo_find_n_frames,
4844 if(algo_find_n_frames < n_frames)
4846 dest = tng_compress_pos_float(start_pos, (int)n_particles,
4849 0, tng_data->compress_algo_pos,
4855 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
4856 (int)algo_find_n_frames,
4862 if(algo_find_n_frames < n_frames)
4864 dest = tng_compress_pos(start_pos, (int)n_particles,
4867 tng_data->compress_algo_pos,
4874 if(type == TNG_FLOAT_DATA)
4876 dest = tng_compress_pos_float(start_pos, (int)n_particles,
4879 tng_data->compress_algo_pos, &new_len);
4883 dest = tng_compress_pos(start_pos, (int)n_particles,
4886 tng_data->compress_algo_pos,
4891 else if(block->id == TNG_TRAJ_VELOCITIES)
4893 /* If there is only one frame in this frame set and there might be more
4894 * do not store the algorithm as the compression algorithm, but find
4895 * the best one without storing it */
4896 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4898 nalgo = tng_compress_nalgo();
4899 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4900 if(type == TNG_FLOAT_DATA)
4902 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4911 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4918 else if(!tng_data->compress_algo_vel)
4922 algo_find_n_frames = 5;
4926 algo_find_n_frames = n_frames;
4929 nalgo = tng_compress_nalgo();
4930 tng_data->compress_algo_vel=malloc(nalgo *
4931 sizeof *tng_data->compress_algo_vel);
4933 if(type == TNG_FLOAT_DATA)
4935 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4936 (int)algo_find_n_frames,
4941 if(algo_find_n_frames < n_frames)
4943 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4946 0, tng_data->compress_algo_vel,
4952 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4953 (int)algo_find_n_frames,
4958 if(algo_find_n_frames < n_frames)
4960 dest = tng_compress_vel(start_pos, (int)n_particles,
4963 0, tng_data->compress_algo_vel,
4970 if(type == TNG_FLOAT_DATA)
4972 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4981 dest = tng_compress_vel(start_pos, (int)n_particles,
4992 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4993 return(TNG_FAILURE);
4996 offset = (unsigned long)((char *)start_pos - block->block_contents);
5003 block->block_contents_size = new_len + offset;
5005 temp = realloc(block->block_contents, block->block_contents_size);
5008 free(block->block_contents);
5009 block->block_contents = 0;
5010 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5011 block->block_contents_size, __FILE__, __LINE__);
5012 return(TNG_CRITICAL);
5014 block->block_contents = temp;
5017 memcpy(temp + offset, dest, new_len);
5022 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
5023 return(TNG_FAILURE);
5026 return(TNG_SUCCESS);
5029 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
5030 tng_gen_block_t block,
5033 const unsigned long uncompressed_len)
5038 unsigned long offset;
5042 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
5044 if(block->id != TNG_TRAJ_POSITIONS &&
5045 block->id != TNG_TRAJ_VELOCITIES)
5047 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
5049 return(TNG_FAILURE);
5051 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
5053 fprintf(stderr, "TNG library: Data type not supported.\n");
5054 return(TNG_FAILURE);
5057 if(type == TNG_FLOAT_DATA)
5059 f_dest = malloc(uncompressed_len);
5062 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5063 uncompressed_len, __FILE__, __LINE__);
5064 return(TNG_CRITICAL);
5066 result = tng_compress_uncompress_float(start_pos, f_dest);
5070 d_dest = malloc(uncompressed_len);
5073 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5074 uncompressed_len, __FILE__, __LINE__);
5075 return(TNG_CRITICAL);
5077 result = tng_compress_uncompress(start_pos, d_dest);
5082 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
5083 return(TNG_FAILURE);
5086 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
5088 block->block_contents_size = (int64_t)(uncompressed_len + offset);
5090 temp = realloc(block->block_contents, uncompressed_len + offset);
5093 free(block->block_contents);
5094 block->block_contents = 0;
5103 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5104 block->block_contents_size, __FILE__, __LINE__);
5105 return(TNG_CRITICAL);
5108 if(type == TNG_FLOAT_DATA)
5110 memcpy(temp + offset, f_dest, uncompressed_len);
5114 memcpy(temp + offset, d_dest, uncompressed_len);
5117 block->block_contents = temp;
5127 return(TNG_SUCCESS);
5131 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
5132 tng_gen_block_t block,
5133 void *start_pos, const int len)
5137 unsigned long max_len, stat, offset;
5140 max_len = compressBound(len);
5141 dest = malloc(max_len);
5144 fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
5145 max_len, __FILE__, __LINE__);
5146 return(TNG_CRITICAL);
5149 stat = compress(dest, &max_len, start_pos, len);
5150 if(stat != (unsigned long)Z_OK)
5153 if(stat == (unsigned long)Z_MEM_ERROR)
5155 fprintf(stderr, "TNG library: Not enough memory. ");
5157 else if(stat == (unsigned long)Z_BUF_ERROR)
5159 fprintf(stderr, "TNG library: Destination buffer too small. ");
5161 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
5162 return(TNG_FAILURE);
5165 offset = (char *)start_pos - block->block_contents;
5167 block->block_contents_size = max_len + offset;
5169 temp = realloc(block->block_contents, block->block_contents_size);
5172 free(block->block_contents);
5174 block->block_contents = 0;
5175 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5176 block->block_contents_size, __FILE__, __LINE__);
5177 return(TNG_CRITICAL);
5180 block->block_contents = temp;
5182 memcpy(temp + offset, dest, max_len);
5186 return(TNG_SUCCESS);
5189 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5190 tng_gen_block_t block,
5192 unsigned long uncompressed_len)
5200 offset = (char *)start_pos - (char *)block->block_contents;
5202 dest = malloc(uncompressed_len);
5205 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5206 uncompressed_len, __FILE__, __LINE__);
5207 return(TNG_CRITICAL);
5210 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
5211 block->block_contents_size - offset);
5216 if(stat == (unsigned long)Z_MEM_ERROR)
5218 fprintf(stderr, "TNG library: Not enough memory. ");
5220 else if(stat == (unsigned long)Z_BUF_ERROR)
5222 fprintf(stderr, "TNG library: Destination buffer too small. ");
5224 else if(stat == (unsigned long)Z_DATA_ERROR)
5226 fprintf(stderr, "TNG library: Data corrupt. ");
5228 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
5230 return(TNG_FAILURE);
5234 block->block_contents_size = uncompressed_len + offset;
5236 temp = realloc(block->block_contents, uncompressed_len + offset);
5239 free(block->block_contents);
5240 block->block_contents = 0;
5242 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5243 block->block_contents_size, __FILE__, __LINE__);
5244 return(TNG_CRITICAL);
5247 memcpy(temp + offset, dest, uncompressed_len);
5249 block->block_contents = temp;
5252 return(TNG_SUCCESS);
5256 /** Allocate memory for storing particle data.
5257 * The allocated block will be refered to by data->values.
5258 * @param tng_data is a trajectory data container.
5259 * @param data is the data struct, which will contain the allocated memory in
5261 * @param n_frames is the number of frames of data to store.
5262 * @param n_particles is the number of particles with data.
5263 * @param n_values_per_frame is the number of data values per particle and
5265 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5266 * error has occured.
5268 static tng_function_status tng_allocate_particle_data_mem
5269 (tng_trajectory_t tng_data,
5270 tng_particle_data_t data,
5272 int64_t stride_length,
5273 const int64_t n_particles,
5274 const int64_t n_values_per_frame)
5277 int64_t i, j, k, size, frame_alloc;
5280 if(n_particles == 0 || n_values_per_frame == 0)
5282 return(TNG_FAILURE);
5285 if(data->strings && data->datatype == TNG_CHAR_DATA)
5287 for(i = 0; i < data->n_frames; i++)
5289 for(j = 0; j < n_particles; j++)
5291 for(k = 0; k < data->n_values_per_frame; k++)
5293 if(data->strings[i][j][k])
5295 free(data->strings[i][j][k]);
5298 free(data->strings[i][j]);
5300 free(data->strings[i]);
5302 free(data->strings);
5304 data->n_frames = n_frames;
5305 n_frames = tng_max_i64(1, n_frames);
5306 data->stride_length = tng_max_i64(1, stride_length);
5307 data->n_values_per_frame = n_values_per_frame;
5308 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5310 if(data->datatype == TNG_CHAR_DATA)
5312 data->strings = malloc(sizeof(char ***) * frame_alloc);
5313 for(i = 0; i < frame_alloc; i++)
5315 data->strings[i] = malloc(sizeof(char **) *
5317 if(!data->strings[i])
5319 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5320 sizeof(union data_values *) * n_particles,
5321 __FILE__, __LINE__);
5322 return(TNG_CRITICAL);
5324 for(j = 0; j < n_particles; j++)
5326 data->strings[i][j] = malloc(sizeof(char *) *
5327 n_values_per_frame);
5328 if(!data->strings[i][j])
5330 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5331 sizeof(union data_values) * n_values_per_frame,
5332 __FILE__, __LINE__);
5333 return(TNG_CRITICAL);
5335 for(k = 0; k < n_values_per_frame; k++)
5337 data->strings[i][j][k] = 0;
5344 switch(data->datatype)
5347 size = sizeof(int64_t);
5349 case TNG_FLOAT_DATA:
5350 size = sizeof(float);
5352 case TNG_DOUBLE_DATA:
5354 size = sizeof(double);
5357 values = realloc(data->values,
5358 size * frame_alloc *
5359 n_particles * n_values_per_frame);
5362 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5363 size * frame_alloc *
5364 n_particles * n_values_per_frame,
5365 __FILE__, __LINE__);
5368 return(TNG_CRITICAL);
5370 data->values = values;
5372 return(TNG_SUCCESS);
5375 static tng_function_status tng_particle_data_find
5376 (tng_trajectory_t tng_data,
5378 tng_particle_data_t *data)
5380 int64_t block_index, i;
5381 tng_trajectory_frame_set_t frame_set = &tng_data->
5382 current_trajectory_frame_set;
5383 char block_type_flag;
5385 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5386 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5388 block_type_flag = TNG_TRAJECTORY_BLOCK;
5392 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5396 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5398 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
5400 *data = &frame_set->tr_particle_data[i];
5401 if((*data)->block_id == id)
5410 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
5412 *data = &tng_data->non_tr_particle_data[i];
5413 if((*data)->block_id == id)
5420 if(block_index == -1)
5422 return(TNG_FAILURE);
5424 return(TNG_SUCCESS);
5427 static tng_function_status tng_data_find
5428 (tng_trajectory_t tng_data,
5430 tng_non_particle_data_t *data)
5432 int64_t block_index, i;
5433 tng_trajectory_frame_set_t frame_set = &tng_data->
5434 current_trajectory_frame_set;
5435 char block_type_flag;
5437 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5438 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5440 block_type_flag = TNG_TRAJECTORY_BLOCK;
5444 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5448 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5450 for(i = 0; i < frame_set->n_data_blocks; i++)
5452 *data = &frame_set->tr_data[i];
5453 if((*data)->block_id == id)
5459 if(block_index == -1)
5461 for(i = 0; i < tng_data->n_data_blocks; i++)
5463 *data = &tng_data->non_tr_data[i];
5464 if((*data)->block_id == id)
5474 for(i = 0; i < tng_data->n_data_blocks; i++)
5476 *data = &tng_data->non_tr_data[i];
5477 if((*data)->block_id == id)
5484 if(block_index == -1)
5486 return(TNG_FAILURE);
5488 return(TNG_SUCCESS);
5491 static tng_function_status tng_data_block_len_calculate
5492 (const tng_trajectory_t tng_data,
5493 const tng_particle_data_t data,
5494 const tng_bool is_particle_data,
5495 const int64_t n_frames,
5496 const int64_t frame_step,
5497 const int64_t stride_length,
5498 const int64_t num_first_particle,
5499 const int64_t n_particles,
5500 const char dependency,
5501 int64_t *data_start_pos,
5506 char ***first_dim_values, **second_dim_values;
5511 return(TNG_SUCCESS);
5514 switch(data->datatype)
5520 size = sizeof(int64_t);
5522 case TNG_FLOAT_DATA:
5523 size = sizeof(float);
5525 case TNG_DOUBLE_DATA:
5527 size = sizeof(double);
5530 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5531 sizeof(data->codec_id);
5532 if(is_particle_data)
5534 *len += sizeof(num_first_particle) + sizeof(n_particles);
5537 if(stride_length > 1)
5539 *len += sizeof(data->first_frame_with_data) +
5540 sizeof(data->stride_length);
5543 if(data->codec_id != TNG_UNCOMPRESSED)
5545 *len += sizeof(data->compression_multiplier);
5548 if(dependency & TNG_FRAME_DEPENDENT)
5550 *len += sizeof(char);
5553 *data_start_pos = *len;
5555 if(data->datatype == TNG_CHAR_DATA)
5557 if(is_particle_data)
5559 for(i = 0; i < n_frames; i++)
5561 first_dim_values = data->strings[i];
5562 for(j = num_first_particle; j < num_first_particle + n_particles;
5565 second_dim_values = first_dim_values[j];
5566 for(k = 0; k < data->n_values_per_frame; k++)
5568 *len += strlen(second_dim_values[k]) + 1;
5575 for(i = 0; i < n_frames; i++)
5577 second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
5578 for(j = 0; j < data->n_values_per_frame; j++)
5580 *len += strlen(second_dim_values[j]) + 1;
5587 *len += size * frame_step * n_particles * data->n_values_per_frame;
5590 return(TNG_SUCCESS);
5593 /** Read the values of a particle data block
5594 * @param tng_data is a trajectory data container.
5595 * @param block is the block to store the data (should already contain
5596 * the block headers and the block contents).
5597 * @param offset is the reading offset to point at the place where the actual
5598 * values are stored, starting from the beginning of the block_contents. The
5599 * offset is changed during the reading.
5600 * @param datatype is the type of data of the data block (char, int, float or
5602 * @param num_first_particle is the number of the first particle in the data
5603 * block. This should be the same as in the corresponding particle mapping
5605 * @param n_particles is the number of particles in the data block. This should
5606 * be the same as in the corresponding particle mapping block.
5607 * @param first_frame_with_data is the frame number of the first frame with data
5608 * in this data block.
5609 * @param stride_length is the number of frames between each data entry.
5610 * @param n_frames is the number of frames in this data block.
5611 * @param n_values is the number of values per particle and frame stored in this
5613 * @param codec_id is the ID of the codec to compress the data.
5614 * @param multiplier is the multiplication factor applied to each data value
5615 * before compression. This factor is applied since some compression algorithms
5616 * work only on integers.
5617 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5618 * error has occured.
5620 static tng_function_status tng_particle_data_read
5621 (tng_trajectory_t tng_data,
5622 tng_gen_block_t block,
5624 const char datatype,
5625 const int64_t num_first_particle,
5626 const int64_t n_particles,
5627 const int64_t first_frame_with_data,
5628 const int64_t stride_length,
5630 const int64_t n_values,
5631 const int64_t codec_id,
5632 const double multiplier)
5634 int64_t i, j, k, tot_n_particles, n_frames_div;
5636 unsigned long data_size;
5637 char ***first_dim_values, **second_dim_values;
5638 tng_particle_data_t data;
5639 tng_trajectory_frame_set_t frame_set =
5640 &tng_data->current_trajectory_frame_set;
5641 char block_type_flag;
5643 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5651 size = sizeof(int64_t);
5653 case TNG_FLOAT_DATA:
5654 size = sizeof(float);
5656 case TNG_DOUBLE_DATA:
5658 size = sizeof(double);
5661 /* If the block does not exist, create it */
5662 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5664 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5666 block_type_flag = TNG_TRAJECTORY_BLOCK;
5670 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5673 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5676 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5677 __FILE__, __LINE__);
5678 return(TNG_CRITICAL);
5680 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5682 data = &frame_set->tr_particle_data[frame_set->
5683 n_particle_data_blocks - 1];
5687 data = &tng_data->non_tr_particle_data[tng_data->
5688 n_particle_data_blocks - 1];
5690 data->block_id = block->id;
5692 data->block_name = malloc(strlen(block->name) + 1);
5693 if(!data->block_name)
5695 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5696 (int)strlen(block->name)+1, __FILE__, __LINE__);
5697 return(TNG_CRITICAL);
5699 strcpy(data->block_name, block->name);
5701 data->datatype = datatype;
5704 /* FIXME: Memory leak from strings. */
5707 data->codec_id = codec_id;
5708 data->compression_multiplier = multiplier;
5709 data->last_retrieved_frame = -1;
5712 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5713 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5714 tng_data->var_num_atoms_flag)
5716 tot_n_particles = frame_set->n_particles;
5720 tot_n_particles = tng_data->n_particles;
5723 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5725 if(codec_id != TNG_UNCOMPRESSED)
5727 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5730 case TNG_XTC_COMPRESSION:
5731 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5733 case TNG_TNG_COMPRESSION:
5734 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5735 if(tng_uncompress(tng_data, block, datatype,
5736 block->block_contents + *offset,
5737 data_size) != TNG_SUCCESS)
5739 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5740 __FILE__, __LINE__);
5741 return(TNG_CRITICAL);
5743 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5746 case TNG_GZIP_COMPRESSION:
5747 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5748 if(tng_gzip_uncompress(tng_data, block,
5749 block->block_contents + *offset,
5750 data_size) != TNG_SUCCESS)
5752 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5754 return(TNG_CRITICAL);
5756 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5761 /* Allocate memory */
5762 if(!data->values || data->n_frames != n_frames ||
5763 data->n_values_per_frame != n_values)
5765 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5767 tot_n_particles, n_values) !=
5770 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5771 __FILE__, __LINE__);
5772 return(TNG_CRITICAL);
5776 data->first_frame_with_data = first_frame_with_data;
5778 if(datatype == TNG_CHAR_DATA)
5780 for(i = 0; i < n_frames_div; i++)
5782 first_dim_values = data->strings[i];
5783 for(j = num_first_particle; j < num_first_particle + n_particles;
5786 second_dim_values = first_dim_values[j];
5787 for(k = 0; k < n_values; k++)
5789 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5791 if(second_dim_values[k])
5793 free(second_dim_values[k]);
5795 second_dim_values[k] = malloc(len);
5796 if(!second_dim_values[k])
5798 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5799 len, __FILE__, __LINE__);
5800 return(TNG_CRITICAL);
5802 strncpy(second_dim_values[k],
5803 block->block_contents+*offset, len);
5811 memcpy((char *)data->values + n_frames_div * size * n_values *
5813 block->block_contents + *offset,
5814 block->block_contents_size - *offset);
5817 case TNG_FLOAT_DATA:
5818 if(tng_data->input_endianness_swap_func_32)
5820 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5822 if(tng_data->input_endianness_swap_func_32(tng_data,
5823 (int32_t *)((char *)data->values + i))
5826 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5827 __FILE__, __LINE__);
5833 case TNG_DOUBLE_DATA:
5834 if(tng_data->input_endianness_swap_func_64)
5836 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5838 if(tng_data->input_endianness_swap_func_64(tng_data,
5839 (int64_t *)((char *)data->values + i))
5842 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5843 __FILE__, __LINE__);
5852 return(TNG_SUCCESS);
5855 /** Write a particle data block
5856 * @param tng_data is a trajectory data container.
5857 * @param block is the block to store the data (should already contain
5858 * the block headers and the block contents).
5859 * @param block_index is the index number of the data block in the frame set.
5860 * @param mapping is the particle mapping that is relevant for the data block.
5861 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5862 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5863 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5864 * error has occured.
5866 static tng_function_status tng_particle_data_block_write
5867 (tng_trajectory_t tng_data,
5868 tng_gen_block_t block,
5869 const int64_t block_index,
5870 const tng_particle_mapping_t mapping,
5871 const char hash_mode)
5873 int64_t n_particles, num_first_particle, n_frames, stride_length;
5874 int64_t frame_step, data_start_pos;
5877 size_t len, offset = 0;
5878 char dependency, temp, *temp_name;
5880 char ***first_dim_values, **second_dim_values;
5881 tng_trajectory_frame_set_t frame_set;
5882 tng_function_status stat;
5884 tng_particle_data_t data;
5885 char block_type_flag;
5887 frame_set = &tng_data->current_trajectory_frame_set;
5889 /* If we have already started writing frame sets it is too late to write
5890 * non-trajectory data blocks */
5891 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5893 block_type_flag = TNG_TRAJECTORY_BLOCK;
5897 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5900 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5902 return(TNG_CRITICAL);
5905 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5907 data = &frame_set->tr_particle_data[block_index];
5909 /* If this data block has not had any data added in this frame set
5910 * do not write it. */
5911 if(data->first_frame_with_data < frame_set->first_frame)
5913 return(TNG_SUCCESS);
5916 stride_length = tng_max_i64(1, data->stride_length);
5920 data = &tng_data->non_tr_particle_data[block_index];
5924 switch(data->datatype)
5930 size = sizeof(int64_t);
5932 case TNG_FLOAT_DATA:
5933 size = sizeof(float);
5935 case TNG_DOUBLE_DATA:
5937 size = sizeof(double);
5940 len = strlen(data->block_name) + 1;
5942 if(!block->name || strlen(block->name) < len)
5944 temp_name = realloc(block->name, len);
5947 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5948 __FILE__, __LINE__);
5951 return(TNG_CRITICAL);
5953 block->name = temp_name;
5955 strncpy(block->name, data->block_name, len);
5956 block->id = data->block_id;
5958 /* If writing frame independent data data->n_frames is 0, but n_frames
5959 is used for the loop writing the data (and reserving memory) and needs
5961 n_frames = tng_max_i64(1, data->n_frames);
5963 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5965 /* If the frame set is finished before writing the full number of frames
5966 make sure the data block is not longer than the frame set. */
5967 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5969 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5972 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5973 n_frames / stride_length;
5975 /* TNG compression will use compression precision to get integers from
5976 * floating point data. The compression multiplier stores that information
5977 * to be able to return the precision of the compressed data. */
5978 if(data->codec_id == TNG_TNG_COMPRESSION)
5980 data->compression_multiplier = tng_data->compression_precision;
5982 /* Uncompressed data blocks do not use compression multipliers at all.
5983 * GZip compression does not need it either. */
5984 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5986 data->compression_multiplier = 1.0;
5989 if(mapping && mapping->n_particles != 0)
5991 n_particles = mapping->n_particles;
5992 num_first_particle = mapping->num_first_particle;
5996 num_first_particle = 0;
5997 if(tng_data->var_num_atoms_flag)
5999 n_particles = frame_set->n_particles;
6003 n_particles = tng_data->n_particles;
6007 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6009 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6013 dependency = TNG_PARTICLE_DEPENDENT;
6016 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6017 frame_step, stride_length, num_first_particle,
6018 n_particles, dependency, &data_start_pos,
6019 &block->block_contents_size) != TNG_SUCCESS)
6021 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6022 __FILE__, __LINE__);
6023 return(TNG_CRITICAL);
6026 if(block->block_contents)
6028 free(block->block_contents);
6030 block->block_contents = malloc(block->block_contents_size);
6031 if(!block->block_contents)
6033 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6034 block->block_contents_size, __FILE__, __LINE__);
6035 return(TNG_CRITICAL);
6039 memcpy(block->block_contents, &data->datatype, sizeof(char));
6040 offset += sizeof(char);
6042 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6043 offset += sizeof(char);
6045 if(dependency & TNG_FRAME_DEPENDENT)
6047 if(stride_length > 1)
6055 memcpy(block->block_contents+offset, &temp, sizeof(char));
6056 offset += sizeof(char);
6059 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6060 sizeof(data->n_values_per_frame));
6061 if(tng_data->output_endianness_swap_func_64)
6063 if(tng_data->output_endianness_swap_func_64(tng_data,
6064 (int64_t *)block->header_contents+offset)
6067 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6068 __FILE__, __LINE__);
6071 offset += sizeof(data->n_values_per_frame);
6073 memcpy(block->block_contents+offset, &data->codec_id,
6074 sizeof(data->codec_id));
6075 if(tng_data->output_endianness_swap_func_64)
6077 if(tng_data->output_endianness_swap_func_64(tng_data,
6078 (int64_t *)block->header_contents+offset)
6081 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6082 __FILE__, __LINE__);
6085 offset += sizeof(data->codec_id);
6087 if(data->codec_id != TNG_UNCOMPRESSED)
6089 memcpy(block->block_contents+offset, &data->compression_multiplier,
6090 sizeof(data->compression_multiplier));
6091 if(tng_data->output_endianness_swap_func_64)
6093 if(tng_data->output_endianness_swap_func_64(tng_data,
6094 (int64_t *)block->header_contents+offset)
6097 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6098 __FILE__, __LINE__);
6101 offset += sizeof(data->compression_multiplier);
6104 if(data->n_frames > 0 && stride_length > 1)
6106 /* FIXME: first_frame_with_data is not reliably set */
6107 if(data->first_frame_with_data == 0)
6109 data->first_frame_with_data = frame_set->first_frame;
6111 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6112 sizeof(data->first_frame_with_data));
6113 if(tng_data->output_endianness_swap_func_64)
6115 if(tng_data->output_endianness_swap_func_64(tng_data,
6116 (int64_t *)block->header_contents+offset)
6119 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6120 __FILE__, __LINE__);
6123 offset += sizeof(data->first_frame_with_data);
6125 memcpy(block->block_contents+offset, &stride_length,
6126 sizeof(stride_length));
6127 if(tng_data->output_endianness_swap_func_64)
6129 if(tng_data->output_endianness_swap_func_64(tng_data,
6130 (int64_t *)block->header_contents+offset)
6133 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6134 __FILE__, __LINE__);
6137 offset += sizeof(stride_length);
6141 memcpy(block->block_contents+offset, &num_first_particle,
6142 sizeof(num_first_particle));
6143 if(tng_data->output_endianness_swap_func_64)
6145 if(tng_data->output_endianness_swap_func_64(tng_data,
6146 (int64_t *)block->header_contents+offset)
6149 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6150 __FILE__, __LINE__);
6153 offset += sizeof(num_first_particle);
6155 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
6156 if(tng_data->output_endianness_swap_func_64)
6158 if(tng_data->output_endianness_swap_func_64(tng_data,
6159 (int64_t *)block->header_contents+offset)
6162 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6163 __FILE__, __LINE__);
6166 offset += sizeof(n_particles);
6168 if(data->datatype == TNG_CHAR_DATA)
6172 for(i = 0; i < frame_step; i++)
6174 first_dim_values = data->strings[i];
6175 for(j = num_first_particle; j < num_first_particle + n_particles;
6178 second_dim_values = first_dim_values[j];
6179 for(k = 0; k < data->n_values_per_frame; k++)
6181 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6182 strncpy(block->block_contents+offset,
6183 second_dim_values[k], len);
6190 else if(data->values)
6192 memcpy(block->block_contents + offset, data->values,
6193 block->block_contents_size - offset);
6195 switch(data->datatype)
6197 case TNG_FLOAT_DATA:
6198 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6199 data->codec_id == TNG_TNG_COMPRESSION)
6201 if(tng_data->input_endianness_swap_func_32)
6203 for(i = offset; i < block->block_contents_size; i+=size)
6205 if(tng_data->input_endianness_swap_func_32(tng_data,
6206 (int32_t *)(block->block_contents + i))
6209 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6210 __FILE__, __LINE__);
6217 multiplier = data->compression_multiplier;
6218 if(fabs(multiplier - 1.0) > 0.00001 ||
6219 tng_data->input_endianness_swap_func_32)
6221 for(i = offset; i < block->block_contents_size; i+=size)
6223 *(float *)(block->block_contents + i) *= (float)multiplier;
6224 if(tng_data->input_endianness_swap_func_32 &&
6225 tng_data->input_endianness_swap_func_32(tng_data,
6226 (int32_t *)(block->block_contents + i))
6229 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6230 __FILE__, __LINE__);
6237 if(tng_data->input_endianness_swap_func_64)
6239 for(i = offset; i < block->block_contents_size; i+=size)
6241 if(tng_data->input_endianness_swap_func_64(tng_data,
6242 (int64_t *)(block->block_contents + i))
6245 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6246 __FILE__, __LINE__);
6251 case TNG_DOUBLE_DATA:
6252 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6253 data->codec_id == TNG_TNG_COMPRESSION)
6255 if(tng_data->input_endianness_swap_func_64)
6257 for(i = offset; i < block->block_contents_size; i+=size)
6259 if(tng_data->input_endianness_swap_func_64(tng_data,
6260 (int64_t *)(block->block_contents + i))
6263 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6264 __FILE__, __LINE__);
6271 multiplier = data->compression_multiplier;
6272 if(fabs(multiplier - 1.0) > 0.00001 ||
6273 tng_data->input_endianness_swap_func_64)
6275 for(i = offset; i < block->block_contents_size; i+=size)
6277 *(double *)(block->block_contents + i) *= multiplier;
6278 if(tng_data->input_endianness_swap_func_64 &&
6279 tng_data->input_endianness_swap_func_64(tng_data,
6280 (int64_t *)(block->block_contents + i))
6283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6284 __FILE__, __LINE__);
6296 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6299 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6300 frame_set->n_unwritten_frames = 0;
6302 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6304 switch(data->codec_id)
6306 case TNG_XTC_COMPRESSION:
6307 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6308 data->codec_id = TNG_UNCOMPRESSED;
6310 case TNG_TNG_COMPRESSION:
6311 stat = tng_compress(tng_data, block, frame_step,
6312 n_particles, data->datatype,
6313 block->block_contents + data_start_pos);
6314 if(stat != TNG_SUCCESS)
6316 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6317 __FILE__, __LINE__);
6318 if(stat == TNG_CRITICAL)
6320 return(TNG_CRITICAL);
6322 /* Set the data again, but with no compression (to write only
6323 * the relevant data) */
6324 data->codec_id = TNG_UNCOMPRESSED;
6325 stat = tng_particle_data_block_write(tng_data, block,
6326 block_index, mapping,
6332 case TNG_GZIP_COMPRESSION:
6333 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6334 stat = tng_gzip_compress(tng_data, block,
6335 block->block_contents + data_start_pos,
6336 block->block_contents_size - data_start_pos);
6337 if(stat != TNG_SUCCESS)
6339 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6341 if(stat == TNG_CRITICAL)
6343 return(TNG_CRITICAL);
6345 /* Set the data again, but with no compression (to write only
6346 * the relevant data) */
6347 data->codec_id = TNG_UNCOMPRESSED;
6348 stat = tng_particle_data_block_write(tng_data, block,
6349 block_index, mapping,
6353 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6359 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6361 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6362 tng_data->output_file_path, __FILE__, __LINE__);
6363 return(TNG_CRITICAL);
6366 if(fwrite(block->block_contents, block->block_contents_size, 1,
6367 tng_data->output_file) != 1)
6369 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6371 return(TNG_CRITICAL);
6374 return(TNG_SUCCESS);
6378 /** Create a non-particle data block
6379 * @param tng_data is a trajectory data container.
6380 * @param block_type_flag specifies if this is a trajectory block or a
6381 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6382 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6383 * error has occured.
6385 static tng_function_status tng_data_block_create
6386 (tng_trajectory_t tng_data,
6387 const char block_type_flag)
6389 tng_trajectory_frame_set_t frame_set =
6390 &tng_data->current_trajectory_frame_set;
6392 tng_non_particle_data_t data;
6394 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6396 frame_set->n_data_blocks++;
6397 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6398 frame_set->n_data_blocks);
6401 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6402 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6403 __FILE__, __LINE__);
6404 free(frame_set->tr_data);
6405 frame_set->tr_data = 0;
6406 return(TNG_CRITICAL);
6408 frame_set->tr_data = data;
6412 tng_data->n_data_blocks++;
6413 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6414 tng_data->n_data_blocks);
6417 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6418 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6419 __FILE__, __LINE__);
6420 free(tng_data->non_tr_data);
6421 tng_data->non_tr_data = 0;
6422 return(TNG_CRITICAL);
6424 tng_data->non_tr_data = data;
6427 return(TNG_SUCCESS);
6431 /** Allocate memory for storing non-particle data.
6432 * The allocated block will be refered to by data->values.
6433 * @param tng_data is a trajectory data container.
6434 * @param data is the data struct, which will contain the allocated memory in
6436 * @param n_frames is the number of frames of data to store.
6437 * @param n_values_per_frame is the number of data values per frame.
6438 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6439 * error has occured.
6441 static tng_function_status tng_allocate_data_mem
6442 (tng_trajectory_t tng_data,
6443 tng_non_particle_data_t data,
6445 int64_t stride_length,
6446 const int64_t n_values_per_frame)
6449 int64_t i, j, size, frame_alloc;
6452 if(n_values_per_frame == 0)
6454 return(TNG_FAILURE);
6457 if(data->strings && data->datatype == TNG_CHAR_DATA)
6459 for(i = 0; i < data->n_frames; i++)
6461 for(j = 0; j < data->n_values_per_frame; j++)
6463 if(data->strings[i][j])
6465 free(data->strings[i][j]);
6466 data->strings[i][j] = 0;
6469 free(data->strings[i]);
6470 data->strings[i] = 0;
6472 free(data->strings);
6474 data->n_frames = n_frames;
6475 data->stride_length = tng_max_i64(1, stride_length);
6476 n_frames = tng_max_i64(1, n_frames);
6477 data->n_values_per_frame = n_values_per_frame;
6478 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6480 if(data->datatype == TNG_CHAR_DATA)
6482 data->strings = malloc(sizeof(char **) * frame_alloc);
6483 for(i = 0; i < frame_alloc; i++)
6485 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6486 if(!data->strings[i])
6488 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6490 __FILE__, __LINE__);
6491 return(TNG_CRITICAL);
6493 for(j = 0; j < n_values_per_frame; j++)
6495 data->strings[i][j] = 0;
6501 switch(data->datatype)
6504 size = sizeof(int64_t);
6506 case TNG_FLOAT_DATA:
6507 size = sizeof(float);
6509 case TNG_DOUBLE_DATA:
6511 size = sizeof(double);
6514 values = realloc(data->values,
6515 size * frame_alloc *
6516 n_values_per_frame);
6519 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6520 size * frame_alloc *
6522 __FILE__, __LINE__);
6525 return(TNG_CRITICAL);
6527 data->values = values;
6530 return(TNG_SUCCESS);
6533 /** Read the values of a non-particle data block
6534 * @param tng_data is a trajectory data container.
6535 * @param block is the block to store the data (should already contain
6536 * the block headers and the block contents).
6537 * @param offset is the reading offset to point at the place where the actual
6538 * values are stored, starting from the beginning of the block_contents. The
6539 * offset is changed during the reading.
6540 * @param datatype is the type of data of the data block (char, int, float or
6542 * @param first_frame_with_data is the frame number of the first frame with data
6543 * in this data block.
6544 * @param stride_length is the number of frames between each data entry.
6545 * @param n_frames is the number of frames in this data block.
6546 * @param n_values is the number of values per frame stored in this data block.
6547 * @param codec_id is the ID of the codec to compress the data.
6548 * @param multiplier is the multiplication factor applied to each data value
6549 * before compression. This factor is applied since some compression algorithms
6550 * work only on integers.
6551 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6552 * error has occured.
6554 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6555 tng_gen_block_t block,
6557 const char datatype,
6558 const int64_t first_frame_with_data,
6559 const int64_t stride_length,
6561 const int64_t n_values,
6562 const int64_t codec_id,
6563 const double multiplier)
6565 int64_t i, j, n_frames_div;
6568 unsigned long data_size;
6570 tng_non_particle_data_t data;
6571 tng_trajectory_frame_set_t frame_set =
6572 &tng_data->current_trajectory_frame_set;
6573 char block_type_flag;
6575 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6577 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6585 size = sizeof(int64_t);
6587 case TNG_FLOAT_DATA:
6588 size = sizeof(float);
6590 case TNG_DOUBLE_DATA:
6592 size = sizeof(double);
6595 /* If the block does not exist, create it */
6596 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6598 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6600 block_type_flag = TNG_TRAJECTORY_BLOCK;
6604 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6607 if(tng_data_block_create(tng_data, block_type_flag) !=
6610 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6611 __FILE__, __LINE__);
6612 return(TNG_CRITICAL);
6614 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6616 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6620 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6622 data->block_id = block->id;
6624 data->block_name = malloc(strlen(block->name) + 1);
6625 if(!data->block_name)
6627 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6628 (int)strlen(block->name)+1, __FILE__, __LINE__);
6629 return(TNG_CRITICAL);
6631 strcpy(data->block_name, block->name);
6633 data->datatype = datatype;
6636 /* FIXME: Memory leak from strings. */
6639 data->codec_id = codec_id;
6640 data->compression_multiplier = multiplier;
6641 data->last_retrieved_frame = -1;
6644 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6646 if(codec_id != TNG_UNCOMPRESSED)
6651 case TNG_GZIP_COMPRESSION:
6652 data_size = n_frames_div * size * n_values;
6653 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6654 if(tng_gzip_uncompress(tng_data, block,
6655 block->block_contents + *offset,
6656 data_size) != TNG_SUCCESS)
6658 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6660 return(TNG_CRITICAL);
6662 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6668 /* Allocate memory */
6669 if(!data->values || data->n_frames != n_frames ||
6670 data->n_values_per_frame != n_values)
6672 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6676 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6677 __FILE__, __LINE__);
6678 return(TNG_CRITICAL);
6682 data->first_frame_with_data = first_frame_with_data;
6684 if(datatype == TNG_CHAR_DATA)
6686 for(i = 0; i < n_frames_div; i++)
6688 for(j = 0; j < n_values; j++)
6690 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6692 if(data->strings[i][j])
6694 free(data->strings[i][j]);
6696 data->strings[i][j] = malloc(len);
6697 if(!data->strings[i][j])
6699 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6700 len, __FILE__, __LINE__);
6701 return(TNG_CRITICAL);
6703 strncpy(data->strings[i][j], block->block_contents+*offset,
6711 memcpy(data->values, block->block_contents + *offset,
6712 block->block_contents_size - *offset);
6715 case TNG_FLOAT_DATA:
6716 if(tng_data->input_endianness_swap_func_32)
6718 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6720 if(tng_data->input_endianness_swap_func_32(tng_data,
6721 (int32_t *)((char *)data->values + i))
6724 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6725 __FILE__, __LINE__);
6731 case TNG_DOUBLE_DATA:
6732 if(tng_data->input_endianness_swap_func_64)
6734 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6736 if(tng_data->input_endianness_swap_func_64(tng_data,
6737 (int64_t *)((char *)data->values + i))
6740 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6741 __FILE__, __LINE__);
6750 return(TNG_SUCCESS);
6753 /** Write a non-particle data block
6754 * @param tng_data is a trajectory data container.
6755 * @param block is the block to store the data (should already contain
6756 * the block headers and the block contents).
6757 * @param block_index is the index number of the data block in the frame set.
6758 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6759 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6760 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6761 * error has occured.
6763 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6764 tng_gen_block_t block,
6765 const int64_t block_index,
6766 const char hash_mode)
6768 int64_t n_frames, stride_length, frame_step, data_start_pos;
6770 int offset = 0, size;
6773 tng_function_status stat;
6775 char temp, dependency, *temp_name;
6777 tng_trajectory_frame_set_t frame_set =
6778 &tng_data->current_trajectory_frame_set;
6780 tng_non_particle_data_t data;
6781 char block_type_flag;
6783 /* If we have already started writing frame sets it is too late to write
6784 * non-trajectory data blocks */
6785 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6787 block_type_flag = TNG_TRAJECTORY_BLOCK;
6791 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6794 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6796 return(TNG_CRITICAL);
6799 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6801 data = &frame_set->tr_data[block_index];
6803 /* If this data block has not had any data added in this frame set
6804 * do not write it. */
6805 if(data->first_frame_with_data < frame_set->first_frame)
6807 return(TNG_SUCCESS);
6810 stride_length = tng_max_i64(1, data->stride_length);
6814 data = &tng_data->non_tr_data[block_index];
6818 switch(data->datatype)
6824 size = sizeof(int64_t);
6826 case TNG_FLOAT_DATA:
6827 size = sizeof(float);
6829 case TNG_DOUBLE_DATA:
6831 size = sizeof(double);
6834 len = (unsigned int)strlen(data->block_name) + 1;
6836 if(!block->name || strlen(block->name) < len)
6838 temp_name = realloc(block->name, len);
6841 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6842 __FILE__, __LINE__);
6845 return(TNG_CRITICAL);
6847 block->name = temp_name;
6849 strncpy(block->name, data->block_name, len);
6850 block->id = data->block_id;
6852 /* If writing frame independent data data->n_frames is 0, but n_frames
6853 is used for the loop writing the data (and reserving memory) and needs
6855 n_frames = tng_max_i64(1, data->n_frames);
6857 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6859 /* If the frame set is finished before writing the full number of frames
6860 make sure the data block is not longer than the frame set. */
6861 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6863 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6866 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6867 n_frames / stride_length;
6869 /* TNG compression will use compression precision to get integers from
6870 * floating point data. The compression multiplier stores that information
6871 * to be able to return the precision of the compressed data. */
6872 if(data->codec_id == TNG_TNG_COMPRESSION)
6874 data->compression_multiplier = tng_data->compression_precision;
6876 /* Uncompressed data blocks do not use compression multipliers at all.
6877 * GZip compression does not need it either. */
6878 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6880 data->compression_multiplier = 1.0;
6883 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6885 dependency = TNG_FRAME_DEPENDENT;
6892 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6893 frame_step, stride_length, 0,
6894 1, dependency, &data_start_pos,
6895 &block->block_contents_size) != TNG_SUCCESS)
6897 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6898 __FILE__, __LINE__);
6899 return(TNG_CRITICAL);
6902 if(block->block_contents)
6904 free(block->block_contents);
6906 block->block_contents = malloc(block->block_contents_size);
6907 if(!block->block_contents)
6909 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6910 block->block_contents_size, __FILE__, __LINE__);
6911 return(TNG_CRITICAL);
6915 memcpy(block->block_contents, &data->datatype, sizeof(char));
6916 offset += sizeof(char);
6918 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6919 offset += sizeof(char);
6921 if(dependency & TNG_FRAME_DEPENDENT)
6923 if(stride_length > 1)
6931 memcpy(block->block_contents+offset, &temp, sizeof(char));
6932 offset += sizeof(char);
6935 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6936 sizeof(data->n_values_per_frame));
6937 if(tng_data->output_endianness_swap_func_64)
6939 if(tng_data->output_endianness_swap_func_64(tng_data,
6940 (int64_t *)block->header_contents+offset)
6943 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6944 __FILE__, __LINE__);
6947 offset += sizeof(data->n_values_per_frame);
6949 memcpy(block->block_contents+offset, &data->codec_id,
6950 sizeof(data->codec_id));
6951 if(tng_data->output_endianness_swap_func_64)
6953 if(tng_data->output_endianness_swap_func_64(tng_data,
6954 (int64_t *)block->header_contents+offset)
6957 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6958 __FILE__, __LINE__);
6961 offset += sizeof(data->codec_id);
6963 if(data->codec_id != TNG_UNCOMPRESSED)
6965 memcpy(block->block_contents+offset, &data->compression_multiplier,
6966 sizeof(data->compression_multiplier));
6967 if(tng_data->output_endianness_swap_func_64)
6969 if(tng_data->output_endianness_swap_func_64(tng_data,
6970 (int64_t *)block->header_contents+offset)
6973 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6974 __FILE__, __LINE__);
6977 offset += sizeof(data->compression_multiplier);
6980 if(data->n_frames > 0 && stride_length > 1)
6982 /* FIXME: first_frame_with_data is not reliably set */
6983 if(data->first_frame_with_data == 0)
6985 data->first_frame_with_data = frame_set->first_frame;
6987 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6988 sizeof(data->first_frame_with_data));
6989 if(tng_data->output_endianness_swap_func_64)
6991 if(tng_data->output_endianness_swap_func_64(tng_data,
6992 (int64_t *)block->header_contents+offset)
6995 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6996 __FILE__, __LINE__);
6999 offset += sizeof(data->first_frame_with_data);
7001 memcpy(block->block_contents+offset, &stride_length,
7002 sizeof(data->stride_length));
7003 if(tng_data->output_endianness_swap_func_64)
7005 if(tng_data->output_endianness_swap_func_64(tng_data,
7006 (int64_t *)block->header_contents+offset)
7009 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7010 __FILE__, __LINE__);
7013 offset += sizeof(data->stride_length);
7016 if(data->datatype == TNG_CHAR_DATA)
7020 for(i = 0; i < frame_step; i++)
7022 for(j = 0; j < data->n_values_per_frame; j++)
7024 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7025 strncpy(block->block_contents+offset, data->strings[i][j],
7032 else if(data->values)
7034 memcpy(block->block_contents + offset, data->values,
7035 block->block_contents_size - offset);
7036 switch(data->datatype)
7038 case TNG_FLOAT_DATA:
7039 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7040 data->codec_id == TNG_TNG_COMPRESSION)
7042 if(tng_data->input_endianness_swap_func_32)
7044 for(i = offset; i < block->block_contents_size; i+=size)
7046 if(tng_data->input_endianness_swap_func_32(tng_data,
7047 (int32_t *)(block->block_contents + i))
7050 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7051 __FILE__, __LINE__);
7058 multiplier = data->compression_multiplier;
7059 if(fabs(multiplier - 1.0) > 0.00001 ||
7060 tng_data->input_endianness_swap_func_32)
7062 for(i = offset; block->block_contents_size; i+=size)
7064 *(float *)(block->block_contents + i) *= (float)multiplier;
7065 if(tng_data->input_endianness_swap_func_32 &&
7066 tng_data->input_endianness_swap_func_32(tng_data,
7067 (int32_t *)(block->block_contents + i))
7070 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7071 __FILE__, __LINE__);
7078 if(tng_data->input_endianness_swap_func_64)
7080 for(i = offset; i < block->block_contents_size; i+=size)
7082 if(tng_data->input_endianness_swap_func_64(tng_data,
7083 (int64_t *)(block->block_contents + i))
7086 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7087 __FILE__, __LINE__);
7092 case TNG_DOUBLE_DATA:
7093 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7094 data->codec_id == TNG_TNG_COMPRESSION)
7096 if(tng_data->input_endianness_swap_func_64)
7098 for(i = offset; i < block->block_contents_size; i+=size)
7100 if(tng_data->input_endianness_swap_func_64(tng_data,
7101 (int64_t *)(block->block_contents + i))
7104 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7105 __FILE__, __LINE__);
7112 multiplier = data->compression_multiplier;
7113 if(fabs(multiplier - 1.0) > 0.00001 ||
7114 tng_data->input_endianness_swap_func_64)
7116 for(i = offset; i < block->block_contents_size; i+=size)
7118 *(double *)(block->block_contents + i) *= multiplier;
7119 if(tng_data->input_endianness_swap_func_64 &&
7120 tng_data->input_endianness_swap_func_64(tng_data,
7121 (int64_t *)(block->block_contents + i))
7124 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7125 __FILE__, __LINE__);
7137 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7140 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7141 frame_set->n_unwritten_frames = 0;
7143 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7145 switch(data->codec_id)
7148 case TNG_GZIP_COMPRESSION:
7149 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7150 stat = tng_gzip_compress(tng_data, block,
7151 block->block_contents + data_start_pos,
7152 block->block_contents_size - data_start_pos);
7153 if(stat != TNG_SUCCESS)
7155 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7157 if(stat == TNG_CRITICAL)
7159 return(TNG_CRITICAL);
7161 data->codec_id = TNG_UNCOMPRESSED;
7163 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7169 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7171 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7172 tng_data->output_file_path, __FILE__, __LINE__);
7173 return(TNG_CRITICAL);
7176 if(fwrite(block->block_contents, block->block_contents_size, 1,
7177 tng_data->output_file) != 1)
7179 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7180 __FILE__, __LINE__);
7181 return(TNG_CRITICAL);
7184 return(TNG_SUCCESS);
7187 /** Read the meta information of a data block (particle or non-particle data).
7188 * @param tng_data is a trajectory data container.
7189 * @param block is the block to store the data (should already contain
7190 * the block headers).
7191 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7192 * error has occured.
7194 static tng_function_status tng_data_block_meta_information_read
7195 (tng_trajectory_t tng_data,
7196 tng_gen_block_t block,
7203 int64_t *first_frame_with_data,
7204 int64_t *stride_length,
7206 int64_t *num_first_particle,
7207 int64_t *block_n_particles,
7213 if(block->block_contents)
7215 contents = block->block_contents;
7219 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7220 contents = malloc(meta_size);
7223 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7224 meta_size, __FILE__, __LINE__);
7227 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7229 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7231 return(TNG_CRITICAL);
7235 memcpy(datatype, contents+*offset,
7237 *offset += sizeof(*datatype);
7239 memcpy(dependency, contents+*offset,
7240 sizeof(*dependency));
7241 *offset += sizeof(*dependency);
7243 if(*dependency & TNG_FRAME_DEPENDENT)
7245 memcpy(sparse_data, contents+*offset,
7246 sizeof(*sparse_data));
7247 *offset += sizeof(*sparse_data);
7250 memcpy(n_values, contents+*offset,
7252 if(tng_data->input_endianness_swap_func_64)
7254 if(tng_data->input_endianness_swap_func_64(tng_data,
7258 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7259 __FILE__, __LINE__);
7262 *offset += sizeof(*n_values);
7264 memcpy(codec_id, contents+*offset,
7266 if(tng_data->input_endianness_swap_func_64)
7268 if(tng_data->input_endianness_swap_func_64(tng_data,
7272 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7273 __FILE__, __LINE__);
7276 *offset += sizeof(*codec_id);
7278 if(*codec_id != TNG_UNCOMPRESSED)
7280 memcpy(multiplier, contents+*offset,
7281 sizeof(*multiplier));
7282 if(tng_data->input_endianness_swap_func_64)
7284 if(tng_data->input_endianness_swap_func_64(tng_data,
7285 (int64_t *) multiplier)
7288 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7289 __FILE__, __LINE__);
7292 *offset += sizeof(*multiplier);
7299 if(*dependency & TNG_FRAME_DEPENDENT)
7303 memcpy(first_frame_with_data, contents+*offset,
7304 sizeof(*first_frame_with_data));
7305 if(tng_data->input_endianness_swap_func_64)
7307 if(tng_data->input_endianness_swap_func_64(tng_data,
7308 first_frame_with_data)
7311 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7312 __FILE__, __LINE__);
7315 *offset += sizeof(*first_frame_with_data);
7317 memcpy(stride_length, contents+*offset,
7318 sizeof(*stride_length));
7319 if(tng_data->input_endianness_swap_func_64)
7321 if(tng_data->input_endianness_swap_func_64(tng_data,
7325 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7326 __FILE__, __LINE__);
7329 *offset += sizeof(*stride_length);
7330 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7331 (*first_frame_with_data -
7332 tng_data->current_trajectory_frame_set.first_frame);
7336 *first_frame_with_data = 0;
7338 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7343 *first_frame_with_data = 0;
7348 if (*dependency & TNG_PARTICLE_DEPENDENT)
7350 memcpy(num_first_particle, contents+*offset,
7351 sizeof(*num_first_particle));
7352 if(tng_data->input_endianness_swap_func_64)
7354 if(tng_data->input_endianness_swap_func_64(tng_data,
7358 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7359 __FILE__, __LINE__);
7362 *offset += sizeof(*num_first_particle);
7364 memcpy(block_n_particles, contents+*offset,
7365 sizeof(*block_n_particles));
7366 if(tng_data->input_endianness_swap_func_64)
7368 if(tng_data->input_endianness_swap_func_64(tng_data,
7372 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7373 __FILE__, __LINE__);
7376 *offset += sizeof(*block_n_particles);
7379 if(!block->block_contents)
7383 return(TNG_SUCCESS);
7386 /** Read the contents of a data block (particle or non-particle data).
7387 * @param tng_data is a trajectory data container.
7388 * @param block is the block to store the data (should already contain
7389 * the block headers).
7390 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7391 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7392 * compared to the md5 hash of the read contents to ensure valid data.
7393 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7394 * error has occured.
7396 static tng_function_status tng_data_block_contents_read
7397 (tng_trajectory_t tng_data,
7398 tng_gen_block_t block,
7399 const char hash_mode)
7401 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7402 int64_t stride_length, block_n_particles, num_first_particle;
7404 char datatype, dependency, sparse_data;
7408 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7410 return(TNG_CRITICAL);
7413 if(block->block_contents)
7415 free(block->block_contents);
7418 block->block_contents = malloc(block->block_contents_size);
7419 if(!block->block_contents)
7421 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7422 block->block_contents_size, __FILE__, __LINE__);
7423 return(TNG_CRITICAL);
7426 /* Read the whole block into block_contents to be able to write it to
7427 * disk even if it cannot be interpreted. */
7428 if(fread(block->block_contents, block->block_contents_size, 1,
7429 tng_data->input_file) == 0)
7431 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7432 return(TNG_CRITICAL);
7435 /* FIXME: Does not check if the size of the contents matches the expected
7436 * size or if the contents can be read. */
7438 if(hash_mode == TNG_USE_HASH)
7440 tng_md5_hash_match_verify(block, &same_hash);
7441 if(same_hash != TNG_TRUE)
7443 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7444 block->name, __FILE__, __LINE__);
7445 /* return(TNG_FAILURE); */
7449 if(tng_data_block_meta_information_read(tng_data, block,
7451 &dependency, &sparse_data,
7452 &n_values, &codec_id,
7453 &first_frame_with_data,
7454 &stride_length, &n_frames,
7455 &num_first_particle,
7457 &multiplier) == TNG_CRITICAL)
7459 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7460 block->name, __FILE__, __LINE__);
7461 return(TNG_CRITICAL);
7464 if (dependency & TNG_PARTICLE_DEPENDENT)
7466 return(tng_particle_data_read(tng_data, block,
7470 first_frame_with_data,
7473 codec_id, multiplier));
7477 return(tng_data_read(tng_data, block,
7479 first_frame_with_data,
7482 codec_id, multiplier));
7487 // ** Move the blocks in a frame set so that there is no unused space between
7488 // * them. This can only be done on the last frame set in the file and should
7489 // * be done e.g. if the last frame set in the file has fewer frames than
7490 // * default or after compressing data blocks in a frame set.
7491 // * @param tng_data is a trajectory data container.
7492 // * @details the current_trajectory_frame_set is the one that will be modified.
7493 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7494 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7495 // * FIXME: This function is not finished!!!
7497 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7499 // tng_gen_block_t block;
7500 // tng_trajectory_frame_set_t frame_set;
7501 // FILE *temp = tng_data->input_file;
7502 // int64_t pos, contents_start_pos, output_file_len;
7504 // frame_set = &tng_data->current_trajectory_frame_set;
7506 // if(frame_set->n_written_frames == frame_set->n_frames)
7508 // return(TNG_SUCCESS);
7511 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7512 // tng_data->last_trajectory_frame_set_output_file_pos)
7516 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7518 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7519 // __FILE__, __LINE__);
7520 // return(TNG_CRITICAL);
7523 // tng_block_init(&block);
7524 // // output_file_pos = ftell(tng_data->output_file);
7526 // tng_data->input_file = tng_data->output_file;
7528 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7530 // fseek(tng_data->output_file, pos, SEEK_SET);
7531 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7533 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7534 // __FILE__, __LINE__);
7535 // tng_data->input_file = temp;
7536 // tng_block_destroy(&block);
7537 // return(TNG_CRITICAL);
7540 // contents_start_pos = ftell(tng_data->output_file);
7542 // fseek(tng_data->output_file, 0, SEEK_END);
7543 // output_file_len = ftell(tng_data->output_file);
7544 // pos = contents_start_pos + block->block_contents_size;
7545 // fseek(tng_data->output_file, pos,
7548 // while(pos < output_file_len)
7550 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7552 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7553 // __FILE__, __LINE__);
7554 // tng_data->input_file = temp;
7555 // tng_block_destroy(&block);
7556 // return(TNG_CRITICAL);
7558 // pos += block->header_contents_size + block->block_contents_size;
7559 // fseek(tng_data->output_file, pos, SEEK_SET);
7562 // return(TNG_SUCCESS);
7565 /** Finish writing the current frame set. Update the number of frames
7566 * and the hashes of the frame set and all its data blocks (if hash_mode
7568 * @param tng_data is a trajectory data container.
7569 * @param hash_mode specifies whether to update the block md5 hash when
7570 * updating the pointers.
7571 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7572 * error has occured.
7574 static tng_function_status tng_frame_set_finalize
7575 (tng_trajectory_t tng_data, const char hash_mode)
7577 tng_gen_block_t block;
7578 tng_trajectory_frame_set_t frame_set;
7579 FILE *temp = tng_data->input_file;
7580 int64_t pos, contents_start_pos, output_file_len;
7582 frame_set = &tng_data->current_trajectory_frame_set;
7584 if(frame_set->n_written_frames == frame_set->n_frames)
7586 return(TNG_SUCCESS);
7589 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7591 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7592 __FILE__, __LINE__);
7593 return(TNG_CRITICAL);
7596 tng_block_init(&block);
7597 /* output_file_pos = ftell(tng_data->output_file); */
7599 tng_data->input_file = tng_data->output_file;
7601 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7603 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7605 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7607 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7608 __FILE__, __LINE__);
7609 tng_data->input_file = temp;
7610 tng_block_destroy(&block);
7611 return(TNG_CRITICAL);
7614 contents_start_pos = ftell(tng_data->output_file);
7616 fseek(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7617 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7618 1, tng_data->output_file) != 1)
7620 tng_data->input_file = temp;
7621 tng_block_destroy(&block);
7622 return(TNG_CRITICAL);
7626 if(hash_mode == TNG_USE_HASH)
7628 tng_md5_hash_update(tng_data, block, pos,
7629 pos + block->header_contents_size);
7632 fseek(tng_data->output_file, 0, SEEK_END);
7633 output_file_len = ftell(tng_data->output_file);
7634 pos = contents_start_pos + block->block_contents_size;
7635 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7637 while(pos < output_file_len)
7639 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7641 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7642 __FILE__, __LINE__);
7643 tng_data->input_file = temp;
7644 tng_block_destroy(&block);
7645 return(TNG_CRITICAL);
7648 if(hash_mode == TNG_USE_HASH)
7650 tng_md5_hash_update(tng_data, block, pos,
7651 pos + block->header_contents_size);
7653 pos += block->header_contents_size + block->block_contents_size;
7654 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7657 tng_data->input_file = temp;
7658 tng_block_destroy(&block);
7659 return(TNG_SUCCESS);
7663 // ** Sets the name of a file contents block
7664 // * @param tng_data is a trajectory data container.
7665 // * @param block is the block, of which to change names.
7666 // * @param new_name is the new name of the block.
7667 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7668 // * error has occured.
7670 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7671 // tng_gen_block_t block,
7672 // const char *new_name)
7676 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7678 // * If the currently stored string length is not enough to store the new
7679 // * string it is freed and reallocated. *
7680 // if(block->name && strlen(block->name) < len)
7682 // free(block->name);
7687 // block->name = malloc(len);
7690 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7691 // __FILE__, __LINE__);
7692 // return(TNG_CRITICAL);
7696 // strncpy(block->name, new_name, len);
7698 // return(TNG_SUCCESS);
7702 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7703 const tng_atom_t atom,
7704 tng_residue_t *residue)
7708 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7710 *residue = atom->residue;
7712 return(TNG_SUCCESS);
7715 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7716 const tng_atom_t atom,
7721 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7722 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7724 strncpy(name, atom->name, max_len - 1);
7725 name[max_len - 1] = 0;
7727 if(strlen(atom->name) > (unsigned int)max_len - 1)
7729 return(TNG_FAILURE);
7731 return(TNG_SUCCESS);
7734 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7736 const char *new_name)
7741 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7742 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7744 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7746 /* If the currently stored string length is not enough to store the new
7747 * string it is freed and reallocated. */
7748 if(atom->name && strlen(atom->name) < len)
7755 atom->name = malloc(len);
7758 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7759 __FILE__, __LINE__);
7760 return(TNG_CRITICAL);
7764 strncpy(atom->name, new_name, len);
7766 return(TNG_SUCCESS);
7769 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7770 const tng_atom_t atom,
7775 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7776 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7778 strncpy(type, atom->atom_type, max_len - 1);
7779 type[max_len - 1] = 0;
7781 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7783 return(TNG_FAILURE);
7785 return(TNG_SUCCESS);
7788 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7790 const char *new_type)
7795 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7796 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7798 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7800 /* If the currently stored string length is not enough to store the new
7801 * string it is freed and reallocated. */
7802 if(atom->atom_type && strlen(atom->atom_type) < len)
7804 free(atom->atom_type);
7805 atom->atom_type = 0;
7807 if(!atom->atom_type)
7809 atom->atom_type = malloc(len);
7810 if(!atom->atom_type)
7812 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7813 __FILE__, __LINE__);
7814 return(TNG_CRITICAL);
7818 strncpy(atom->atom_type, new_type, len);
7820 return(TNG_SUCCESS);
7823 /** Initialise an atom struct
7824 * @param atom is the atom to initialise.
7825 * @return TNG_SUCCESS (0) if successful.
7827 static tng_function_status tng_atom_init(tng_atom_t atom)
7830 atom->atom_type = 0;
7832 return(TNG_SUCCESS);
7835 /** Free the memory in an atom struct
7836 * @param atom is the atom to destroy.
7837 * @return TNG_SUCCESS (0) if successful.
7839 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7848 free(atom->atom_type);
7849 atom->atom_type = 0;
7852 return(TNG_SUCCESS);
7855 tng_function_status DECLSPECDLLEXPORT tng_version_major
7856 (const tng_trajectory_t tng_data,
7861 *version = TNG_VERSION_MAJOR;
7863 return(TNG_SUCCESS);
7866 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7867 (const tng_trajectory_t tng_data,
7872 *version = TNG_VERSION_MINOR;
7874 return(TNG_SUCCESS);
7877 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7878 (const tng_trajectory_t tng_data,
7883 *patch_level = TNG_VERSION_PATCHLEVEL;
7885 return(TNG_SUCCESS);
7888 tng_function_status DECLSPECDLLEXPORT tng_version
7889 (const tng_trajectory_t tng_data,
7894 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
7896 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
7898 return(TNG_SUCCESS);
7901 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7902 (tng_trajectory_t tng_data,
7904 tng_molecule_t *molecule)
7908 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7909 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7911 /* Set ID to the ID of the last molecule + 1 */
7912 if(tng_data->n_molecules)
7914 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7921 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7924 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7925 (tng_trajectory_t tng_data,
7928 tng_molecule_t *molecule)
7930 tng_molecule_t new_molecules;
7931 int64_t *new_molecule_cnt_list;
7932 tng_function_status stat = TNG_SUCCESS;
7934 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7935 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7937 new_molecules = realloc(tng_data->molecules,
7938 sizeof(struct tng_molecule) *
7939 (tng_data->n_molecules + 1));
7943 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7944 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7945 __FILE__, __LINE__);
7946 free(tng_data->molecules);
7947 tng_data->molecules = 0;
7948 return(TNG_CRITICAL);
7951 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7953 (tng_data->n_molecules + 1));
7955 if(!new_molecule_cnt_list)
7957 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7958 sizeof(int64_t) * (tng_data->n_molecules + 1),
7959 __FILE__, __LINE__);
7960 free(tng_data->molecule_cnt_list);
7961 tng_data->molecule_cnt_list = 0;
7962 free(new_molecules);
7963 return(TNG_CRITICAL);
7966 tng_data->molecules = new_molecules;
7967 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7969 *molecule = &new_molecules[tng_data->n_molecules];
7971 tng_molecule_init(tng_data, *molecule);
7972 tng_molecule_name_set(tng_data, *molecule, name);
7974 /* FIXME: Should this be a function argument instead? */
7975 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7977 (*molecule)->id = id;
7979 tng_data->n_molecules++;
7984 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
7985 (tng_trajectory_t tng_data,
7986 tng_molecule_t *molecule_p)
7988 int64_t *new_molecule_cnt_list, id;
7989 tng_molecule_t new_molecules, molecule;
7991 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7993 /* Set ID to the ID of the last molecule + 1 */
7994 if(tng_data->n_molecules)
7996 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
8003 new_molecules = realloc(tng_data->molecules,
8004 sizeof(struct tng_molecule) *
8005 (tng_data->n_molecules + 1));
8009 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8010 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8011 __FILE__, __LINE__);
8012 free(tng_data->molecules);
8013 tng_data->molecules = 0;
8014 return(TNG_CRITICAL);
8017 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8019 (tng_data->n_molecules + 1));
8021 if(!new_molecule_cnt_list)
8023 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8024 sizeof(int64_t) * (tng_data->n_molecules + 1),
8025 __FILE__, __LINE__);
8026 free(tng_data->molecule_cnt_list);
8027 tng_data->molecule_cnt_list = 0;
8028 free(new_molecules);
8029 return(TNG_CRITICAL);
8032 molecule = *molecule_p;
8034 tng_data->molecules = new_molecules;
8035 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8037 new_molecules[tng_data->n_molecules] = *molecule;
8039 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8043 molecule = &new_molecules[tng_data->n_molecules];
8045 *molecule_p = molecule;
8049 tng_data->n_molecules++;
8051 return(TNG_SUCCESS);
8054 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8055 const tng_molecule_t molecule,
8060 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8061 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8063 strncpy(name, molecule->name, max_len - 1);
8064 name[max_len - 1] = 0;
8066 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8068 return(TNG_FAILURE);
8070 return(TNG_SUCCESS);
8073 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8074 (tng_trajectory_t tng_data,
8075 tng_molecule_t molecule,
8076 const char *new_name)
8081 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8082 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8084 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8086 /* If the currently stored string length is not enough to store the new
8087 * string it is freed and reallocated. */
8088 if(molecule->name && strlen(molecule->name) < len)
8090 free(molecule->name);
8095 molecule->name = malloc(len);
8098 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8099 __FILE__, __LINE__);
8100 return(TNG_CRITICAL);
8104 strncpy(molecule->name, new_name, len);
8106 return(TNG_SUCCESS);
8109 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8110 (const tng_trajectory_t tng_data,
8111 const tng_molecule_t molecule,
8114 int64_t i, index = -1;
8116 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8117 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8119 for(i = 0; i < tng_data->n_molecules; i++)
8121 if(&tng_data->molecules[i] == molecule)
8129 return(TNG_FAILURE);
8131 *cnt = tng_data->molecule_cnt_list[index];
8133 return(TNG_SUCCESS);
8136 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8137 (tng_trajectory_t tng_data,
8138 tng_molecule_t molecule,
8141 int64_t i, old_cnt, index = -1;
8143 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8145 for(i = 0; i < tng_data->n_molecules; i++)
8147 if(&tng_data->molecules[i] == molecule)
8155 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8156 __FILE__, __LINE__);
8157 return(TNG_FAILURE);
8159 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8161 old_cnt = tng_data->molecule_cnt_list[index];
8162 tng_data->molecule_cnt_list[index] = cnt;
8164 tng_data->n_particles += (cnt-old_cnt) *
8165 tng_data->molecules[index].n_atoms;
8169 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8170 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8172 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8173 tng_data->molecules[index].n_atoms;
8176 return(TNG_SUCCESS);
8179 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8180 (tng_trajectory_t tng_data,
8183 tng_molecule_t *molecule)
8185 int64_t i, n_molecules;
8187 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8188 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8189 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8191 n_molecules = tng_data->n_molecules;
8193 for(i = n_molecules - 1; i >= 0; i--)
8195 *molecule = &tng_data->molecules[i];
8196 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8198 if(nr == -1 || nr == (*molecule)->id)
8200 return(TNG_SUCCESS);
8207 return(TNG_FAILURE);
8210 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8211 (tng_trajectory_t tng_data,
8213 tng_molecule_t *molecule)
8215 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8216 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8218 if(index >= tng_data->n_molecules)
8221 return(TNG_FAILURE);
8223 *molecule = &tng_data->molecules[index];
8224 return(TNG_SUCCESS);
8227 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8228 tng_trajectory_t tng_data_dest)
8230 tng_molecule_t molecule, molecule_temp;
8231 tng_chain_t chain, chain_temp;
8232 tng_residue_t residue, residue_temp;
8233 tng_atom_t atom, atom_temp;
8234 tng_bond_t bond_temp;
8235 tng_function_status stat;
8236 int64_t i, j, k, l, *list_temp;
8238 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8239 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8241 for(i = 0; i < tng_data_dest->n_molecules; i++)
8243 molecule = &tng_data_dest->molecules[i];
8244 tng_molecule_destroy(tng_data_dest, molecule);
8247 tng_data_dest->n_molecules = 0;
8248 tng_data_dest->n_particles = 0;
8250 molecule_temp = realloc(tng_data_dest->molecules,
8251 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8254 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8255 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8256 __FILE__, __LINE__);
8257 free(tng_data_dest->molecules);
8258 tng_data_dest->molecules = 0;
8259 return(TNG_CRITICAL);
8261 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8262 sizeof(int64_t) * tng_data_src->n_molecules);
8265 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8266 sizeof(int64_t) * tng_data_src->n_molecules,
8267 __FILE__, __LINE__);
8268 free(tng_data_dest->molecule_cnt_list);
8269 tng_data_dest->molecule_cnt_list = 0;
8270 free(molecule_temp);
8271 return(TNG_CRITICAL);
8274 tng_data_dest->molecules = molecule_temp;
8275 tng_data_dest->molecule_cnt_list = list_temp;
8277 for(i = 0; i < tng_data_src->n_molecules; i++)
8279 molecule = &tng_data_src->molecules[i];
8280 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8282 if(stat != TNG_SUCCESS)
8284 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8285 __FILE__, __LINE__);
8288 molecule_temp->quaternary_str = molecule->quaternary_str;
8289 for(j = 0; j < molecule->n_chains; j++)
8291 chain = &molecule->chains[j];
8292 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8293 chain->name, chain->id,
8295 if(stat != TNG_SUCCESS)
8297 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8298 __FILE__, __LINE__);
8301 for(k = 0; k < chain->n_residues; k++)
8303 residue = &chain->residues[k];
8304 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8305 residue->name, residue->id,
8307 if(stat != TNG_SUCCESS)
8309 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8310 __FILE__, __LINE__);
8313 for(l = 0; l < residue->n_atoms; l++)
8315 atom = &molecule->atoms[residue->atoms_offset + l];
8316 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8317 atom->name, atom->atom_type,
8318 atom->id, &atom_temp);
8319 if(stat != TNG_SUCCESS)
8321 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8322 __FILE__, __LINE__);
8328 molecule_temp->n_bonds = molecule->n_bonds;
8329 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8333 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8334 sizeof(struct tng_bond) * molecule->n_bonds,
8335 __FILE__, __LINE__);
8336 free(molecule_temp->bonds);
8337 molecule_temp->n_bonds = 0;
8338 return(TNG_CRITICAL);
8340 molecule_temp->bonds = bond_temp;
8341 for(j = 0; j < molecule->n_bonds; j++)
8343 molecule_temp->bonds[j] = molecule->bonds[j];
8345 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8346 tng_data_src->molecule_cnt_list[i]);
8347 if(stat != TNG_SUCCESS)
8349 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8350 __FILE__, __LINE__);
8354 return(TNG_SUCCESS);
8357 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8358 (const tng_trajectory_t tng_data,
8359 const tng_molecule_t molecule,
8363 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8364 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8366 *n = molecule->n_chains;
8368 return(TNG_SUCCESS);
8371 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8372 (tng_trajectory_t tng_data,
8373 tng_molecule_t molecule,
8378 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8379 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8381 if(index >= molecule->n_chains)
8384 return(TNG_FAILURE);
8386 *chain = &molecule->chains[index];
8387 return(TNG_SUCCESS);
8390 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8391 (const tng_trajectory_t tng_data,
8392 const tng_molecule_t molecule,
8396 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8397 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8399 *n = molecule->n_residues;
8401 return(TNG_SUCCESS);
8404 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8405 (const tng_trajectory_t tng_data,
8406 const tng_molecule_t molecule,
8407 const int64_t index,
8408 tng_residue_t *residue)
8411 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8412 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8414 if(index >= molecule->n_residues)
8417 return(TNG_FAILURE);
8419 *residue = &molecule->residues[index];
8420 return(TNG_SUCCESS);
8423 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8424 (const tng_trajectory_t tng_data,
8425 const tng_molecule_t molecule,
8429 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8430 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8432 *n = molecule->n_atoms;
8434 return(TNG_SUCCESS);
8437 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8438 (const tng_trajectory_t tng_data,
8439 const tng_molecule_t molecule,
8440 const int64_t index,
8444 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8445 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8447 if(index >= molecule->n_atoms)
8450 return(TNG_FAILURE);
8452 *atom = &molecule->atoms[index];
8453 return(TNG_SUCCESS);
8456 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8457 (tng_trajectory_t tng_data,
8458 tng_molecule_t molecule,
8463 int64_t i, n_chains;
8466 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8467 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8469 n_chains = molecule->n_chains;
8471 for(i = n_chains - 1; i >= 0; i--)
8473 *chain = &molecule->chains[i];
8474 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8476 if(nr == -1 || nr == (*chain)->id)
8478 return(TNG_SUCCESS);
8485 return(TNG_FAILURE);
8488 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8489 (tng_trajectory_t tng_data,
8490 tng_molecule_t molecule,
8496 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8497 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8499 /* Set ID to the ID of the last chain + 1 */
8500 if(molecule->n_chains)
8502 id = molecule->chains[molecule->n_chains-1].id + 1;
8509 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8513 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8514 (tng_trajectory_t tng_data,
8515 tng_molecule_t molecule,
8520 tng_chain_t new_chains;
8521 tng_function_status stat = TNG_SUCCESS;
8523 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8524 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8526 new_chains = realloc(molecule->chains,
8527 sizeof(struct tng_chain) *
8528 (molecule->n_chains + 1));
8532 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8533 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8534 __FILE__, __LINE__);
8535 free(molecule->chains);
8536 molecule->chains = 0;
8537 return(TNG_CRITICAL);
8540 molecule->chains = new_chains;
8542 *chain = &new_chains[molecule->n_chains];
8545 tng_chain_name_set(tng_data, *chain, name);
8547 (*chain)->molecule = molecule;
8548 (*chain)->n_residues = 0;
8550 molecule->n_chains++;
8557 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8558 (const tng_trajectory_t tng_data,
8559 tng_molecule_t molecule,
8560 const int64_t from_atom_id,
8561 const int64_t to_atom_id,
8564 tng_bond_t new_bonds;
8567 new_bonds = realloc(molecule->bonds,
8568 sizeof(struct tng_bond) *
8569 (molecule->n_bonds + 1));
8573 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8574 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8575 __FILE__, __LINE__);
8577 free(molecule->bonds);
8578 molecule->bonds = 0;
8579 return(TNG_CRITICAL);
8582 molecule->bonds = new_bonds;
8584 *bond = &new_bonds[molecule->n_bonds];
8586 (*bond)->from_atom_id = from_atom_id;
8587 (*bond)->to_atom_id = to_atom_id;
8589 molecule->n_bonds++;
8591 return(TNG_SUCCESS);
8594 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8595 (tng_trajectory_t tng_data,
8596 tng_molecule_t molecule,
8604 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8606 n_atoms = molecule->n_atoms;
8608 for(i = n_atoms - 1; i >= 0; i--)
8610 *atom = &molecule->atoms[i];
8611 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8613 if(id == -1 || id == (*atom)->id)
8615 return(TNG_SUCCESS);
8622 return(TNG_FAILURE);
8625 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8626 const tng_chain_t chain,
8631 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8632 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8634 strncpy(name, chain->name, max_len - 1);
8635 name[max_len - 1] = 0;
8637 if(strlen(chain->name) > (unsigned int)max_len - 1)
8639 return(TNG_FAILURE);
8641 return(TNG_SUCCESS);
8644 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8645 (tng_trajectory_t tng_data,
8647 const char *new_name)
8652 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8654 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8656 /* If the currently stored string length is not enough to store the new
8657 * string it is freed and reallocated. */
8658 if(chain->name && strlen(chain->name) < len)
8665 chain->name = malloc(len);
8668 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8669 __FILE__, __LINE__);
8670 return(TNG_CRITICAL);
8674 strncpy(chain->name, new_name, len);
8676 return(TNG_SUCCESS);
8679 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8680 (const tng_trajectory_t tng_data,
8681 const tng_chain_t chain,
8685 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8686 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8688 *n = chain->n_residues;
8690 return(TNG_SUCCESS);
8693 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8694 (const tng_trajectory_t tng_data,
8695 const tng_chain_t chain,
8696 const int64_t index,
8697 tng_residue_t *residue)
8700 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8701 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8703 if(index >= chain->n_residues)
8706 return(TNG_FAILURE);
8708 *residue = &chain->residues[index];
8709 return(TNG_SUCCESS);
8712 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8713 (tng_trajectory_t tng_data,
8717 tng_residue_t *residue)
8719 int64_t i, n_residues;
8722 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8724 n_residues = chain->n_residues;
8726 for(i = n_residues - 1; i >= 0; i--)
8728 *residue = &chain->residues[i];
8729 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8731 if(id == -1 || id == (*residue)->id)
8733 return(TNG_SUCCESS);
8740 return(TNG_FAILURE);
8743 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8744 (tng_trajectory_t tng_data,
8747 tng_residue_t *residue)
8751 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8752 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8754 /* Set ID to the ID of the last residue + 1 */
8755 if(chain->n_residues)
8757 id = chain->residues[chain->n_residues-1].id + 1;
8764 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8768 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8769 (tng_trajectory_t tng_data,
8773 tng_residue_t *residue)
8776 tng_residue_t new_residues, temp_residue, last_residue;
8777 tng_molecule_t molecule = chain->molecule;
8778 tng_function_status stat = TNG_SUCCESS;
8780 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8781 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8783 if(chain->n_residues)
8785 curr_index = chain->residues - molecule->residues;
8792 new_residues = realloc(molecule->residues,
8793 sizeof(struct tng_residue) *
8794 (molecule->n_residues + 1));
8798 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8799 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8800 __FILE__, __LINE__);
8801 free(molecule->residues);
8802 molecule->residues = 0;
8803 return(TNG_CRITICAL);
8806 molecule->residues = new_residues;
8808 if(curr_index != -1)
8810 chain->residues = new_residues + curr_index;
8811 if(molecule->n_residues)
8813 last_residue = &new_residues[molecule->n_residues - 1];
8815 temp_residue = chain->residues + (chain->n_residues - 1);
8816 /* Make space in list of residues to add the new residues together with the other
8817 * residues of this chain */
8818 if(temp_residue != last_residue)
8821 memmove(temp_residue + 1, temp_residue,
8822 last_residue - temp_residue);
8828 curr_index = molecule->n_residues;
8831 *residue = &molecule->residues[curr_index + chain->n_residues];
8833 if(!chain->n_residues)
8835 chain->residues = *residue;
8839 chain->residues = &molecule->residues[curr_index];
8842 (*residue)->name = 0;
8843 tng_residue_name_set(tng_data, *residue, name);
8845 (*residue)->chain = chain;
8846 (*residue)->n_atoms = 0;
8847 (*residue)->atoms_offset = 0;
8849 chain->n_residues++;
8850 molecule->n_residues++;
8852 (*residue)->id = id;
8857 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8858 const tng_residue_t residue,
8863 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8864 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8866 strncpy(name, residue->name, max_len - 1);
8867 name[max_len - 1] = 0;
8869 if(strlen(residue->name) > (unsigned int)max_len - 1)
8871 return(TNG_FAILURE);
8873 return(TNG_SUCCESS);
8876 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8877 tng_residue_t residue,
8878 const char *new_name)
8883 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8884 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8886 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8888 /* If the currently stored string length is not enough to store the new
8889 * string it is freed and reallocated. */
8890 if(residue->name && strlen(residue->name) < len)
8892 free(residue->name);
8897 residue->name = malloc(len);
8900 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8901 __FILE__, __LINE__);
8902 return(TNG_CRITICAL);
8906 strncpy(residue->name, new_name, len);
8908 return(TNG_SUCCESS);
8911 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8912 (const tng_trajectory_t tng_data,
8913 const tng_residue_t residue,
8917 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8918 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8920 *n = residue->n_atoms;
8922 return(TNG_SUCCESS);
8925 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8926 (const tng_trajectory_t tng_data,
8927 const tng_residue_t residue,
8928 const int64_t index,
8932 tng_molecule_t molecule;
8935 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8936 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8938 if(index >= residue->n_atoms)
8941 return(TNG_FAILURE);
8943 chain = residue->chain;
8944 molecule = chain->molecule;
8946 if(index + residue->atoms_offset >= molecule->n_atoms)
8949 return(TNG_FAILURE);
8952 *atom = &molecule->atoms[residue->atoms_offset + index];
8953 return(TNG_SUCCESS);
8956 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8957 (tng_trajectory_t tng_data,
8958 tng_residue_t residue,
8959 const char *atom_name,
8960 const char *atom_type,
8965 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8966 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8967 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8969 /* Set ID to the ID of the last atom + 1 */
8970 if(residue->chain->molecule->n_atoms)
8972 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
8979 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
8983 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
8984 (tng_trajectory_t tng_data,
8985 tng_residue_t residue,
8986 const char *atom_name,
8987 const char *atom_type,
8991 tng_atom_t new_atoms;
8992 tng_molecule_t molecule = residue->chain->molecule;
8993 tng_function_status stat = TNG_SUCCESS;
8995 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8996 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8997 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8999 if(!residue->n_atoms)
9001 residue->atoms_offset = molecule->n_atoms;
9004 new_atoms = realloc(molecule->atoms,
9005 sizeof(struct tng_atom) *
9006 (molecule->n_atoms + 1));
9010 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9011 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
9012 __FILE__, __LINE__);
9013 free(molecule->atoms);
9014 molecule->atoms = 0;
9015 return(TNG_CRITICAL);
9018 molecule->atoms = new_atoms;
9020 *atom = &new_atoms[molecule->n_atoms];
9022 tng_atom_init(*atom);
9023 tng_atom_name_set(tng_data, *atom, atom_name);
9024 tng_atom_type_set(tng_data, *atom, atom_type);
9026 (*atom)->residue = residue;
9029 molecule->n_atoms++;
9036 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
9037 tng_molecule_t *molecule_p)
9039 *molecule_p = malloc(sizeof(struct tng_molecule));
9042 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9043 sizeof(struct tng_molecule), __FILE__, __LINE__);
9044 return(TNG_CRITICAL);
9047 tng_molecule_init(tng_data, *molecule_p);
9049 return(TNG_SUCCESS);
9052 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9053 tng_molecule_t *molecule_p)
9057 return(TNG_SUCCESS);
9060 tng_molecule_destroy(tng_data, *molecule_p);
9065 return(TNG_SUCCESS);
9068 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9069 tng_molecule_t molecule)
9072 molecule->quaternary_str = 1;
9074 molecule->n_chains = 0;
9075 molecule->chains = 0;
9076 molecule->n_residues = 0;
9077 molecule->residues = 0;
9078 molecule->n_atoms = 0;
9079 molecule->atoms = 0;
9080 molecule->n_bonds = 0;
9081 molecule->bonds = 0;
9083 return(TNG_SUCCESS);
9086 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9087 tng_molecule_t molecule)
9094 free(molecule->name);
9098 if(molecule->chains)
9100 for(i = 0; i < molecule->n_chains; i++)
9102 if(molecule->chains[i].name)
9104 free(molecule->chains[i].name);
9105 molecule->chains[i].name = 0;
9108 free(molecule->chains);
9109 molecule->chains = 0;
9111 molecule->n_chains = 0;
9113 if(molecule->residues)
9115 for(i = 0; i < molecule->n_residues; i++)
9117 if(molecule->residues[i].name)
9119 free(molecule->residues[i].name);
9120 molecule->residues[i].name = 0;
9123 free(molecule->residues);
9124 molecule->residues = 0;
9126 molecule->n_residues = 0;
9130 for(i = 0; i < molecule->n_atoms; i++)
9132 tng_atom_destroy(&molecule->atoms[i]);
9134 free(molecule->atoms);
9135 molecule->atoms = 0;
9137 molecule->n_atoms = 0;
9141 free(molecule->bonds);
9142 molecule->bonds = 0;
9144 molecule->n_bonds = 0;
9146 return(TNG_SUCCESS);
9149 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9150 (const tng_trajectory_t tng_data,
9155 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9157 tng_bool found = TNG_FALSE;
9159 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9160 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9162 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9164 if(!molecule_cnt_list)
9166 return(TNG_FAILURE);
9169 for(i = 0; i < tng_data->n_molecules; i++)
9171 mol = &tng_data->molecules[i];
9172 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9174 cnt += mol->n_atoms * molecule_cnt_list[i];
9182 return(TNG_FAILURE);
9185 strncpy(name, mol->name, max_len - 1);
9186 name[max_len - 1] = 0;
9188 if(strlen(mol->name) > (unsigned int)max_len - 1)
9190 return(TNG_FAILURE);
9192 return(TNG_SUCCESS);
9195 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9196 (const tng_trajectory_t tng_data,
9200 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9202 tng_bool found = TNG_FALSE;
9204 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9205 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9207 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9209 if(!molecule_cnt_list)
9211 return(TNG_FAILURE);
9214 for(i = 0; i < tng_data->n_molecules; i++)
9216 mol = &tng_data->molecules[i];
9217 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9219 cnt += mol->n_atoms * molecule_cnt_list[i];
9227 return(TNG_FAILURE);
9232 return(TNG_SUCCESS);
9235 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9236 (const tng_trajectory_t tng_data,
9238 int64_t **from_atoms,
9241 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9242 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9246 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9247 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9248 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9249 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9251 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9253 if(!molecule_cnt_list)
9255 return(TNG_FAILURE);
9259 /* First count the total number of bonds to allocate memory */
9260 for(i = 0; i < tng_data->n_molecules; i++)
9262 mol = &tng_data->molecules[i];
9263 mol_cnt = molecule_cnt_list[i];
9264 *n_bonds += mol_cnt * mol->n_bonds;
9268 return(TNG_SUCCESS);
9271 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9274 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9275 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9276 return(TNG_CRITICAL);
9278 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9281 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9282 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9285 return(TNG_CRITICAL);
9289 for(i = 0; i < tng_data->n_molecules; i++)
9291 mol = &tng_data->molecules[i];
9292 mol_cnt = molecule_cnt_list[i];
9293 for(j = 0; j < mol_cnt; j++)
9295 for(k = 0; k < mol->n_bonds; k++)
9297 bond = &mol->bonds[k];
9298 from_atom = atom_cnt + bond->from_atom_id;
9299 to_atom = atom_cnt + bond->to_atom_id;
9300 (*from_atoms)[cnt] = from_atom;
9301 (*to_atoms)[cnt++] = to_atom;
9303 atom_cnt += mol->n_atoms;
9307 return(TNG_SUCCESS);
9310 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9311 (const tng_trajectory_t tng_data,
9316 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9319 tng_bool found = TNG_FALSE;
9321 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9322 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9324 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9326 if(!molecule_cnt_list)
9328 return(TNG_FAILURE);
9331 for(i = 0; i < tng_data->n_molecules; i++)
9333 mol = &tng_data->molecules[i];
9334 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9336 cnt += mol->n_atoms * molecule_cnt_list[i];
9339 atom = &mol->atoms[nr % mol->n_atoms];
9345 return(TNG_FAILURE);
9347 if(!atom->residue || !atom->residue->chain)
9349 return(TNG_FAILURE);
9352 strncpy(name, atom->residue->chain->name, max_len - 1);
9353 name[max_len - 1] = 0;
9355 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9357 return(TNG_FAILURE);
9359 return(TNG_SUCCESS);
9362 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9363 (const tng_trajectory_t tng_data,
9368 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9371 tng_bool found = TNG_FALSE;
9373 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9374 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9376 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9378 if(!molecule_cnt_list)
9380 return(TNG_FAILURE);
9383 for(i = 0; i < tng_data->n_molecules; i++)
9385 mol = &tng_data->molecules[i];
9386 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9388 cnt += mol->n_atoms * molecule_cnt_list[i];
9391 atom = &mol->atoms[nr % mol->n_atoms];
9397 return(TNG_FAILURE);
9401 return(TNG_FAILURE);
9404 strncpy(name, atom->residue->name, max_len - 1);
9405 name[max_len - 1] = 0;
9407 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9409 return(TNG_FAILURE);
9411 return(TNG_SUCCESS);
9414 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9415 (const tng_trajectory_t tng_data,
9419 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9422 tng_bool found = TNG_FALSE;
9424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9425 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9427 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9429 if(!molecule_cnt_list)
9431 return(TNG_FAILURE);
9434 for(i = 0; i < tng_data->n_molecules; i++)
9436 mol = &tng_data->molecules[i];
9437 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9439 cnt += mol->n_atoms * molecule_cnt_list[i];
9442 atom = &mol->atoms[nr % mol->n_atoms];
9448 return(TNG_FAILURE);
9452 return(TNG_FAILURE);
9455 *id = atom->residue->id;
9457 return(TNG_SUCCESS);
9460 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9461 (const tng_trajectory_t tng_data,
9465 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9468 tng_bool found = TNG_FALSE;
9470 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9471 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9473 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9475 if(!molecule_cnt_list)
9477 return(TNG_FAILURE);
9480 for(i = 0; i < tng_data->n_molecules; i++)
9482 mol = &tng_data->molecules[i];
9483 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9485 cnt += mol->n_atoms * molecule_cnt_list[i];
9486 offset += mol->n_residues * molecule_cnt_list[i];
9489 atom = &mol->atoms[nr % mol->n_atoms];
9495 return(TNG_FAILURE);
9499 return(TNG_FAILURE);
9502 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9504 *id = atom->residue->id + offset;
9506 return(TNG_SUCCESS);
9509 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9510 (const tng_trajectory_t tng_data,
9515 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9518 tng_bool found = TNG_FALSE;
9520 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9521 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9523 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9525 if(!molecule_cnt_list)
9527 return(TNG_FAILURE);
9530 for(i = 0; i < tng_data->n_molecules; i++)
9532 mol = &tng_data->molecules[i];
9533 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9535 cnt += mol->n_atoms * molecule_cnt_list[i];
9538 atom = &mol->atoms[nr % mol->n_atoms];
9544 return(TNG_FAILURE);
9547 strncpy(name, atom->name, max_len - 1);
9548 name[max_len - 1] = 0;
9550 if(strlen(atom->name) > (unsigned int)max_len - 1)
9552 return(TNG_FAILURE);
9554 return(TNG_SUCCESS);
9557 tng_function_status tng_atom_type_of_particle_nr_get
9558 (const tng_trajectory_t tng_data,
9563 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9566 tng_bool found = TNG_FALSE;
9568 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9569 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9571 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9573 if(!molecule_cnt_list)
9575 return(TNG_FAILURE);
9578 for(i = 0; i < tng_data->n_molecules; i++)
9580 mol = &tng_data->molecules[i];
9581 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9583 cnt += mol->n_atoms * molecule_cnt_list[i];
9586 atom = &mol->atoms[nr % mol->n_atoms];
9592 return(TNG_FAILURE);
9595 strncpy(type, atom->atom_type, max_len - 1);
9596 type[max_len - 1] = 0;
9598 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9600 return(TNG_FAILURE);
9602 return(TNG_SUCCESS);
9605 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9606 (tng_trajectory_t tng_data,
9607 const int64_t num_first_particle,
9608 const int64_t n_particles,
9609 const int64_t *mapping_table)
9612 tng_particle_mapping_t mapping;
9613 tng_trajectory_frame_set_t frame_set;
9615 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9617 frame_set = &tng_data->current_trajectory_frame_set;
9619 /* Sanity check of the particle ranges. Split into multiple if
9620 * statements for improved readability */
9621 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9623 mapping = &frame_set->mappings[i];
9624 if(num_first_particle >= mapping->num_first_particle &&
9625 num_first_particle < mapping->num_first_particle +
9626 mapping->n_particles)
9628 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9629 return(TNG_FAILURE);
9631 if(num_first_particle + n_particles >=
9632 mapping->num_first_particle &&
9633 num_first_particle + n_particles <
9634 mapping->num_first_particle + mapping->n_particles)
9636 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9637 return(TNG_FAILURE);
9639 if(mapping->num_first_particle >= num_first_particle &&
9640 mapping->num_first_particle < num_first_particle +
9643 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9644 return(TNG_FAILURE);
9646 if(mapping->num_first_particle + mapping->n_particles >
9647 num_first_particle &&
9648 mapping->num_first_particle + mapping->n_particles <
9649 num_first_particle + n_particles)
9651 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9652 return(TNG_FAILURE);
9656 frame_set->n_mapping_blocks++;
9658 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9659 frame_set->n_mapping_blocks);
9663 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9664 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9665 __FILE__, __LINE__);
9666 free(frame_set->mappings);
9667 frame_set->mappings = 0;
9668 return(TNG_CRITICAL);
9670 frame_set->mappings = mapping;
9672 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9673 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9675 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9676 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9678 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9679 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9680 return(TNG_CRITICAL);
9683 for(i=0; i<n_particles; i++)
9685 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9688 return(TNG_SUCCESS);
9691 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9693 tng_trajectory_frame_set_t frame_set;
9694 tng_particle_mapping_t mapping;
9697 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9699 frame_set = &tng_data->current_trajectory_frame_set;
9701 if(frame_set->n_mapping_blocks && frame_set->mappings)
9703 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9705 mapping = &frame_set->mappings[i];
9706 if(mapping->real_particle_numbers)
9708 free(mapping->real_particle_numbers);
9709 mapping->real_particle_numbers = 0;
9712 free(frame_set->mappings);
9713 frame_set->mappings = 0;
9714 frame_set->n_mapping_blocks = 0;
9717 return(TNG_SUCCESS);
9720 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9723 tng_trajectory_frame_set_t frame_set;
9724 tng_trajectory_t tng_data;
9726 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9729 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9730 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9731 return(TNG_CRITICAL);
9734 tng_data = *tng_data_p;
9736 frame_set = &tng_data->current_trajectory_frame_set;
9738 tng_data->input_file_path = 0;
9739 tng_data->input_file = 0;
9740 tng_data->input_file_len = 0;
9741 tng_data->output_file_path = 0;
9742 tng_data->output_file = 0;
9744 tng_data->first_program_name = 0;
9745 tng_data->first_user_name = 0;
9746 tng_data->first_computer_name = 0;
9747 tng_data->first_pgp_signature = 0;
9748 tng_data->last_program_name = 0;
9749 tng_data->last_user_name = 0;
9750 tng_data->last_computer_name = 0;
9751 tng_data->last_pgp_signature = 0;
9752 tng_data->forcefield_name = 0;
9757 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9761 tng_data->time = seconds;
9764 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9765 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9766 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9767 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9768 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9769 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9770 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9771 tng_data->frame_set_n_frames = 100;
9772 tng_data->n_trajectory_frame_sets = 0;
9773 tng_data->medium_stride_length = 100;
9774 tng_data->long_stride_length = 10000;
9776 tng_data->time_per_frame = -1;
9778 tng_data->n_particle_data_blocks = 0;
9779 tng_data->n_data_blocks = 0;
9781 tng_data->non_tr_particle_data = 0;
9782 tng_data->non_tr_data = 0;
9784 tng_data->compress_algo_pos = 0;
9785 tng_data->compress_algo_vel = 0;
9786 tng_data->compression_precision = 1000;
9787 tng_data->distance_unit_exponential = -9;
9789 frame_set->first_frame = -1;
9790 frame_set->n_mapping_blocks = 0;
9791 frame_set->mappings = 0;
9792 frame_set->molecule_cnt_list = 0;
9794 frame_set->n_particle_data_blocks = 0;
9795 frame_set->n_data_blocks = 0;
9797 frame_set->tr_particle_data = 0;
9798 frame_set->tr_data = 0;
9800 frame_set->n_written_frames = 0;
9801 frame_set->n_unwritten_frames = 0;
9803 frame_set->next_frame_set_file_pos = -1;
9804 frame_set->prev_frame_set_file_pos = -1;
9805 frame_set->medium_stride_next_frame_set_file_pos = -1;
9806 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9807 frame_set->long_stride_next_frame_set_file_pos = -1;
9808 frame_set->long_stride_prev_frame_set_file_pos = -1;
9810 frame_set->first_frame_time = -1;
9812 tng_data->n_molecules = 0;
9813 tng_data->molecules = 0;
9814 tng_data->molecule_cnt_list = 0;
9815 tng_data->n_particles = 0;
9818 /* Check the endianness of the computer */
9819 static int32_t endianness_32 = 0x01234567;
9821 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9823 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9827 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9829 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9834 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9836 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9840 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9841 /* 0x0123456789ABCDEF */
9842 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9844 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9847 /* 0xEFCDAB8967452301 */
9848 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9850 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9853 /* 0x89ABCDEF01234567 */
9854 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9856 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9859 /* 0x45670123CDEF89AB */
9860 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9862 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9865 /* 0x23016745AB89EFCD */
9866 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9868 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9872 /* By default do not swap the byte order, i.e. keep the byte order of the
9873 * architecture. The input file endianness will be set when reading the
9874 * header. The output endianness can be changed - before the file is
9876 tng_data->input_endianness_swap_func_32 = 0;
9877 tng_data->input_endianness_swap_func_64 = 0;
9878 tng_data->output_endianness_swap_func_32 = 0;
9879 tng_data->output_endianness_swap_func_64 = 0;
9881 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9882 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9883 tng_data->current_trajectory_frame_set.n_frames = 0;
9885 return(TNG_SUCCESS);
9888 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9891 int64_t n_particles, n_values_per_frame;
9892 tng_trajectory_t tng_data = *tng_data_p;
9893 tng_trajectory_frame_set_t frame_set;
9897 return(TNG_SUCCESS);
9900 frame_set = &tng_data->current_trajectory_frame_set;
9902 if(tng_data->input_file_path)
9904 free(tng_data->input_file_path);
9905 tng_data->input_file_path = 0;
9908 if(tng_data->input_file)
9910 if(tng_data->output_file == tng_data->input_file)
9912 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9913 tng_data->output_file = 0;
9915 fclose(tng_data->input_file);
9916 tng_data->input_file = 0;
9919 if(tng_data->output_file_path)
9921 free(tng_data->output_file_path);
9922 tng_data->output_file_path = 0;
9925 if(tng_data->output_file)
9927 /* FIXME: Do not always write the hash */
9928 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9929 fclose(tng_data->output_file);
9930 tng_data->output_file = 0;
9933 if(tng_data->first_program_name)
9935 free(tng_data->first_program_name);
9936 tng_data->first_program_name = 0;
9939 if(tng_data->last_program_name)
9941 free(tng_data->last_program_name);
9942 tng_data->last_program_name = 0;
9945 if(tng_data->first_user_name)
9947 free(tng_data->first_user_name);
9948 tng_data->first_user_name = 0;
9951 if(tng_data->last_user_name)
9953 free(tng_data->last_user_name);
9954 tng_data->last_user_name = 0;
9957 if(tng_data->first_computer_name)
9959 free(tng_data->first_computer_name);
9960 tng_data->first_computer_name = 0;
9963 if(tng_data->last_computer_name)
9965 free(tng_data->last_computer_name);
9966 tng_data->last_computer_name = 0;
9969 if(tng_data->first_pgp_signature)
9971 free(tng_data->first_pgp_signature);
9972 tng_data->first_pgp_signature = 0;
9975 if(tng_data->last_pgp_signature)
9977 free(tng_data->last_pgp_signature);
9978 tng_data->last_pgp_signature = 0;
9981 if(tng_data->forcefield_name)
9983 free(tng_data->forcefield_name);
9984 tng_data->forcefield_name = 0;
9987 tng_frame_set_particle_mapping_free(tng_data);
9989 if(frame_set->molecule_cnt_list)
9991 free(frame_set->molecule_cnt_list);
9992 frame_set->molecule_cnt_list = 0;
9995 if(tng_data->var_num_atoms_flag)
9997 n_particles = frame_set->n_particles;
10001 n_particles = tng_data->n_particles;
10004 if(tng_data->non_tr_particle_data)
10006 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
10008 if(tng_data->non_tr_particle_data[i].values)
10010 free(tng_data->non_tr_particle_data[i].values);
10011 tng_data->non_tr_particle_data[i].values = 0;
10014 if(tng_data->non_tr_particle_data[i].strings)
10016 n_values_per_frame = tng_data->non_tr_particle_data[i].
10017 n_values_per_frame;
10018 if(tng_data->non_tr_particle_data[i].strings[0])
10020 for(j = 0; j < n_particles; j++)
10022 if(tng_data->non_tr_particle_data[i].strings[0][j])
10024 for(k = 0; k < n_values_per_frame; k++)
10026 if(tng_data->non_tr_particle_data[i].
10029 free(tng_data->non_tr_particle_data[i].
10031 tng_data->non_tr_particle_data[i].
10032 strings[0][j][k] = 0;
10035 free(tng_data->non_tr_particle_data[i].
10037 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
10040 free(tng_data->non_tr_particle_data[i].strings[0]);
10041 tng_data->non_tr_particle_data[i].strings[0] = 0;
10043 free(tng_data->non_tr_particle_data[i].strings);
10044 tng_data->non_tr_particle_data[i].strings = 0;
10047 if(tng_data->non_tr_particle_data[i].block_name)
10049 free(tng_data->non_tr_particle_data[i].block_name);
10050 tng_data->non_tr_particle_data[i].block_name = 0;
10053 free(tng_data->non_tr_particle_data);
10054 tng_data->non_tr_particle_data = 0;
10057 if(tng_data->non_tr_data)
10059 for(i = 0; i < tng_data->n_data_blocks; i++)
10061 if(tng_data->non_tr_data[i].values)
10063 free(tng_data->non_tr_data[i].values);
10064 tng_data->non_tr_data[i].values = 0;
10067 if(tng_data->non_tr_data[i].strings)
10069 n_values_per_frame = tng_data->non_tr_data[i].
10070 n_values_per_frame;
10071 if(tng_data->non_tr_data[i].strings[0])
10073 for(j = 0; j < n_values_per_frame; j++)
10075 if(tng_data->non_tr_data[i].strings[0][j])
10077 free(tng_data->non_tr_data[i].strings[0][j]);
10078 tng_data->non_tr_data[i].strings[0][j] = 0;
10081 free(tng_data->non_tr_data[i].strings[0]);
10082 tng_data->non_tr_data[i].strings[0] = 0;
10084 free(tng_data->non_tr_data[i].strings);
10085 tng_data->non_tr_data[i].strings = 0;
10088 if(tng_data->non_tr_data[i].block_name)
10090 free(tng_data->non_tr_data[i].block_name);
10091 tng_data->non_tr_data[i].block_name = 0;
10094 free(tng_data->non_tr_data);
10095 tng_data->non_tr_data = 0;
10098 tng_data->n_particle_data_blocks = 0;
10099 tng_data->n_data_blocks = 0;
10101 if(tng_data->compress_algo_pos)
10103 free(tng_data->compress_algo_pos);
10104 tng_data->compress_algo_pos = 0;
10106 if(tng_data->compress_algo_vel)
10108 free(tng_data->compress_algo_vel);
10109 tng_data->compress_algo_vel = 0;
10112 if(frame_set->tr_particle_data)
10114 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10116 if(frame_set->tr_particle_data[i].values)
10118 free(frame_set->tr_particle_data[i].values);
10119 frame_set->tr_particle_data[i].values = 0;
10122 if(frame_set->tr_particle_data[i].strings)
10124 n_values_per_frame = frame_set->tr_particle_data[i].
10125 n_values_per_frame;
10126 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10128 if(frame_set->tr_particle_data[i].strings[j])
10130 for(k = 0; k < n_particles; k++)
10132 if(frame_set->tr_particle_data[i].
10135 for(l = 0; l < n_values_per_frame; l++)
10137 if(frame_set->tr_particle_data[i].
10140 free(frame_set->tr_particle_data[i].
10142 frame_set->tr_particle_data[i].
10143 strings[j][k][l] = 0;
10146 free(frame_set->tr_particle_data[i].
10148 frame_set->tr_particle_data[i].
10152 free(frame_set->tr_particle_data[i].strings[j]);
10153 frame_set->tr_particle_data[i].strings[j] = 0;
10156 free(frame_set->tr_particle_data[i].strings);
10157 frame_set->tr_particle_data[i].strings = 0;
10160 if(frame_set->tr_particle_data[i].block_name)
10162 free(frame_set->tr_particle_data[i].block_name);
10163 frame_set->tr_particle_data[i].block_name = 0;
10166 free(frame_set->tr_particle_data);
10167 frame_set->tr_particle_data = 0;
10170 if(frame_set->tr_data)
10172 for(i = 0; i < frame_set->n_data_blocks; i++)
10174 if(frame_set->tr_data[i].values)
10176 free(frame_set->tr_data[i].values);
10177 frame_set->tr_data[i].values = 0;
10180 if(frame_set->tr_data[i].strings)
10182 n_values_per_frame = frame_set->tr_data[i].
10183 n_values_per_frame;
10184 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10186 if(frame_set->tr_data[i].strings[j])
10188 for(k = 0; k < n_values_per_frame; k++)
10190 if(frame_set->tr_data[i].strings[j][k])
10192 free(frame_set->tr_data[i].strings[j][k]);
10193 frame_set->tr_data[i].strings[j][k] = 0;
10196 free(frame_set->tr_data[i].strings[j]);
10197 frame_set->tr_data[i].strings[j] = 0;
10200 free(frame_set->tr_data[i].strings);
10201 frame_set->tr_data[i].strings = 0;
10204 if(frame_set->tr_data[i].block_name)
10206 free(frame_set->tr_data[i].block_name);
10207 frame_set->tr_data[i].block_name = 0;
10210 free(frame_set->tr_data);
10211 frame_set->tr_data = 0;
10214 frame_set->n_particle_data_blocks = 0;
10215 frame_set->n_data_blocks = 0;
10217 if(tng_data->molecules)
10219 for(i = 0; i < tng_data->n_molecules; i++)
10221 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10223 free(tng_data->molecules);
10224 tng_data->molecules = 0;
10225 tng_data->n_molecules = 0;
10227 if(tng_data->molecule_cnt_list)
10229 free(tng_data->molecule_cnt_list);
10230 tng_data->molecule_cnt_list = 0;
10236 return(TNG_SUCCESS);
10239 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10240 tng_trajectory_t *dest_p)
10242 tng_trajectory_frame_set_t frame_set;
10243 tng_trajectory_t dest;
10245 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10247 *dest_p = malloc(sizeof(struct tng_trajectory));
10250 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10251 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10252 return(TNG_CRITICAL);
10257 frame_set = &dest->current_trajectory_frame_set;
10259 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10260 if(!dest->input_file_path)
10262 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10263 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10264 return(TNG_CRITICAL);
10266 strcpy(dest->input_file_path, src->input_file_path);
10267 dest->input_file = 0;
10268 dest->input_file_len = src->input_file_len;
10269 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10270 if(!dest->output_file_path)
10272 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10273 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10274 return(TNG_CRITICAL);
10276 strcpy(dest->output_file_path, src->output_file_path);
10277 dest->output_file = 0;
10279 dest->first_program_name = 0;
10280 dest->first_user_name = 0;
10281 dest->first_computer_name = 0;
10282 dest->first_pgp_signature = 0;
10283 dest->last_program_name = 0;
10284 dest->last_user_name = 0;
10285 dest->last_computer_name = 0;
10286 dest->last_pgp_signature = 0;
10287 dest->forcefield_name = 0;
10289 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10290 dest->first_trajectory_frame_set_input_file_pos =
10291 src->first_trajectory_frame_set_input_file_pos;
10292 dest->last_trajectory_frame_set_input_file_pos =
10293 src->last_trajectory_frame_set_input_file_pos;
10294 dest->current_trajectory_frame_set_input_file_pos =
10295 src->current_trajectory_frame_set_input_file_pos;
10296 dest->first_trajectory_frame_set_output_file_pos =
10297 src->first_trajectory_frame_set_output_file_pos;
10298 dest->last_trajectory_frame_set_output_file_pos =
10299 src->last_trajectory_frame_set_output_file_pos;
10300 dest->current_trajectory_frame_set_output_file_pos =
10301 src->current_trajectory_frame_set_output_file_pos;
10302 dest->frame_set_n_frames = src->frame_set_n_frames;
10303 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10304 dest->medium_stride_length = src->medium_stride_length;
10305 dest->long_stride_length = src->long_stride_length;
10307 dest->time_per_frame = src->time_per_frame;
10309 /* Currently the non trajectory data blocks are not copied since it
10310 * can lead to problems when freeing memory in a parallel block. */
10311 dest->n_particle_data_blocks = 0;
10312 dest->n_data_blocks = 0;
10313 dest->non_tr_particle_data = 0;
10314 dest->non_tr_data = 0;
10316 dest->compress_algo_pos = 0;
10317 dest->compress_algo_vel = 0;
10318 dest->distance_unit_exponential = -9;
10319 dest->compression_precision = 1000;
10321 frame_set->n_mapping_blocks = 0;
10322 frame_set->mappings = 0;
10323 frame_set->molecule_cnt_list = 0;
10325 frame_set->n_particle_data_blocks = 0;
10326 frame_set->n_data_blocks = 0;
10328 frame_set->tr_particle_data = 0;
10329 frame_set->tr_data = 0;
10331 frame_set->next_frame_set_file_pos = -1;
10332 frame_set->prev_frame_set_file_pos = -1;
10333 frame_set->medium_stride_next_frame_set_file_pos = -1;
10334 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10335 frame_set->long_stride_next_frame_set_file_pos = -1;
10336 frame_set->long_stride_prev_frame_set_file_pos = -1;
10337 frame_set->first_frame = -1;
10339 dest->n_molecules = 0;
10340 dest->molecules = 0;
10341 dest->molecule_cnt_list = 0;
10342 dest->n_particles = src->n_particles;
10344 dest->endianness_32 = src->endianness_32;
10345 dest->endianness_64 = src->endianness_64;
10346 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10347 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10348 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10349 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10351 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10352 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10353 dest->current_trajectory_frame_set.n_frames = 0;
10355 return(TNG_SUCCESS);
10358 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10359 char *file_name, const int max_len)
10361 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10362 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10364 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10365 file_name[max_len - 1] = 0;
10367 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10369 return(TNG_FAILURE);
10371 return(TNG_SUCCESS);
10374 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10375 const char *file_name)
10380 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10381 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10384 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10387 return(TNG_SUCCESS);
10390 if(tng_data->input_file)
10392 fclose(tng_data->input_file);
10395 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10396 temp = realloc(tng_data->input_file_path, len);
10399 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10400 __FILE__, __LINE__);
10401 free(tng_data->input_file_path);
10402 tng_data->input_file_path = 0;
10403 return(TNG_CRITICAL);
10405 tng_data->input_file_path = temp;
10407 strncpy(tng_data->input_file_path, file_name, len);
10409 return(tng_input_file_init(tng_data));
10412 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10413 char *file_name, const int max_len)
10415 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10416 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10418 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10419 file_name[max_len - 1] = 0;
10421 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10423 return(TNG_FAILURE);
10425 return(TNG_SUCCESS);
10428 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10429 const char *file_name)
10434 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10435 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10437 if(tng_data->output_file_path &&
10438 strcmp(tng_data->output_file_path, file_name) == 0)
10440 return(TNG_SUCCESS);
10443 if(tng_data->output_file)
10445 fclose(tng_data->output_file);
10448 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10449 temp = realloc(tng_data->output_file_path, len);
10452 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10453 __FILE__, __LINE__);
10454 free(tng_data->output_file_path);
10455 tng_data->output_file_path = 0;
10456 return(TNG_CRITICAL);
10458 tng_data->output_file_path = temp;
10460 strncpy(tng_data->output_file_path, file_name, len);
10462 return(tng_output_file_init(tng_data));
10465 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10466 (tng_trajectory_t tng_data,
10467 const char *file_name)
10472 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10473 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10475 if(tng_data->output_file_path &&
10476 strcmp(tng_data->output_file_path, file_name) == 0)
10478 return(TNG_SUCCESS);
10481 if(tng_data->output_file)
10483 fclose(tng_data->output_file);
10486 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10487 temp = realloc(tng_data->output_file_path, len);
10490 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10491 __FILE__, __LINE__);
10492 free(tng_data->output_file_path);
10493 tng_data->output_file_path = 0;
10494 return(TNG_CRITICAL);
10496 tng_data->output_file_path = temp;
10498 strncpy(tng_data->output_file_path, file_name, len);
10500 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10501 if(!tng_data->output_file)
10503 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10504 tng_data->output_file_path, __FILE__, __LINE__);
10505 return(TNG_CRITICAL);
10507 tng_data->input_file = tng_data->output_file;
10509 return(TNG_SUCCESS);
10512 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10513 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10515 tng_endianness_32 end_32;
10516 tng_endianness_64 end_64;
10518 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10519 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10521 if(tng_data->output_endianness_swap_func_32)
10523 /* If other endianness variants are added they must be added here as well */
10524 if(tng_data->output_endianness_swap_func_32 ==
10525 &tng_swap_byte_order_big_endian_32)
10527 end_32 = TNG_BIG_ENDIAN_32;
10529 else if(tng_data->output_endianness_swap_func_32 ==
10530 &tng_swap_byte_order_little_endian_32)
10532 end_32 = TNG_LITTLE_ENDIAN_32;
10536 return(TNG_FAILURE);
10541 end_32 = (tng_endianness_32)tng_data->endianness_32;
10544 if(tng_data->output_endianness_swap_func_64)
10546 /* If other endianness variants are added they must be added here as well */
10547 if(tng_data->output_endianness_swap_func_64 ==
10548 &tng_swap_byte_order_big_endian_64)
10550 end_64 = TNG_BIG_ENDIAN_64;
10552 else if(tng_data->output_endianness_swap_func_64 ==
10553 &tng_swap_byte_order_little_endian_64)
10555 end_64 = TNG_LITTLE_ENDIAN_64;
10559 return(TNG_FAILURE);
10564 end_64 = (tng_endianness_64)tng_data->endianness_64;
10567 if((int)end_32 != (int)end_64)
10569 return(TNG_FAILURE);
10572 if(end_32 == TNG_LITTLE_ENDIAN_32)
10574 *endianness = TNG_LITTLE_ENDIAN;
10577 else if(end_32 == TNG_BIG_ENDIAN_32)
10579 *endianness = TNG_BIG_ENDIAN;
10583 return(TNG_FAILURE);
10586 return(TNG_SUCCESS);
10589 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10590 (tng_trajectory_t tng_data,
10591 const tng_file_endianness endianness)
10593 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10595 /* Tne endianness cannot be changed if the data has already been written
10596 * to the output file. */
10597 if(ftell(tng_data->output_file) > 0)
10599 return(TNG_FAILURE);
10602 if(endianness == TNG_BIG_ENDIAN)
10604 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10606 tng_data->output_endianness_swap_func_32 = 0;
10610 tng_data->output_endianness_swap_func_32 =
10611 &tng_swap_byte_order_big_endian_32;
10613 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10615 tng_data->output_endianness_swap_func_64 = 0;
10619 tng_data->output_endianness_swap_func_64 =
10620 &tng_swap_byte_order_big_endian_64;
10622 return(TNG_SUCCESS);
10624 else if(endianness == TNG_LITTLE_ENDIAN)
10626 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10628 tng_data->output_endianness_swap_func_32 = 0;
10632 tng_data->output_endianness_swap_func_32 =
10633 &tng_swap_byte_order_little_endian_32;
10635 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10637 tng_data->output_endianness_swap_func_64 = 0;
10641 tng_data->output_endianness_swap_func_64 =
10642 &tng_swap_byte_order_little_endian_64;
10644 return(TNG_SUCCESS);
10647 /* If the specified endianness is neither big nor little endian return a
10649 return(TNG_FAILURE);
10652 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10653 (const tng_trajectory_t tng_data,
10654 char *name, const int max_len)
10656 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10657 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10659 strncpy(name, tng_data->first_program_name, max_len - 1);
10660 name[max_len - 1] = 0;
10662 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10664 return(TNG_FAILURE);
10666 return(TNG_SUCCESS);
10669 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10670 const char *new_name)
10674 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10675 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10677 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10679 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10681 free(tng_data->first_program_name);
10682 tng_data->first_program_name = 0;
10684 if(!tng_data->first_program_name)
10686 tng_data->first_program_name = malloc(len);
10687 if(!tng_data->first_program_name)
10689 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10690 __FILE__, __LINE__);
10691 return(TNG_CRITICAL);
10695 strncpy(tng_data->first_program_name, new_name, len);
10697 return(TNG_SUCCESS);
10700 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10701 (const tng_trajectory_t tng_data,
10702 char *name, const int max_len)
10704 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10705 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10707 strncpy(name, tng_data->last_program_name, max_len - 1);
10708 name[max_len - 1] = 0;
10710 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10712 return(TNG_FAILURE);
10714 return(TNG_SUCCESS);
10717 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10718 (tng_trajectory_t tng_data,
10719 const char *new_name)
10723 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10724 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10726 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10728 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10730 free(tng_data->last_program_name);
10731 tng_data->last_program_name = 0;
10733 if(!tng_data->last_program_name)
10735 tng_data->last_program_name = malloc(len);
10736 if(!tng_data->last_program_name)
10738 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10739 __FILE__, __LINE__);
10740 return(TNG_CRITICAL);
10744 strncpy(tng_data->last_program_name, new_name, len);
10746 return(TNG_SUCCESS);
10749 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10750 (const tng_trajectory_t tng_data,
10751 char *name, const int max_len)
10753 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10754 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10756 strncpy(name, tng_data->first_user_name, max_len - 1);
10757 name[max_len - 1] = 0;
10759 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10761 return(TNG_FAILURE);
10763 return(TNG_SUCCESS);
10766 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10767 (tng_trajectory_t tng_data,
10768 const char *new_name)
10772 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10773 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10775 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10777 /* If the currently stored string length is not enough to store the new
10778 * string it is freed and reallocated. */
10779 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10781 free(tng_data->first_user_name);
10782 tng_data->first_user_name = 0;
10784 if(!tng_data->first_user_name)
10786 tng_data->first_user_name = malloc(len);
10787 if(!tng_data->first_user_name)
10789 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10790 __FILE__, __LINE__);
10791 return(TNG_CRITICAL);
10795 strncpy(tng_data->first_user_name, new_name, len);
10797 return(TNG_SUCCESS);
10800 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10801 (const tng_trajectory_t tng_data,
10802 char *name, const int max_len)
10804 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10805 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10807 strncpy(name, tng_data->last_user_name, max_len - 1);
10808 name[max_len - 1] = 0;
10810 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10812 return(TNG_FAILURE);
10814 return(TNG_SUCCESS);
10817 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10818 (tng_trajectory_t tng_data,
10819 const char *new_name)
10823 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10824 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10826 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10828 /* If the currently stored string length is not enough to store the new
10829 * string it is freed and reallocated. */
10830 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10832 free(tng_data->last_user_name);
10833 tng_data->last_user_name = 0;
10835 if(!tng_data->last_user_name)
10837 tng_data->last_user_name = malloc(len);
10838 if(!tng_data->last_user_name)
10840 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10841 __FILE__, __LINE__);
10842 return(TNG_CRITICAL);
10846 strncpy(tng_data->last_user_name, new_name, len);
10848 return(TNG_SUCCESS);
10851 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10852 (const tng_trajectory_t tng_data,
10853 char *name, const int max_len)
10855 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10856 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10858 strncpy(name, tng_data->first_computer_name, max_len - 1);
10859 name[max_len - 1] = 0;
10861 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10863 return(TNG_FAILURE);
10865 return(TNG_SUCCESS);
10868 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10869 (tng_trajectory_t tng_data,
10870 const char *new_name)
10874 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10875 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10877 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10879 /* If the currently stored string length is not enough to store the new
10880 * string it is freed and reallocated. */
10881 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10883 free(tng_data->first_computer_name);
10884 tng_data->first_computer_name = 0;
10886 if(!tng_data->first_computer_name)
10888 tng_data->first_computer_name = malloc(len);
10889 if(!tng_data->first_computer_name)
10891 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10892 __FILE__, __LINE__);
10893 return(TNG_CRITICAL);
10897 strncpy(tng_data->first_computer_name, new_name, len);
10899 return(TNG_SUCCESS);
10902 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10903 (const tng_trajectory_t tng_data,
10904 char *name, const int max_len)
10906 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10907 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10909 strncpy(name, tng_data->last_computer_name, max_len - 1);
10910 name[max_len - 1] = 0;
10912 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10914 return(TNG_FAILURE);
10916 return(TNG_SUCCESS);
10919 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10920 (tng_trajectory_t tng_data,
10921 const char *new_name)
10925 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10926 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10928 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10930 /* If the currently stored string length is not enough to store the new
10931 * string it is freed and reallocated. */
10932 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10935 free(tng_data->last_computer_name);
10936 tng_data->last_computer_name = 0;
10938 if(!tng_data->last_computer_name)
10940 tng_data->last_computer_name = malloc(len);
10941 if(!tng_data->last_computer_name)
10943 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10944 __FILE__, __LINE__);
10945 return(TNG_CRITICAL);
10949 strncpy(tng_data->last_computer_name, new_name, len);
10951 return(TNG_SUCCESS);
10954 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10955 (const tng_trajectory_t tng_data,
10956 char *signature, const int max_len)
10958 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10959 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10961 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
10962 signature[max_len - 1] = 0;
10964 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10966 return(TNG_FAILURE);
10968 return(TNG_SUCCESS);
10971 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10972 (tng_trajectory_t tng_data,
10973 const char *signature)
10977 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10978 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10980 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10982 /* If the currently stored string length is not enough to store the new
10983 * string it is freed and reallocated. */
10984 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10987 free(tng_data->first_pgp_signature);
10988 tng_data->first_pgp_signature = 0;
10990 if(!tng_data->first_pgp_signature)
10992 tng_data->first_pgp_signature = malloc(len);
10993 if(!tng_data->first_pgp_signature)
10995 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10996 __FILE__, __LINE__);
10997 return(TNG_CRITICAL);
11001 strncpy(tng_data->first_pgp_signature, signature, len);
11003 return(TNG_SUCCESS);
11006 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11007 (const tng_trajectory_t tng_data,
11008 char *signature, const int max_len)
11010 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11011 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11013 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
11014 signature[max_len - 1] = 0;
11016 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
11018 return(TNG_FAILURE);
11020 return(TNG_SUCCESS);
11023 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11024 (tng_trajectory_t tng_data,
11025 const char *signature)
11029 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11030 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11032 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11034 /* If the currently stored string length is not enough to store the new
11035 * string it is freed and reallocated. */
11036 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
11039 free(tng_data->last_pgp_signature);
11040 tng_data->last_pgp_signature = 0;
11042 if(!tng_data->last_pgp_signature)
11044 tng_data->last_pgp_signature = malloc(len);
11045 if(!tng_data->last_pgp_signature)
11047 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11048 __FILE__, __LINE__);
11049 return(TNG_CRITICAL);
11053 strncpy(tng_data->last_pgp_signature, signature, len);
11055 return(TNG_SUCCESS);
11058 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11059 (const tng_trajectory_t tng_data,
11060 char *name, const int max_len)
11062 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11063 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11065 strncpy(name, tng_data->forcefield_name, max_len - 1);
11066 name[max_len - 1] = 0;
11068 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11070 return(TNG_FAILURE);
11072 return(TNG_SUCCESS);
11075 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11076 (tng_trajectory_t tng_data,
11077 const char *new_name)
11081 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11082 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11084 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11086 /* If the currently stored string length is not enough to store the new
11087 * string it is freed and reallocated. */
11088 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11090 free(tng_data->forcefield_name);
11091 tng_data->forcefield_name = 0;
11093 if(!tng_data->forcefield_name)
11095 tng_data->forcefield_name = malloc(len);
11096 if(!tng_data->forcefield_name)
11098 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11099 __FILE__, __LINE__);
11100 return(TNG_CRITICAL);
11104 strncpy(tng_data->forcefield_name, new_name, len);
11106 return(TNG_SUCCESS);
11109 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11110 (const tng_trajectory_t tng_data,
11113 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11114 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11116 *len = tng_data->medium_stride_length;
11118 return(TNG_SUCCESS);
11121 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11122 (tng_trajectory_t tng_data,
11125 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11127 if(len >= tng_data->long_stride_length)
11129 return(TNG_FAILURE);
11131 tng_data->medium_stride_length = len;
11133 return(TNG_SUCCESS);
11136 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11137 (const tng_trajectory_t tng_data,
11140 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11141 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11143 *len = tng_data->long_stride_length;
11145 return(TNG_SUCCESS);
11148 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11149 (tng_trajectory_t tng_data,
11152 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11154 if(len <= tng_data->medium_stride_length)
11156 return(TNG_FAILURE);
11158 tng_data->long_stride_length = len;
11160 return(TNG_SUCCESS);
11163 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11164 (const tng_trajectory_t tng_data,
11167 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11168 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11170 *time = tng_data->time_per_frame;
11172 return(TNG_SUCCESS);
11175 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11176 (tng_trajectory_t tng_data,
11179 tng_trajectory_frame_set_t frame_set;
11181 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11182 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11184 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11186 return(TNG_SUCCESS);
11189 frame_set = &tng_data->current_trajectory_frame_set;
11191 /* If the current frame set is not finished write it to disk before
11192 changing time per frame. */
11193 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11195 frame_set->n_frames = frame_set->n_unwritten_frames;
11196 tng_frame_set_write(tng_data, TNG_USE_HASH);
11198 tng_data->time_per_frame = time;
11200 return(TNG_SUCCESS);
11203 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11204 (const tng_trajectory_t tng_data,
11207 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11208 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11210 *len = tng_data->input_file_len;
11212 return(TNG_SUCCESS);
11215 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11216 (const tng_trajectory_t tng_data,
11219 tng_gen_block_t block;
11220 tng_function_status stat;
11222 int64_t last_file_pos, first_frame, n_frames;
11224 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11225 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11226 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11228 file_pos = ftell(tng_data->input_file);
11229 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11231 if(last_file_pos <= 0)
11233 return(TNG_FAILURE);
11236 tng_block_init(&block);
11237 fseek(tng_data->input_file,
11238 (long)last_file_pos,
11240 /* Read block headers first to see that a frame set block is found. */
11241 stat = tng_block_header_read(tng_data, block);
11242 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11244 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11245 __FILE__, __LINE__);
11246 tng_block_destroy(&block);
11247 return(TNG_FAILURE);
11249 tng_block_destroy(&block);
11251 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11253 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11254 __FILE__, __LINE__);
11255 return(TNG_CRITICAL);
11257 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11259 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11260 __FILE__, __LINE__);
11261 return(TNG_CRITICAL);
11263 fseek(tng_data->input_file, file_pos, SEEK_SET);
11265 *n = first_frame + n_frames;
11267 return(TNG_SUCCESS);
11270 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11271 (const tng_trajectory_t tng_data,
11274 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11276 *precision = tng_data->compression_precision;
11278 return(TNG_SUCCESS);
11281 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11282 (tng_trajectory_t tng_data,
11283 const double precision)
11285 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11287 tng_data->compression_precision = precision;
11289 return(TNG_SUCCESS);
11292 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11293 (tng_trajectory_t tng_data,
11296 tng_molecule_t mol;
11300 tng_function_status stat;
11301 int64_t diff, n_mod, n_impl;
11303 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11305 diff = n - tng_data->n_particles;
11307 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11308 if(stat == TNG_SUCCESS)
11310 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11312 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11313 __FILE__, __LINE__);
11314 return(TNG_FAILURE);
11316 diff -= n_impl * mol->n_atoms;
11321 if(stat == TNG_SUCCESS)
11323 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11326 return(TNG_SUCCESS);
11330 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11331 fprintf(stderr, "particle count.\n");
11332 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11333 __FILE__, __LINE__);
11334 /* FIXME: Should we set the count of all other molecules to 0 and add
11335 * implicit molecules? */
11336 return(TNG_FAILURE);
11338 if(stat != TNG_SUCCESS)
11340 stat = tng_molecule_add(tng_data,
11341 "TNG_IMPLICIT_MOL",
11343 if(stat != TNG_SUCCESS)
11347 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11348 if(stat != TNG_SUCCESS)
11352 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11353 if(stat != TNG_SUCCESS)
11357 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11358 if(stat != TNG_SUCCESS)
11365 if(mol->n_atoms > 1)
11367 n_mod = diff % mol->n_atoms;
11370 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11371 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11372 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11373 __FILE__, __LINE__);
11374 return(TNG_FAILURE);
11376 diff /= mol->n_atoms;
11379 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11384 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11385 (const tng_trajectory_t tng_data,
11388 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11389 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11391 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11393 *n = tng_data->n_particles;
11397 *n = tng_data->current_trajectory_frame_set.n_particles;
11400 return(TNG_SUCCESS);
11403 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11404 (const tng_trajectory_t tng_data,
11407 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11408 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11410 *variable = tng_data->var_num_atoms_flag;
11412 return(TNG_SUCCESS);
11415 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11416 (const tng_trajectory_t tng_data,
11419 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11420 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11422 *n = tng_data->n_molecules;
11424 return(TNG_SUCCESS);
11427 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11428 (const tng_trajectory_t tng_data,
11431 int64_t *cnt_list = 0, cnt = 0, i;
11433 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11434 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11436 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11440 return(TNG_FAILURE);
11443 for(i = 0; i < tng_data->n_molecules; i++)
11445 cnt += cnt_list[i];
11450 return(TNG_SUCCESS);
11453 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11454 (const tng_trajectory_t tng_data,
11455 int64_t **mol_cnt_list)
11457 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11459 if(tng_data->var_num_atoms_flag)
11461 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11466 *mol_cnt_list = tng_data->molecule_cnt_list;
11468 if(*mol_cnt_list == 0)
11470 return(TNG_FAILURE);
11472 return(TNG_SUCCESS);
11475 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11476 (const tng_trajectory_t tng_data,
11479 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11480 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11482 *exp = tng_data->distance_unit_exponential;
11484 return(TNG_SUCCESS);
11487 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11488 (const tng_trajectory_t tng_data,
11491 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11493 tng_data->distance_unit_exponential = exp;
11495 return(TNG_SUCCESS);
11498 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11499 (const tng_trajectory_t tng_data,
11502 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11503 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11505 *n = tng_data->frame_set_n_frames;
11507 return(TNG_SUCCESS);
11510 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11511 (const tng_trajectory_t tng_data,
11514 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11516 tng_data->frame_set_n_frames = n;
11518 return(TNG_SUCCESS);
11521 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11522 (const tng_trajectory_t tng_data,
11525 int64_t long_stride_length, medium_stride_length;
11526 long file_pos, orig_frame_set_file_pos;
11527 tng_trajectory_frame_set_t frame_set;
11528 struct tng_trajectory_frame_set orig_frame_set;
11529 tng_gen_block_t block;
11530 tng_function_status stat;
11533 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11534 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11536 orig_frame_set = tng_data->current_trajectory_frame_set;
11538 frame_set = &tng_data->current_trajectory_frame_set;
11540 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11541 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
11543 tng_block_init(&block);
11544 fseek(tng_data->input_file,
11547 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
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 %ld. %s: %d\n", file_pos,
11553 __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);
11567 long_stride_length = tng_data->long_stride_length;
11568 medium_stride_length = tng_data->medium_stride_length;
11570 /* Take long steps forward until a long step forward would be too long or
11571 * the last frame set is found */
11572 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
11573 while(file_pos > 0)
11577 cnt += long_stride_length;
11578 fseek(tng_data->input_file, file_pos, SEEK_SET);
11579 /* Read block headers first to see what block is found. */
11580 stat = tng_block_header_read(tng_data, block);
11581 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11583 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11584 file_pos, __FILE__, __LINE__);
11585 tng_block_destroy(&block);
11586 return(TNG_CRITICAL);
11589 if(tng_block_read_next(tng_data, block,
11590 TNG_SKIP_HASH) != TNG_SUCCESS)
11592 tng_block_destroy(&block);
11593 return(TNG_CRITICAL);
11596 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
11599 /* Take medium steps forward until a medium step forward would be too long
11600 * or the last frame set is found */
11601 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11602 while(file_pos > 0)
11606 cnt += medium_stride_length;
11607 fseek(tng_data->input_file,
11610 /* Read block headers first to see what block is found. */
11611 stat = tng_block_header_read(tng_data, block);
11612 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11614 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11615 file_pos, __FILE__, __LINE__);
11616 tng_block_destroy(&block);
11617 return(TNG_CRITICAL);
11620 if(tng_block_read_next(tng_data, block,
11621 TNG_SKIP_HASH) != TNG_SUCCESS)
11623 tng_block_destroy(&block);
11624 return(TNG_CRITICAL);
11627 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11630 /* Take one step forward until the last frame set is found */
11631 file_pos = (long)frame_set->next_frame_set_file_pos;
11632 while(file_pos > 0)
11637 fseek(tng_data->input_file,
11640 /* Read block headers first to see what block is found. */
11641 stat = tng_block_header_read(tng_data, block);
11642 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11644 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11645 file_pos, __FILE__, __LINE__);
11646 tng_block_destroy(&block);
11647 return(TNG_CRITICAL);
11650 if(tng_block_read_next(tng_data, block,
11651 TNG_SKIP_HASH) != TNG_SUCCESS)
11653 tng_block_destroy(&block);
11654 return(TNG_CRITICAL);
11657 file_pos = (long)frame_set->next_frame_set_file_pos;
11660 tng_block_destroy(&block);
11662 *n = tng_data->n_trajectory_frame_sets = cnt;
11664 *frame_set = orig_frame_set;
11666 fseek(tng_data->input_file,
11667 (long)tng_data->first_trajectory_frame_set_input_file_pos,
11670 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11672 return(TNG_SUCCESS);
11675 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11676 (const tng_trajectory_t tng_data,
11677 tng_trajectory_frame_set_t *frame_set_p)
11679 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11681 *frame_set_p = &tng_data->current_trajectory_frame_set;
11683 return(TNG_SUCCESS);
11686 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11687 (tng_trajectory_t tng_data,
11690 int64_t long_stride_length, medium_stride_length;
11691 int64_t file_pos, curr_nr = 0, n_frame_sets;
11692 tng_trajectory_frame_set_t frame_set;
11693 tng_gen_block_t block;
11694 tng_function_status stat;
11696 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11697 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11699 frame_set = &tng_data->current_trajectory_frame_set;
11701 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11703 if(stat != TNG_SUCCESS)
11708 if(nr >= n_frame_sets)
11710 return(TNG_FAILURE);
11713 long_stride_length = tng_data->long_stride_length;
11714 medium_stride_length = tng_data->medium_stride_length;
11716 /* FIXME: The frame set number of the current frame set is not stored */
11718 if(nr < n_frame_sets - 1 - nr)
11720 /* Start from the beginning */
11721 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11725 /* Start from the end */
11726 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11727 curr_nr = n_frame_sets - 1;
11731 return(TNG_FAILURE);
11734 tng_block_init(&block);
11735 fseek(tng_data->input_file,
11738 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11739 /* Read block headers first to see what block is found. */
11740 stat = tng_block_header_read(tng_data, block);
11741 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11743 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11744 __FILE__, __LINE__);
11745 tng_block_destroy(&block);
11746 return(TNG_CRITICAL);
11749 if(tng_block_read_next(tng_data, block,
11750 TNG_SKIP_HASH) != TNG_SUCCESS)
11752 tng_block_destroy(&block);
11753 return(TNG_CRITICAL);
11758 tng_block_destroy(&block);
11759 return(TNG_SUCCESS);
11762 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11764 /* Take long steps forward until a long step forward would be too long or
11765 * the right frame set is found */
11766 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11768 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11771 curr_nr += long_stride_length;
11772 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11773 /* Read block headers first to see what block is found. */
11774 stat = tng_block_header_read(tng_data, block);
11775 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11777 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11778 file_pos, __FILE__, __LINE__);
11779 tng_block_destroy(&block);
11780 return(TNG_CRITICAL);
11783 if(tng_block_read_next(tng_data, block,
11784 TNG_SKIP_HASH) != TNG_SUCCESS)
11786 tng_block_destroy(&block);
11787 return(TNG_CRITICAL);
11791 tng_block_destroy(&block);
11792 return(TNG_SUCCESS);
11797 /* Take medium steps forward until a medium step forward would be too long
11798 * or the right frame set is found */
11799 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11801 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11804 curr_nr += medium_stride_length;
11805 fseek(tng_data->input_file,
11808 /* Read block headers first to see what block is found. */
11809 stat = tng_block_header_read(tng_data, block);
11810 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11812 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11813 file_pos, __FILE__, __LINE__);
11814 tng_block_destroy(&block);
11815 return(TNG_CRITICAL);
11818 if(tng_block_read_next(tng_data, block,
11819 TNG_SKIP_HASH) != TNG_SUCCESS)
11821 tng_block_destroy(&block);
11822 return(TNG_CRITICAL);
11826 tng_block_destroy(&block);
11827 return(TNG_SUCCESS);
11832 /* Take one step forward until the right frame set is found */
11833 while(file_pos > 0 && curr_nr < nr)
11835 file_pos = frame_set->next_frame_set_file_pos;
11840 fseek(tng_data->input_file,
11843 /* Read block headers first to see what block is found. */
11844 stat = tng_block_header_read(tng_data, block);
11845 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11847 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11848 file_pos, __FILE__, __LINE__);
11849 tng_block_destroy(&block);
11850 return(TNG_CRITICAL);
11853 if(tng_block_read_next(tng_data, block,
11854 TNG_SKIP_HASH) != TNG_SUCCESS)
11856 tng_block_destroy(&block);
11857 return(TNG_CRITICAL);
11861 tng_block_destroy(&block);
11862 return(TNG_SUCCESS);
11867 /* Take long steps backward until a long step backward would be too long
11868 * or the right frame set is found */
11869 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11871 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11874 curr_nr -= long_stride_length;
11875 fseek(tng_data->input_file,
11878 /* Read block headers first to see what block is found. */
11879 stat = tng_block_header_read(tng_data, block);
11880 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11882 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11883 file_pos, __FILE__, __LINE__);
11884 tng_block_destroy(&block);
11885 return(TNG_CRITICAL);
11888 if(tng_block_read_next(tng_data, block,
11889 TNG_SKIP_HASH) != TNG_SUCCESS)
11891 tng_block_destroy(&block);
11892 return(TNG_CRITICAL);
11896 tng_block_destroy(&block);
11897 return(TNG_SUCCESS);
11902 /* Take medium steps backward until a medium step backward would be too long
11903 * or the right frame set is found */
11904 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11906 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11909 curr_nr -= medium_stride_length;
11910 fseek(tng_data->input_file,
11913 /* Read block headers first to see what block is found. */
11914 stat = tng_block_header_read(tng_data, block);
11915 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11917 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11918 file_pos, __FILE__, __LINE__);
11919 tng_block_destroy(&block);
11920 return(TNG_CRITICAL);
11923 if(tng_block_read_next(tng_data, block,
11924 TNG_SKIP_HASH) != TNG_SUCCESS)
11926 tng_block_destroy(&block);
11927 return(TNG_CRITICAL);
11931 tng_block_destroy(&block);
11932 return(TNG_SUCCESS);
11937 /* Take one step backward until the right frame set is found */
11938 while(file_pos > 0 && curr_nr > nr)
11940 file_pos = frame_set->prev_frame_set_file_pos;
11944 fseek(tng_data->input_file,
11947 /* Read block headers first to see what block is found. */
11948 stat = tng_block_header_read(tng_data, block);
11949 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11951 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11952 file_pos, __FILE__, __LINE__);
11953 tng_block_destroy(&block);
11954 return(TNG_CRITICAL);
11957 if(tng_block_read_next(tng_data, block,
11958 TNG_SKIP_HASH) != TNG_SUCCESS)
11960 tng_block_destroy(&block);
11961 return(TNG_CRITICAL);
11965 tng_block_destroy(&block);
11966 return(TNG_SUCCESS);
11971 /* If for some reason the current frame set is not yet found,
11972 * take one step forward until the right frame set is found */
11973 while(file_pos > 0 && curr_nr < nr)
11975 file_pos = frame_set->next_frame_set_file_pos;
11979 fseek(tng_data->input_file,
11982 /* Read block headers first to see what block is found. */
11983 stat = tng_block_header_read(tng_data, block);
11984 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11986 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11987 file_pos, __FILE__, __LINE__);
11988 tng_block_destroy(&block);
11989 return(TNG_CRITICAL);
11992 if(tng_block_read_next(tng_data, block,
11993 TNG_SKIP_HASH) != TNG_SUCCESS)
11995 tng_block_destroy(&block);
11996 return(TNG_CRITICAL);
12000 tng_block_destroy(&block);
12001 return(TNG_SUCCESS);
12006 tng_block_destroy(&block);
12007 return(TNG_FAILURE);
12010 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12011 (tng_trajectory_t tng_data,
12012 const int64_t frame)
12014 int64_t first_frame, last_frame, n_frames_per_frame_set;
12015 int64_t long_stride_length, medium_stride_length;
12016 int64_t file_pos, temp_frame, n_frames;
12017 tng_trajectory_frame_set_t frame_set;
12018 tng_gen_block_t block;
12019 tng_function_status stat;
12021 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12022 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
12024 frame_set = &tng_data->current_trajectory_frame_set;
12026 tng_block_init(&block);
12028 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
12030 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12031 fseek(tng_data->input_file,
12034 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
12035 /* Read block headers first to see what block is found. */
12036 stat = tng_block_header_read(tng_data, block);
12037 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12039 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12040 file_pos, __FILE__, __LINE__);
12041 tng_block_destroy(&block);
12042 return(TNG_CRITICAL);
12045 if(tng_block_read_next(tng_data, block,
12046 TNG_SKIP_HASH) != TNG_SUCCESS)
12048 tng_block_destroy(&block);
12049 return(TNG_CRITICAL);
12053 first_frame = tng_max_i64(frame_set->first_frame, 0);
12054 last_frame = first_frame + frame_set->n_frames - 1;
12055 /* Is this the right frame set? */
12056 if(first_frame <= frame && frame <= last_frame)
12058 tng_block_destroy(&block);
12059 return(TNG_SUCCESS);
12062 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12063 long_stride_length = tng_data->long_stride_length;
12064 medium_stride_length = tng_data->medium_stride_length;
12066 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12069 if(temp_frame - first_frame > n_frames_per_frame_set)
12071 n_frames_per_frame_set = temp_frame - first_frame;
12075 tng_num_frames_get(tng_data, &n_frames);
12077 if(frame >= n_frames)
12079 tng_block_destroy(&block);
12080 return(TNG_FAILURE);
12083 if(first_frame - frame >= frame ||
12084 frame - last_frame >
12085 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12087 /* Start from the beginning */
12088 if(first_frame - frame >= frame)
12090 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12094 tng_block_destroy(&block);
12095 return(TNG_FAILURE);
12098 /* Start from the end */
12099 else if(frame - first_frame > (n_frames - 1) - frame)
12101 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12103 /* If the last frame set position is not set start from the current
12104 * frame set, since it will be closer than the first frame set. */
12106 /* Start from current */
12109 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12114 fseek(tng_data->input_file,
12117 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
12118 /* Read block headers first to see what block is found. */
12119 stat = tng_block_header_read(tng_data, block);
12120 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12122 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12123 file_pos, __FILE__, __LINE__);
12124 tng_block_destroy(&block);
12125 return(TNG_CRITICAL);
12128 if(tng_block_read_next(tng_data, block,
12129 TNG_SKIP_HASH) != TNG_SUCCESS)
12131 tng_block_destroy(&block);
12132 return(TNG_CRITICAL);
12137 first_frame = tng_max_i64(frame_set->first_frame, 0);
12138 last_frame = first_frame + frame_set->n_frames - 1;
12140 if(frame >= first_frame && frame <= last_frame)
12142 tng_block_destroy(&block);
12143 return(TNG_SUCCESS);
12146 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12148 /* Take long steps forward until a long step forward would be too long or
12149 * the right frame set is found */
12150 while(file_pos > 0 && first_frame + long_stride_length *
12151 n_frames_per_frame_set <= frame)
12153 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12156 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
12157 /* Read block headers first to see what block is found. */
12158 stat = tng_block_header_read(tng_data, block);
12159 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12161 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12162 file_pos, __FILE__, __LINE__);
12163 tng_block_destroy(&block);
12164 return(TNG_CRITICAL);
12167 if(tng_block_read_next(tng_data, block,
12168 TNG_SKIP_HASH) != TNG_SUCCESS)
12170 tng_block_destroy(&block);
12171 return(TNG_CRITICAL);
12174 first_frame = tng_max_i64(frame_set->first_frame, 0);
12175 last_frame = first_frame + frame_set->n_frames - 1;
12176 if(frame >= first_frame && frame <= last_frame)
12178 tng_block_destroy(&block);
12179 return(TNG_SUCCESS);
12183 /* Take medium steps forward until a medium step forward would be too long
12184 * or the right frame set is found */
12185 while(file_pos > 0 && first_frame + medium_stride_length *
12186 n_frames_per_frame_set <= frame)
12188 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12191 fseek(tng_data->input_file,
12194 /* Read block headers first to see what block is found. */
12195 stat = tng_block_header_read(tng_data, block);
12196 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12198 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12199 file_pos, __FILE__, __LINE__);
12200 tng_block_destroy(&block);
12201 return(TNG_CRITICAL);
12204 if(tng_block_read_next(tng_data, block,
12205 TNG_SKIP_HASH) != TNG_SUCCESS)
12207 tng_block_destroy(&block);
12208 return(TNG_CRITICAL);
12211 first_frame = tng_max_i64(frame_set->first_frame, 0);
12212 last_frame = first_frame + frame_set->n_frames - 1;
12213 if(frame >= first_frame && frame <= last_frame)
12215 tng_block_destroy(&block);
12216 return(TNG_SUCCESS);
12220 /* Take one step forward until the right frame set is found */
12221 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12223 file_pos = frame_set->next_frame_set_file_pos;
12226 fseek(tng_data->input_file,
12229 /* Read block headers first to see what block is found. */
12230 stat = tng_block_header_read(tng_data, block);
12231 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12233 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12234 file_pos, __FILE__, __LINE__);
12235 tng_block_destroy(&block);
12236 return(TNG_CRITICAL);
12239 if(tng_block_read_next(tng_data, block,
12240 TNG_SKIP_HASH) != TNG_SUCCESS)
12242 tng_block_destroy(&block);
12243 return(TNG_CRITICAL);
12246 first_frame = tng_max_i64(frame_set->first_frame, 0);
12247 last_frame = first_frame + frame_set->n_frames - 1;
12248 if(frame >= first_frame && frame <= last_frame)
12250 tng_block_destroy(&block);
12251 return(TNG_SUCCESS);
12255 /* Take long steps backward until a long step backward would be too long
12256 * or the right frame set is found */
12257 while(file_pos > 0 && first_frame - long_stride_length *
12258 n_frames_per_frame_set >= frame)
12260 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12263 fseek(tng_data->input_file,
12266 /* Read block headers first to see what block is found. */
12267 stat = tng_block_header_read(tng_data, block);
12268 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12270 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12271 file_pos, __FILE__, __LINE__);
12272 tng_block_destroy(&block);
12273 return(TNG_CRITICAL);
12276 if(tng_block_read_next(tng_data, block,
12277 TNG_SKIP_HASH) != TNG_SUCCESS)
12279 tng_block_destroy(&block);
12280 return(TNG_CRITICAL);
12283 first_frame = tng_max_i64(frame_set->first_frame, 0);
12284 last_frame = first_frame + frame_set->n_frames - 1;
12285 if(frame >= first_frame && frame <= last_frame)
12287 tng_block_destroy(&block);
12288 return(TNG_SUCCESS);
12292 /* Take medium steps backward until a medium step backward would be too long
12293 * or the right frame set is found */
12294 while(file_pos > 0 && first_frame - medium_stride_length *
12295 n_frames_per_frame_set >= frame)
12297 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12300 fseek(tng_data->input_file,
12303 /* Read block headers first to see what block is found. */
12304 stat = tng_block_header_read(tng_data, block);
12305 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12307 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12308 file_pos, __FILE__, __LINE__);
12309 tng_block_destroy(&block);
12310 return(TNG_CRITICAL);
12313 if(tng_block_read_next(tng_data, block,
12314 TNG_SKIP_HASH) != TNG_SUCCESS)
12316 tng_block_destroy(&block);
12317 return(TNG_CRITICAL);
12320 first_frame = tng_max_i64(frame_set->first_frame, 0);
12321 last_frame = first_frame + frame_set->n_frames - 1;
12322 if(frame >= first_frame && frame <= last_frame)
12324 tng_block_destroy(&block);
12325 return(TNG_SUCCESS);
12329 /* Take one step backward until the right frame set is found */
12330 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12332 file_pos = frame_set->prev_frame_set_file_pos;
12335 fseek(tng_data->input_file,
12338 /* Read block headers first to see what block is found. */
12339 stat = tng_block_header_read(tng_data, block);
12340 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12342 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12343 file_pos, __FILE__, __LINE__);
12344 tng_block_destroy(&block);
12345 return(TNG_CRITICAL);
12348 if(tng_block_read_next(tng_data, block,
12349 TNG_SKIP_HASH) != TNG_SUCCESS)
12351 tng_block_destroy(&block);
12352 return(TNG_CRITICAL);
12355 first_frame = tng_max_i64(frame_set->first_frame, 0);
12356 last_frame = first_frame + frame_set->n_frames - 1;
12357 if(frame >= first_frame && frame <= last_frame)
12359 tng_block_destroy(&block);
12360 return(TNG_SUCCESS);
12364 /* If for some reason the current frame set is not yet found,
12365 * take one step forward until the right frame set is found */
12366 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12368 file_pos = frame_set->next_frame_set_file_pos;
12371 fseek(tng_data->input_file,
12374 /* Read block headers first to see what block is found. */
12375 stat = tng_block_header_read(tng_data, block);
12376 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12378 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12379 file_pos, __FILE__, __LINE__);
12380 tng_block_destroy(&block);
12381 return(TNG_CRITICAL);
12384 if(tng_block_read_next(tng_data, block,
12385 TNG_SKIP_HASH) != TNG_SUCCESS)
12387 tng_block_destroy(&block);
12388 return(TNG_CRITICAL);
12391 first_frame = tng_max_i64(frame_set->first_frame, 0);
12392 last_frame = first_frame + frame_set->n_frames - 1;
12393 if(frame >= first_frame && frame <= last_frame)
12395 tng_block_destroy(&block);
12396 return(TNG_SUCCESS);
12400 tng_block_destroy(&block);
12401 return(TNG_FAILURE);
12404 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12405 (const tng_trajectory_t tng_data,
12406 const tng_trajectory_frame_set_t frame_set,
12411 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12412 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12414 *pos = frame_set->next_frame_set_file_pos;
12416 return(TNG_SUCCESS);
12419 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12420 (const tng_trajectory_t tng_data,
12421 const tng_trajectory_frame_set_t frame_set,
12426 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12427 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12429 *pos = frame_set->prev_frame_set_file_pos;
12431 return(TNG_SUCCESS);
12434 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12435 (const tng_trajectory_t tng_data,
12436 const tng_trajectory_frame_set_t frame_set,
12437 int64_t *first_frame,
12438 int64_t *last_frame)
12442 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12443 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12444 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12446 *first_frame = frame_set->first_frame;
12447 *last_frame = *first_frame + frame_set->n_frames - 1;
12449 return(TNG_SUCCESS);
12452 /** Translate from the particle numbering used in a frame set to the real
12453 * particle numbering - used in the molecule description.
12454 * @param frame_set is the frame_set containing the mappings to use.
12455 * @param local is the index number of the atom in this frame set
12456 * @param real is set to the index of the atom in the molecular system.
12457 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12460 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12461 (const tng_trajectory_frame_set_t frame_set,
12462 const int64_t local,
12465 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12466 tng_particle_mapping_t mapping;
12470 return(TNG_SUCCESS);
12472 for(i = 0; i < n_blocks; i++)
12474 mapping = &frame_set->mappings[i];
12475 first = mapping->num_first_particle;
12476 if(local < first ||
12477 local >= first + mapping->n_particles)
12481 *real = mapping->real_particle_numbers[local-first];
12482 return(TNG_SUCCESS);
12485 return(TNG_FAILURE);
12488 /** Translate from the real particle numbering to the particle numbering
12489 * used in a frame set.
12490 * @param frame_set is the frame_set containing the mappings to use.
12491 * @param real is the index number of the atom in the molecular system.
12492 * @param local is set to the index of the atom in this frame set.
12493 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12496 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12497 (const tng_trajectory_frame_set_t frame_set,
12498 const int64_t real,
12501 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12502 tng_particle_mapping_t mapping;
12506 return(TNG_SUCCESS);
12508 for(i = 0; i < n_blocks; i++)
12510 mapping = &frame_set->mappings[i];
12511 for(j = mapping->n_particles; j--;)
12513 if(mapping->real_particle_numbers[j] == real)
12516 return(TNG_SUCCESS);
12520 return(TNG_FAILURE);
12524 static tng_function_status tng_file_headers_len_get
12525 (tng_trajectory_t tng_data,
12529 tng_gen_block_t block;
12531 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12533 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12535 return(TNG_CRITICAL);
12540 orig_pos = ftell(tng_data->input_file);
12542 if(!tng_data->input_file_len)
12544 fseek(tng_data->input_file, 0, SEEK_END);
12545 tng_data->input_file_len = ftell(tng_data->input_file);
12547 fseek(tng_data->input_file, 0, SEEK_SET);
12549 tng_block_init(&block);
12550 /* Read through the headers of non-trajectory blocks (they come before the
12551 * trajectory blocks in the file) */
12552 while (*len < tng_data->input_file_len &&
12553 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12555 block->id != TNG_TRAJECTORY_FRAME_SET)
12557 *len += block->header_contents_size + block->block_contents_size;
12558 fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12561 fseek(tng_data->input_file, orig_pos, SEEK_SET);
12563 tng_block_destroy(&block);
12565 return(TNG_SUCCESS);
12568 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12569 (tng_trajectory_t tng_data,
12570 const char hash_mode)
12572 int64_t prev_pos = 0;
12573 tng_gen_block_t block;
12575 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12577 tng_data->n_trajectory_frame_sets = 0;
12579 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12581 return(TNG_CRITICAL);
12584 if(!tng_data->input_file_len)
12586 fseek(tng_data->input_file, 0, SEEK_END);
12587 tng_data->input_file_len = ftell(tng_data->input_file);
12589 fseek(tng_data->input_file, 0, SEEK_SET);
12591 tng_block_init(&block);
12592 /* Non trajectory blocks (they come before the trajectory
12593 * blocks in the file) */
12594 while (prev_pos < tng_data->input_file_len &&
12595 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12597 block->id != TNG_TRAJECTORY_FRAME_SET)
12599 tng_block_read_next(tng_data, block, hash_mode);
12600 prev_pos = ftell(tng_data->input_file);
12603 /* Go back if a trajectory block was encountered */
12604 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12606 fseek(tng_data->input_file, prev_pos, SEEK_SET);
12609 tng_block_destroy(&block);
12611 return(TNG_SUCCESS);
12614 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12615 (tng_trajectory_t tng_data,
12616 const char hash_mode)
12619 int64_t len, orig_len, tot_len = 0, data_start_pos;
12620 tng_function_status stat;
12621 tng_gen_block_t block;
12623 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12625 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12627 return(TNG_CRITICAL);
12630 if(tng_data->n_trajectory_frame_sets > 0)
12632 stat = tng_file_headers_len_get(tng_data, &orig_len);
12633 if(stat != TNG_SUCCESS)
12638 tng_block_init(&block);
12639 block->name = malloc(TNG_MAX_STR_LEN);
12642 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12643 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12644 tng_block_destroy(&block);
12645 return(TNG_CRITICAL);
12647 strcpy(block->name, "GENERAL INFO");
12648 tng_block_header_len_calculate(tng_data, block, &len);
12650 tng_general_info_block_len_calculate(tng_data, &len);
12652 strcpy(block->name, "MOLECULES");
12653 tng_block_header_len_calculate(tng_data, block, &len);
12655 tng_molecules_block_len_calculate(tng_data, &len);
12658 for(i = 0; i < tng_data->n_data_blocks; i++)
12660 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12661 tng_block_header_len_calculate(tng_data, block, &len);
12663 tng_data_block_len_calculate(tng_data,
12664 (tng_particle_data_t)&tng_data->non_tr_data[i],
12665 TNG_FALSE, 1, 1, 1, 0,
12666 1, 0, &data_start_pos,
12670 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12672 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12673 tng_block_header_len_calculate(tng_data, block, &len);
12675 tng_data_block_len_calculate(tng_data,
12676 &tng_data->non_tr_particle_data[i],
12677 TNG_TRUE, 1, 1, 1, 0,
12678 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12683 tng_block_destroy(&block);
12685 if(tot_len > orig_len)
12687 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12690 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12693 /* TODO: If there is already frame set data written to this file (e.g. when
12694 * appending to an already existing file we might need to move frame sets to
12695 * the end of the file. */
12697 if(tng_general_info_block_write(tng_data, hash_mode)
12700 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12701 tng_data->input_file_path, __FILE__, __LINE__);
12702 return(TNG_CRITICAL);
12705 if(tng_molecules_block_write(tng_data, hash_mode)
12708 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12709 tng_data->input_file_path, __FILE__, __LINE__);
12710 return(TNG_CRITICAL);
12713 /* FIXME: Currently writing non-trajectory data blocks here.
12714 * Should perhaps be moved. */
12715 tng_block_init(&block);
12716 for(i = 0; i < tng_data->n_data_blocks; i++)
12718 block->id = tng_data->non_tr_data[i].block_id;
12719 tng_data_block_write(tng_data, block,
12723 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12725 block->id = tng_data->non_tr_particle_data[i].block_id;
12726 tng_particle_data_block_write(tng_data, block,
12730 tng_block_destroy(&block);
12732 return(TNG_SUCCESS);
12735 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12736 tng_gen_block_t block,
12737 const char hash_mode)
12739 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12740 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12744 case TNG_TRAJECTORY_FRAME_SET:
12745 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12746 case TNG_PARTICLE_MAPPING:
12747 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12748 case TNG_GENERAL_INFO:
12749 return(tng_general_info_block_read(tng_data, block, hash_mode));
12750 case TNG_MOLECULES:
12751 return(tng_molecules_block_read(tng_data, block, hash_mode));
12753 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12755 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12759 /* Skip to the next block */
12760 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12761 return(TNG_FAILURE);
12766 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12767 (tng_trajectory_t tng_data,
12768 const char hash_mode)
12771 tng_gen_block_t block;
12772 tng_function_status stat;
12774 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12776 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12778 return(TNG_CRITICAL);
12781 file_pos = ftell(tng_data->input_file);
12783 tng_block_init(&block);
12785 if(!tng_data->input_file_len)
12787 fseek(tng_data->input_file, 0, SEEK_END);
12788 tng_data->input_file_len = ftell(tng_data->input_file);
12789 fseek(tng_data->input_file, file_pos, SEEK_SET);
12792 /* Read block headers first to see what block is found. */
12793 stat = tng_block_header_read(tng_data, block);
12794 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12797 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12798 file_pos, __FILE__, __LINE__);
12799 tng_block_destroy(&block);
12800 return(TNG_CRITICAL);
12803 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12805 if(tng_block_read_next(tng_data, block,
12806 hash_mode) == TNG_SUCCESS)
12808 tng_data->n_trajectory_frame_sets++;
12809 file_pos = ftell(tng_data->input_file);
12810 /* Read all blocks until next frame set block */
12811 stat = tng_block_header_read(tng_data, block);
12812 while(file_pos < tng_data->input_file_len &&
12813 stat != TNG_CRITICAL &&
12814 block->id != TNG_TRAJECTORY_FRAME_SET &&
12817 stat = tng_block_read_next(tng_data, block,
12819 if(stat != TNG_CRITICAL)
12821 file_pos = ftell(tng_data->input_file);
12822 if(file_pos < tng_data->input_file_len)
12824 stat = tng_block_header_read(tng_data, block);
12828 if(stat == TNG_CRITICAL)
12830 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12831 file_pos, __FILE__, __LINE__);
12832 tng_block_destroy(&block);
12836 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12838 fseek(tng_data->input_file, file_pos, SEEK_SET);
12842 tng_block_destroy(&block);
12844 return(TNG_SUCCESS);
12848 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12849 (tng_trajectory_t tng_data,
12850 const char hash_mode,
12851 const int64_t block_id)
12854 tng_gen_block_t block;
12855 tng_function_status stat;
12856 int found_flag = 1;
12858 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12860 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12862 return(TNG_CRITICAL);
12865 file_pos = (long)tng_data->current_trajectory_frame_set_input_file_pos;
12869 /* No current frame set. This means that the first frame set must be
12872 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12877 fseek(tng_data->input_file,
12883 return(TNG_FAILURE);
12886 tng_block_init(&block);
12888 if(!tng_data->input_file_len)
12890 fseek(tng_data->input_file, 0, SEEK_END);
12891 tng_data->input_file_len = ftell(tng_data->input_file);
12892 fseek(tng_data->input_file, file_pos, SEEK_SET);
12895 /* Read block headers first to see what block is found. */
12896 stat = tng_block_header_read(tng_data, block);
12897 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12899 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12900 file_pos, __FILE__, __LINE__);
12901 tng_block_destroy(&block);
12902 return(TNG_CRITICAL);
12904 /* If the current frame set had already been read skip its block contents */
12907 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12909 /* Otherwiese read the frame set block */
12912 stat = tng_block_read_next(tng_data, block,
12914 if(stat != TNG_SUCCESS)
12916 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12917 tng_block_destroy(&block);
12921 file_pos = ftell(tng_data->input_file);
12925 /* Read only blocks of the requested ID
12926 * until next frame set block */
12927 stat = tng_block_header_read(tng_data, block);
12928 while(file_pos < tng_data->input_file_len &&
12929 stat != TNG_CRITICAL &&
12930 block->id != TNG_TRAJECTORY_FRAME_SET &&
12933 if(block->id == block_id)
12935 stat = tng_block_read_next(tng_data, block,
12937 if(stat != TNG_CRITICAL)
12939 file_pos = ftell(tng_data->input_file);
12941 if(file_pos < tng_data->input_file_len)
12943 stat = tng_block_header_read(tng_data, block);
12949 file_pos += (long)(block->block_contents_size + block->header_contents_size);
12950 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12951 if(file_pos < tng_data->input_file_len)
12953 stat = tng_block_header_read(tng_data, block);
12957 if(stat == TNG_CRITICAL)
12959 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12960 file_pos, __FILE__, __LINE__);
12961 tng_block_destroy(&block);
12965 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12967 fseek(tng_data->input_file, file_pos, SEEK_SET);
12970 tng_block_destroy(&block);
12974 return(TNG_SUCCESS);
12978 return(TNG_FAILURE);
12982 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12983 (tng_trajectory_t tng_data,
12984 const char hash_mode)
12988 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12990 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12992 return(TNG_CRITICAL);
12995 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12997 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12999 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13004 fseek(tng_data->input_file,
13010 return(TNG_FAILURE);
13013 return(tng_frame_set_read(tng_data, hash_mode));
13016 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13017 (tng_trajectory_t tng_data,
13018 const char hash_mode,
13019 const int64_t block_id)
13022 tng_gen_block_t block;
13023 tng_function_status stat;
13025 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13027 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13029 return(TNG_CRITICAL);
13032 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13034 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13036 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13041 fseek(tng_data->input_file,
13047 return(TNG_FAILURE);
13050 tng_block_init(&block);
13052 if(!tng_data->input_file_len)
13054 fseek(tng_data->input_file, 0, SEEK_END);
13055 tng_data->input_file_len = ftell(tng_data->input_file);
13056 fseek(tng_data->input_file, file_pos, SEEK_SET);
13059 /* Read block headers first to see what block is found. */
13060 stat = tng_block_header_read(tng_data, block);
13061 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13063 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13064 file_pos, __FILE__, __LINE__);
13065 tng_block_destroy(&block);
13066 return(TNG_CRITICAL);
13069 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13071 if(tng_block_read_next(tng_data, block,
13072 hash_mode) == TNG_SUCCESS)
13074 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13077 tng_block_destroy(&block);
13082 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13083 const char hash_mode)
13086 tng_gen_block_t block;
13087 tng_trajectory_frame_set_t frame_set;
13088 tng_function_status stat;
13090 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13092 frame_set = &tng_data->current_trajectory_frame_set;
13094 if(frame_set->n_written_frames == frame_set->n_frames)
13096 return(TNG_SUCCESS);
13099 tng_data->current_trajectory_frame_set_output_file_pos =
13100 ftell(tng_data->output_file);
13101 tng_data->last_trajectory_frame_set_output_file_pos =
13102 tng_data->current_trajectory_frame_set_output_file_pos;
13104 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13106 return(TNG_FAILURE);
13109 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13111 tng_data->first_trajectory_frame_set_output_file_pos =
13112 tng_data->current_trajectory_frame_set_output_file_pos;
13115 tng_block_init(&block);
13117 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13119 tng_block_destroy(&block);
13120 return(TNG_FAILURE);
13123 /* Write non-particle data blocks */
13124 for(i = 0; i<frame_set->n_data_blocks; i++)
13126 block->id = frame_set->tr_data[i].block_id;
13127 tng_data_block_write(tng_data, block, i, hash_mode);
13129 /* Write the mapping blocks and particle data blocks*/
13130 if(frame_set->n_mapping_blocks)
13132 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13134 block->id = TNG_PARTICLE_MAPPING;
13135 if(frame_set->mappings[i].n_particles > 0)
13137 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13138 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13140 block->id = frame_set->tr_particle_data[j].block_id;
13141 tng_particle_data_block_write(tng_data, block,
13142 j, &frame_set->mappings[i],
13150 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13152 block->id = frame_set->tr_particle_data[i].block_id;
13153 tng_particle_data_block_write(tng_data, block,
13159 /* Update pointers in the general info block */
13160 stat = tng_header_pointers_update(tng_data, hash_mode);
13162 if(stat == TNG_SUCCESS)
13164 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13167 tng_block_destroy(&block);
13169 frame_set->n_unwritten_frames = 0;
13171 fflush(tng_data->output_file);
13176 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13177 (tng_trajectory_t tng_data,
13178 const char hash_mode)
13180 tng_trajectory_frame_set_t frame_set;
13182 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13184 frame_set = &tng_data->current_trajectory_frame_set;
13186 if(frame_set->n_unwritten_frames == 0)
13188 return(TNG_SUCCESS);
13190 frame_set->n_frames = frame_set->n_unwritten_frames;
13192 return(tng_frame_set_write(tng_data, hash_mode));
13195 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13196 (tng_trajectory_t tng_data,
13197 const int64_t first_frame,
13198 const int64_t n_frames)
13200 tng_gen_block_t block;
13201 tng_trajectory_frame_set_t frame_set;
13202 FILE *temp = tng_data->input_file;
13205 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13206 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13207 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13209 frame_set = &tng_data->current_trajectory_frame_set;
13211 curr_pos = ftell(tng_data->output_file);
13215 tng_file_headers_write(tng_data, TNG_USE_HASH);
13218 /* Set pointer to previous frame set to the one that was loaded
13220 * FIXME: This is a bit risky. If they are not added in order
13221 * it will be wrong. */
13222 if(tng_data->n_trajectory_frame_sets)
13224 frame_set->prev_frame_set_file_pos =
13225 tng_data->current_trajectory_frame_set_output_file_pos;
13228 tng_data->current_trajectory_frame_set_output_file_pos =
13229 ftell(tng_data->output_file);
13231 tng_data->n_trajectory_frame_sets++;
13233 /* Set the medium range pointers */
13234 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13236 frame_set->medium_stride_prev_frame_set_file_pos =
13237 tng_data->first_trajectory_frame_set_output_file_pos;
13239 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13241 /* FIXME: Currently only working if the previous frame set has its
13242 * medium stride pointer already set. This might need some fixing. */
13243 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13244 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13246 tng_block_init(&block);
13247 tng_data->input_file = tng_data->output_file;
13249 curr_pos = ftell(tng_data->output_file);
13250 fseek(tng_data->output_file,
13251 (long)frame_set->medium_stride_prev_frame_set_file_pos,
13254 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13256 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13257 __FILE__, __LINE__);
13258 tng_data->input_file = temp;
13259 tng_block_destroy(&block);
13260 return(TNG_CRITICAL);
13263 /* Read the next frame set from the previous frame set and one
13264 * medium stride step back */
13265 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
13266 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13267 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13268 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13269 1, tng_data->output_file) == 0)
13271 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13272 tng_data->input_file = temp;
13273 tng_block_destroy(&block);
13274 return(TNG_CRITICAL);
13277 if(tng_data->input_endianness_swap_func_64)
13279 if(tng_data->input_endianness_swap_func_64(tng_data,
13280 &frame_set->medium_stride_prev_frame_set_file_pos)
13283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13284 __FILE__, __LINE__);
13288 tng_block_destroy(&block);
13290 /* Set the long range pointers */
13291 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13293 frame_set->long_stride_prev_frame_set_file_pos =
13294 tng_data->first_trajectory_frame_set_output_file_pos;
13296 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13298 /* FIXME: Currently only working if the previous frame set has its
13299 * long stride pointer already set. This might need some fixing. */
13300 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13301 frame_set->long_stride_prev_frame_set_file_pos != 0)
13303 tng_block_init(&block);
13304 tng_data->input_file = tng_data->output_file;
13306 fseek(tng_data->output_file,
13307 (long)frame_set->long_stride_prev_frame_set_file_pos,
13310 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13312 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13313 __FILE__, __LINE__);
13314 tng_data->input_file = temp;
13315 tng_block_destroy(&block);
13316 return(TNG_CRITICAL);
13319 /* Read the next frame set from the previous frame set and one
13320 * long stride step back */
13321 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
13322 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13324 tng_block_destroy(&block);
13326 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13327 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13328 1, tng_data->output_file) == 0)
13330 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13331 tng_data->input_file = temp;
13332 return(TNG_CRITICAL);
13335 if(tng_data->input_endianness_swap_func_64)
13337 if(tng_data->input_endianness_swap_func_64(tng_data,
13338 &frame_set->long_stride_prev_frame_set_file_pos)
13341 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13342 __FILE__, __LINE__);
13349 tng_data->input_file = temp;
13350 fseek(tng_data->output_file, (long)curr_pos, SEEK_SET);
13354 frame_set->first_frame = first_frame;
13355 frame_set->n_frames = n_frames;
13356 frame_set->n_written_frames = 0;
13357 frame_set->n_unwritten_frames = 0;
13358 frame_set->first_frame_time = -1;
13360 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13361 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13363 tng_data->first_trajectory_frame_set_output_file_pos =
13364 tng_data->current_trajectory_frame_set_output_file_pos;
13366 /* FIXME: Should check the frame number instead of the file_pos,
13367 * in case frame sets are not in order */
13368 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13369 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13370 tng_data->last_trajectory_frame_set_output_file_pos <
13371 tng_data->current_trajectory_frame_set_output_file_pos)
13373 tng_data->last_trajectory_frame_set_output_file_pos =
13374 tng_data->current_trajectory_frame_set_output_file_pos;
13377 return(TNG_SUCCESS);
13380 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13381 (tng_trajectory_t tng_data,
13382 const int64_t first_frame,
13383 const int64_t n_frames,
13384 const double first_frame_time)
13386 tng_function_status stat;
13388 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13389 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13390 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13391 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13394 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13395 if(stat != TNG_SUCCESS)
13399 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13404 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13405 (tng_trajectory_t tng_data,
13406 const double first_frame_time)
13408 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13409 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13411 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13413 return(TNG_SUCCESS);
13416 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13417 (const tng_trajectory_t tng_data,
13420 long file_pos, next_frame_set_file_pos;
13421 tng_gen_block_t block;
13422 tng_function_status stat;
13424 tng_trajectory_frame_set_t frame_set;
13426 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13427 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13428 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13430 file_pos = ftell(tng_data->input_file);
13432 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13434 next_frame_set_file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13438 frame_set = &tng_data->current_trajectory_frame_set;
13439 next_frame_set_file_pos = (long)frame_set->next_frame_set_file_pos;
13442 if(next_frame_set_file_pos <= 0)
13444 return(TNG_FAILURE);
13447 fseek(tng_data->input_file, (long)next_frame_set_file_pos, SEEK_SET);
13448 /* Read block headers first to see that a frame set block is found. */
13449 tng_block_init(&block);
13450 stat = tng_block_header_read(tng_data, block);
13451 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13453 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13454 file_pos, __FILE__, __LINE__);
13455 return(TNG_CRITICAL);
13457 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13459 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13461 tng_block_destroy(&block);
13463 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13465 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13466 __FILE__, __LINE__);
13467 return(TNG_CRITICAL);
13469 fseek(tng_data->input_file, file_pos, SEEK_SET);
13471 return(TNG_SUCCESS);
13474 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13475 (tng_trajectory_t tng_data,
13477 const char *block_name,
13478 const char datatype,
13479 const char block_type_flag,
13481 const int64_t n_values_per_frame,
13482 int64_t stride_length,
13483 const int64_t codec_id,
13486 int i, j, size, len;
13487 tng_trajectory_frame_set_t frame_set;
13488 tng_non_particle_data_t data;
13489 char **first_dim_values;
13490 char *new_data_c=new_data;
13491 int64_t n_frames_div;
13493 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13494 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13495 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13497 frame_set = &tng_data->current_trajectory_frame_set;
13499 if(stride_length <= 0)
13504 /* If the block does not exist, create it */
13505 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13507 if(tng_data_block_create(tng_data, block_type_flag) !=
13510 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13511 __FILE__, __LINE__);
13512 return(TNG_CRITICAL);
13514 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13516 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13520 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13522 data->block_id = id;
13524 data->block_name = malloc(strlen(block_name) + 1);
13525 if(!data->block_name)
13527 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13528 (int)strlen(block_name)+1, __FILE__, __LINE__);
13529 return(TNG_CRITICAL);
13531 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13534 /* FIXME: Memory leak from strings. */
13536 data->last_retrieved_frame = -1;
13539 data->datatype = datatype;
13540 data->stride_length = tng_max_i64(stride_length, 1);
13541 data->n_values_per_frame = n_values_per_frame;
13542 data->n_frames = n_frames;
13543 data->codec_id = codec_id;
13544 data->compression_multiplier = 1.0;
13545 /* FIXME: This can cause problems. */
13546 data->first_frame_with_data = frame_set->first_frame;
13550 case TNG_FLOAT_DATA:
13551 size = sizeof(float);
13554 size = sizeof(int64_t);
13556 case TNG_DOUBLE_DATA:
13558 size = sizeof(double);
13564 /* Allocate memory */
13565 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13566 n_values_per_frame) !=
13569 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13570 __FILE__, __LINE__);
13571 return(TNG_CRITICAL);
13574 if(n_frames > frame_set->n_unwritten_frames)
13576 frame_set->n_unwritten_frames = n_frames;
13579 n_frames_div = (n_frames % stride_length) ?
13580 n_frames / stride_length + 1:
13581 n_frames / stride_length;
13583 if(datatype == TNG_CHAR_DATA)
13585 for(i = 0; i < n_frames_div; i++)
13587 first_dim_values = data->strings[i];
13588 for(j = 0; j < n_values_per_frame; j++)
13590 len = tng_min_i((int)strlen(new_data_c) + 1,
13592 if(first_dim_values[j])
13594 free(first_dim_values[j]);
13596 first_dim_values[j] = malloc(len);
13597 if(!first_dim_values[j])
13599 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13600 len, __FILE__, __LINE__);
13601 return(TNG_CRITICAL);
13603 strncpy(first_dim_values[j],
13611 memcpy(data->values, new_data, size * n_frames_div *
13612 n_values_per_frame);
13616 return(TNG_SUCCESS);
13619 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13620 (tng_trajectory_t tng_data,
13622 const char *block_name,
13623 const char datatype,
13624 const char block_type_flag,
13626 const int64_t n_values_per_frame,
13627 int64_t stride_length,
13628 const int64_t num_first_particle,
13629 const int64_t n_particles,
13630 const int64_t codec_id,
13635 int64_t tot_n_particles, n_frames_div;
13636 char ***first_dim_values, **second_dim_values;
13637 tng_trajectory_frame_set_t frame_set;
13638 tng_particle_data_t data;
13639 char *new_data_c=new_data;
13641 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13642 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13643 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13644 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13645 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13648 frame_set = &tng_data->current_trajectory_frame_set;
13650 if(stride_length <= 0)
13655 /* If the block does not exist, create it */
13656 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13658 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13661 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13662 __FILE__, __LINE__);
13663 return(TNG_CRITICAL);
13665 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13667 data = &frame_set->tr_particle_data[frame_set->
13668 n_particle_data_blocks - 1];
13672 data = &tng_data->non_tr_particle_data[tng_data->
13673 n_particle_data_blocks - 1];
13675 data->block_id = id;
13677 data->block_name = malloc(strlen(block_name) + 1);
13678 if(!data->block_name)
13680 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13681 (int)strlen(block_name)+1, __FILE__, __LINE__);
13682 return(TNG_CRITICAL);
13684 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13686 data->datatype = datatype;
13689 /* FIXME: Memory leak from strings. */
13691 data->last_retrieved_frame = -1;
13694 data->stride_length = tng_max_i64(stride_length, 1);
13695 data->n_values_per_frame = n_values_per_frame;
13696 data->n_frames = n_frames;
13697 data->codec_id = codec_id;
13698 data->compression_multiplier = 1.0;
13699 /* FIXME: This can cause problems. */
13700 data->first_frame_with_data = frame_set->first_frame;
13702 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13704 tot_n_particles = frame_set->n_particles;
13708 tot_n_particles = tng_data->n_particles;
13711 /* If data values are supplied add that data to the data block. */
13714 /* Allocate memory */
13715 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13716 stride_length, tot_n_particles,
13717 n_values_per_frame) !=
13720 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13721 __FILE__, __LINE__);
13722 return(TNG_CRITICAL);
13725 if(n_frames > frame_set->n_unwritten_frames)
13727 frame_set->n_unwritten_frames = n_frames;
13730 n_frames_div = (n_frames % stride_length) ?
13731 n_frames / stride_length + 1:
13732 n_frames / stride_length;
13734 if(datatype == TNG_CHAR_DATA)
13736 for(i = 0; i < n_frames_div; i++)
13738 first_dim_values = data->strings[i];
13739 for(j = num_first_particle; j < num_first_particle + n_particles;
13742 second_dim_values = first_dim_values[j];
13743 for(k = 0; k < n_values_per_frame; k++)
13745 len = tng_min_i((int)strlen(new_data_c) + 1,
13747 if(second_dim_values[k])
13749 free(second_dim_values[k]);
13751 second_dim_values[k] = malloc(len);
13752 if(!second_dim_values[k])
13754 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13755 len, __FILE__, __LINE__);
13756 return(TNG_CRITICAL);
13758 strncpy(second_dim_values[k],
13770 size = sizeof(int64_t);
13772 case TNG_FLOAT_DATA:
13773 size = sizeof(float);
13775 case TNG_DOUBLE_DATA:
13777 size = sizeof(double);
13780 memcpy(data->values, new_data, size * n_frames_div *
13781 n_particles * n_values_per_frame);
13785 return(TNG_SUCCESS);
13788 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13789 (tng_trajectory_t tng_data,
13795 tng_trajectory_frame_set_t frame_set;
13796 tng_function_status stat;
13797 tng_particle_data_t p_data;
13798 tng_non_particle_data_t np_data;
13799 int block_type = -1;
13801 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13802 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13804 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13806 p_data = &tng_data->non_tr_particle_data[i];
13807 if(p_data->block_id == block_id)
13809 strncpy(name, p_data->block_name, max_len);
13810 name[max_len - 1] = '\0';
13811 return(TNG_SUCCESS);
13814 for(i = 0; i < tng_data->n_data_blocks; i++)
13816 np_data = &tng_data->non_tr_data[i];
13817 if(np_data->block_id == block_id)
13819 strncpy(name, np_data->block_name, max_len);
13820 name[max_len - 1] = '\0';
13821 return(TNG_SUCCESS);
13825 frame_set = &tng_data->current_trajectory_frame_set;
13827 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13828 if(stat == TNG_SUCCESS)
13830 block_type = TNG_PARTICLE_BLOCK_DATA;
13834 stat = tng_data_find(tng_data, block_id, &np_data);
13835 if(stat == TNG_SUCCESS)
13837 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13841 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13842 if(stat != TNG_SUCCESS)
13846 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13847 if(stat == TNG_SUCCESS)
13849 block_type = TNG_PARTICLE_BLOCK_DATA;
13853 stat = tng_data_find(tng_data, block_id, &np_data);
13854 if(stat == TNG_SUCCESS)
13856 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13861 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13863 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13865 p_data = &frame_set->tr_particle_data[i];
13866 if(p_data->block_id == block_id)
13868 strncpy(name, p_data->block_name, max_len);
13869 name[max_len - 1] = '\0';
13870 return(TNG_SUCCESS);
13874 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13876 for(i = 0; i < frame_set->n_data_blocks; i++)
13878 np_data = &frame_set->tr_data[i];
13879 if(np_data->block_id == block_id)
13881 strncpy(name, np_data->block_name, max_len);
13882 name[max_len - 1] = '\0';
13883 return(TNG_SUCCESS);
13888 return(TNG_FAILURE);
13891 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13892 (const tng_trajectory_t tng_data,
13894 int *block_dependency)
13897 tng_function_status stat;
13898 tng_particle_data_t p_data;
13899 tng_non_particle_data_t np_data;
13901 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13902 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13904 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13906 p_data = &tng_data->non_tr_particle_data[i];
13907 if(p_data->block_id == block_id)
13909 *block_dependency = TNG_PARTICLE_DEPENDENT;
13910 return(TNG_SUCCESS);
13913 for(i = 0; i < tng_data->n_data_blocks; i++)
13915 np_data = &tng_data->non_tr_data[i];
13916 if(np_data->block_id == block_id)
13918 *block_dependency = 0;
13919 return(TNG_SUCCESS);
13923 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13924 if(stat == TNG_SUCCESS)
13926 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13927 return(TNG_SUCCESS);
13931 stat = tng_data_find(tng_data, block_id, &np_data);
13932 if(stat == TNG_SUCCESS)
13934 *block_dependency = TNG_FRAME_DEPENDENT;
13935 return(TNG_SUCCESS);
13939 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13940 if(stat != TNG_SUCCESS)
13944 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13945 if(stat == TNG_SUCCESS)
13947 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13948 return(TNG_SUCCESS);
13952 stat = tng_data_find(tng_data, block_id, &np_data);
13953 if(stat == TNG_SUCCESS)
13955 *block_dependency = TNG_FRAME_DEPENDENT;
13956 return(TNG_SUCCESS);
13962 return(TNG_FAILURE);
13965 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13966 (const tng_trajectory_t tng_data,
13968 int64_t *n_values_per_frame)
13971 tng_function_status stat;
13972 tng_particle_data_t p_data;
13973 tng_non_particle_data_t np_data;
13975 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13976 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13978 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13980 p_data = &tng_data->non_tr_particle_data[i];
13981 if(p_data->block_id == block_id)
13983 *n_values_per_frame = p_data->n_values_per_frame;
13984 return(TNG_SUCCESS);
13987 for(i = 0; i < tng_data->n_data_blocks; i++)
13989 np_data = &tng_data->non_tr_data[i];
13990 if(np_data->block_id == block_id)
13992 *n_values_per_frame = np_data->n_values_per_frame;
13993 return(TNG_SUCCESS);
13997 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13998 if(stat == TNG_SUCCESS)
14000 *n_values_per_frame = p_data->n_values_per_frame;
14001 return(TNG_SUCCESS);
14005 stat = tng_data_find(tng_data, block_id, &np_data);
14006 if(stat == TNG_SUCCESS)
14008 *n_values_per_frame = np_data->n_values_per_frame;
14009 return(TNG_SUCCESS);
14013 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14014 if(stat != TNG_SUCCESS)
14018 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14019 if(stat == TNG_SUCCESS)
14021 *n_values_per_frame = p_data->n_values_per_frame;
14022 return(TNG_SUCCESS);
14026 stat = tng_data_find(tng_data, block_id, &np_data);
14027 if(stat == TNG_SUCCESS)
14029 *n_values_per_frame = np_data->n_values_per_frame;
14030 return(TNG_SUCCESS);
14036 return(TNG_FAILURE);
14039 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14040 (tng_trajectory_t tng_data,
14041 const int64_t frame_nr,
14042 const int64_t block_id,
14043 const void *values,
14044 const char hash_mode)
14046 int64_t header_pos, file_pos;
14047 int64_t output_file_len, n_values_per_frame, size, contents_size;
14048 int64_t header_size, temp_first, temp_last;
14049 int64_t i, last_frame;
14051 tng_gen_block_t block;
14052 tng_trajectory_frame_set_t frame_set;
14053 FILE *temp = tng_data->input_file;
14054 struct tng_non_particle_data data;
14055 tng_function_status stat;
14056 char dependency, sparse_data, datatype;
14059 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14060 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14061 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14063 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14065 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14066 __FILE__, __LINE__);
14067 return(TNG_CRITICAL);
14070 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14071 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14072 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14073 tng_data->first_trajectory_frame_set_input_file_pos =
14074 tng_data->first_trajectory_frame_set_output_file_pos;
14075 tng_data->last_trajectory_frame_set_input_file_pos =
14076 tng_data->last_trajectory_frame_set_output_file_pos;
14077 tng_data->current_trajectory_frame_set_input_file_pos =
14078 tng_data->current_trajectory_frame_set_output_file_pos;
14080 tng_data->input_file = tng_data->output_file;
14082 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14084 frame_set = &tng_data->current_trajectory_frame_set;
14086 if(stat != TNG_SUCCESS)
14088 last_frame = frame_set->first_frame +
14089 frame_set->n_frames - 1;
14090 /* If the wanted frame would be in the frame set after the last
14091 * frame set create a new frame set. */
14092 if(stat == TNG_FAILURE &&
14093 last_frame < frame_nr)
14094 /* (last_frame < frame_nr &&
14095 tng_data->current_trajectory_frame_set.first_frame +
14096 tng_data->frame_set_n_frames >= frame_nr))*/
14098 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14100 last_frame = frame_nr - 1;
14102 tng_frame_set_new(tng_data,
14104 tng_data->frame_set_n_frames);
14105 file_pos = ftell(tng_data->output_file);
14106 fseek(tng_data->output_file, 0, SEEK_END);
14107 output_file_len = ftell(tng_data->output_file);
14108 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14110 /* Read mapping blocks from the last frame set */
14111 tng_block_init(&block);
14113 stat = tng_block_header_read(tng_data, block);
14114 while(file_pos < output_file_len &&
14115 stat != TNG_CRITICAL &&
14116 block->id != TNG_TRAJECTORY_FRAME_SET &&
14119 if(block->id == TNG_PARTICLE_MAPPING)
14121 tng_trajectory_mapping_block_read(tng_data, block,
14126 fseek(tng_data->output_file, (long)block->block_contents_size,
14129 file_pos = ftell(tng_data->output_file);
14130 if(file_pos < output_file_len)
14132 stat = tng_block_header_read(tng_data, block);
14136 tng_block_destroy(&block);
14137 /* Write the frame set to disk */
14138 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14140 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14141 return(TNG_CRITICAL);
14146 tng_data->input_file = temp;
14147 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14148 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14149 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14154 tng_block_init(&block);
14156 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14158 fseek(tng_data->output_file, 0, SEEK_END);
14159 output_file_len = ftell(tng_data->output_file);
14160 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14162 /* Read past the frame set block first */
14163 stat = tng_block_header_read(tng_data, block);
14164 if(stat == TNG_CRITICAL)
14166 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14167 file_pos, __FILE__, __LINE__);
14168 tng_block_destroy(&block);
14169 tng_data->input_file = temp;
14171 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14172 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14173 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14176 fseek(tng_data->output_file, (long)block->block_contents_size,
14179 /* Read all block headers until next frame set block or
14180 * until the wanted block id is found */
14181 stat = tng_block_header_read(tng_data, block);
14182 while(file_pos < output_file_len &&
14183 stat != TNG_CRITICAL &&
14184 block->id != block_id &&
14185 block->id != TNG_TRAJECTORY_FRAME_SET &&
14188 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
14189 file_pos = ftell(tng_data->output_file);
14190 if(file_pos < output_file_len)
14192 stat = tng_block_header_read(tng_data, block);
14195 if(stat == TNG_CRITICAL)
14197 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14198 file_pos, __FILE__, __LINE__);
14199 tng_block_destroy(&block);
14200 tng_data->input_file = temp;
14201 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14202 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14203 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14207 contents_size = block->block_contents_size;
14208 header_size = block->header_contents_size;
14210 header_pos = ftell(tng_data->output_file) - header_size;
14211 frame_set = &tng_data->current_trajectory_frame_set;
14213 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14215 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14216 tng_block_destroy(&block);
14217 return(TNG_CRITICAL);
14219 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14221 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14222 tng_block_destroy(&block);
14223 return(TNG_CRITICAL);
14225 data.datatype = datatype;
14227 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14228 (dependency & TNG_PARTICLE_DEPENDENT))
14230 tng_block_destroy(&block);
14231 tng_data->input_file = temp;
14233 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14234 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14235 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14236 return(TNG_FAILURE);
14239 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14241 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14242 tng_block_destroy(&block);
14243 return(TNG_CRITICAL);
14246 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14247 tng_data->input_file) == 0)
14249 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14250 tng_block_destroy(&block);
14251 return(TNG_CRITICAL);
14253 if(tng_data->output_endianness_swap_func_64)
14255 if(tng_data->output_endianness_swap_func_64(tng_data,
14256 &data.n_values_per_frame)
14259 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14260 __FILE__, __LINE__);
14264 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14265 tng_data->input_file) == 0)
14267 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14268 tng_block_destroy(&block);
14269 return(TNG_CRITICAL);
14271 if(tng_data->output_endianness_swap_func_64)
14273 if(tng_data->output_endianness_swap_func_64(tng_data,
14277 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14278 __FILE__, __LINE__);
14282 if(data.codec_id != TNG_UNCOMPRESSED)
14284 if(fread(&data.compression_multiplier,
14285 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14288 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14289 tng_block_destroy(&block);
14290 return(TNG_CRITICAL);
14292 if(tng_data->output_endianness_swap_func_64)
14294 if(tng_data->output_endianness_swap_func_64(tng_data,
14295 (int64_t *)&data.compression_multiplier)
14298 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14299 __FILE__, __LINE__);
14305 data.compression_multiplier = 1;
14310 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14311 1, tng_data->input_file) == 0)
14313 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14314 tng_block_destroy(&block);
14315 return(TNG_CRITICAL);
14317 if(tng_data->output_endianness_swap_func_64)
14319 if(tng_data->output_endianness_swap_func_64(tng_data,
14320 &data.first_frame_with_data)
14323 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14324 __FILE__, __LINE__);
14328 if(fread(&data.stride_length, sizeof(data.stride_length),
14329 1, tng_data->input_file) == 0)
14331 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14332 tng_block_destroy(&block);
14333 return(TNG_CRITICAL);
14335 if(tng_data->output_endianness_swap_func_64)
14337 if(tng_data->output_endianness_swap_func_64(tng_data,
14338 &data.stride_length)
14341 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14342 __FILE__, __LINE__);
14348 data.first_frame_with_data = 0;
14349 data.stride_length = 1;
14351 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14353 tng_data->input_file = temp;
14355 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14356 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14357 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14359 switch(data.datatype)
14361 case(TNG_INT_DATA):
14362 size = sizeof(int64_t);
14364 case(TNG_FLOAT_DATA):
14365 size = sizeof(float);
14367 case(TNG_DOUBLE_DATA):
14368 size = sizeof(double);
14371 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14373 tng_block_destroy(&block);
14374 return(TNG_FAILURE);
14377 n_values_per_frame = data.n_values_per_frame;
14379 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14380 data.first_frame_with_data)) /
14381 data.stride_length;
14382 file_pos *= size * n_values_per_frame;
14384 if(file_pos > contents_size)
14386 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14388 tng_block_destroy(&block);
14389 return(TNG_FAILURE);
14392 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14394 /* If the endianness is not big endian the data needs to be swapped */
14395 if((data.datatype == TNG_INT_DATA ||
14396 data.datatype == TNG_DOUBLE_DATA) &&
14397 tng_data->output_endianness_swap_func_64)
14399 copy = malloc(n_values_per_frame * size);
14400 memcpy(copy, values, n_values_per_frame * size);
14401 for(i = 0; i < n_values_per_frame; i++)
14403 if(tng_data->output_endianness_swap_func_64(tng_data,
14407 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14408 __FILE__, __LINE__);
14411 fwrite(copy, n_values_per_frame, size,
14412 tng_data->output_file);
14415 else if(data.datatype == TNG_FLOAT_DATA &&
14416 tng_data->output_endianness_swap_func_32)
14418 copy = malloc(n_values_per_frame * size);
14419 memcpy(copy, values, n_values_per_frame * size);
14420 for(i = 0; i < n_values_per_frame; i++)
14422 if(tng_data->output_endianness_swap_func_32(tng_data,
14426 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14427 __FILE__, __LINE__);
14430 fwrite(copy, n_values_per_frame, size,
14431 tng_data->output_file);
14437 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14440 fflush(tng_data->output_file);
14442 /* Update the number of written frames in the frame set. */
14443 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14445 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14448 /* If the last frame has been written update the hash */
14449 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14450 data.first_frame_with_data) >=
14451 frame_set->n_frames)
14453 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14457 tng_block_destroy(&block);
14459 return(TNG_SUCCESS);
14462 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14463 (tng_trajectory_t tng_data,
14464 const int64_t frame_nr,
14465 const int64_t block_id,
14466 const int64_t val_first_particle,
14467 const int64_t val_n_particles,
14468 const void *values,
14469 const char hash_mode)
14471 int64_t header_pos, file_pos, tot_n_particles;
14472 int64_t output_file_len, n_values_per_frame, size, contents_size;
14473 int64_t header_size, temp_first, temp_last;
14474 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14475 int64_t i, last_frame;
14477 tng_gen_block_t block;
14478 tng_trajectory_frame_set_t frame_set;
14479 FILE *temp = tng_data->input_file;
14480 struct tng_particle_data data;
14481 tng_function_status stat;
14482 tng_particle_mapping_t mapping;
14483 char dependency, sparse_data, datatype;
14486 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14487 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14488 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14489 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14490 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14492 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14494 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14495 __FILE__, __LINE__);
14496 return(TNG_CRITICAL);
14499 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14500 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14501 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14502 tng_data->first_trajectory_frame_set_input_file_pos =
14503 tng_data->first_trajectory_frame_set_output_file_pos;
14504 tng_data->last_trajectory_frame_set_input_file_pos =
14505 tng_data->last_trajectory_frame_set_output_file_pos;
14506 tng_data->current_trajectory_frame_set_input_file_pos =
14507 tng_data->current_trajectory_frame_set_output_file_pos;
14509 tng_data->input_file = tng_data->output_file;
14511 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14513 frame_set = &tng_data->current_trajectory_frame_set;
14515 if(stat != TNG_SUCCESS)
14517 last_frame = frame_set->first_frame +
14518 frame_set->n_frames - 1;
14519 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14521 /* If the wanted frame would be in the frame set after the last
14522 * frame set create a new frame set. */
14523 if(stat == TNG_FAILURE &&
14524 (last_frame < frame_nr &&
14525 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14527 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14529 last_frame = frame_nr - 1;
14531 tng_frame_set_new(tng_data,
14533 tng_data->frame_set_n_frames);
14535 file_pos = ftell(tng_data->output_file);
14536 fseek(tng_data->output_file, 0, SEEK_END);
14537 output_file_len = ftell(tng_data->output_file);
14538 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14540 /* Read mapping blocks from the last frame set */
14541 tng_block_init(&block);
14543 stat = tng_block_header_read(tng_data, block);
14544 while(file_pos < output_file_len &&
14545 stat != TNG_CRITICAL &&
14546 block->id != TNG_TRAJECTORY_FRAME_SET &&
14549 if(block->id == TNG_PARTICLE_MAPPING)
14551 tng_trajectory_mapping_block_read(tng_data, block,
14556 fseek(tng_data->output_file, (long)block->block_contents_size,
14559 file_pos = ftell(tng_data->output_file);
14560 if(file_pos < output_file_len)
14562 stat = tng_block_header_read(tng_data, block);
14566 tng_block_destroy(&block);
14567 /* Write the frame set to disk */
14568 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14570 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14576 tng_data->input_file = temp;
14577 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14578 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14579 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14585 tng_block_init(&block);
14587 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14589 fseek(tng_data->output_file, 0, SEEK_END);
14590 output_file_len = ftell(tng_data->output_file);
14591 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14593 /* Read past the frame set block first */
14594 stat = tng_block_header_read(tng_data, block);
14595 if(stat == TNG_CRITICAL)
14597 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14598 file_pos, __FILE__, __LINE__);
14599 tng_block_destroy(&block);
14600 tng_data->input_file = temp;
14602 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14603 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14604 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14607 fseek(tng_data->output_file, (long)block->block_contents_size,
14610 if(tng_data->var_num_atoms_flag)
14612 tot_n_particles = frame_set->n_particles;
14616 tot_n_particles = tng_data->n_particles;
14619 if(val_n_particles < tot_n_particles)
14621 mapping_block_end_pos = -1;
14622 /* Read all mapping blocks to find the right place to put the data */
14623 stat = tng_block_header_read(tng_data, block);
14624 while(file_pos < output_file_len &&
14625 stat != TNG_CRITICAL &&
14626 block->id != TNG_TRAJECTORY_FRAME_SET &&
14629 if(block->id == TNG_PARTICLE_MAPPING)
14631 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14635 fseek(tng_data->output_file, (long)block->block_contents_size,
14638 file_pos = ftell(tng_data->output_file);
14639 if(block->id == TNG_PARTICLE_MAPPING)
14641 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14642 if(val_first_particle >= mapping->num_first_particle &&
14643 val_first_particle < mapping->num_first_particle +
14644 mapping->n_particles &&
14645 val_first_particle + val_n_particles <=
14646 mapping->num_first_particle + mapping->n_particles)
14648 mapping_block_end_pos = file_pos;
14651 if(file_pos < output_file_len)
14653 stat = tng_block_header_read(tng_data, block);
14656 if(stat == TNG_CRITICAL)
14658 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14659 file_pos, __FILE__, __LINE__);
14660 tng_block_destroy(&block);
14661 tng_data->input_file = temp;
14663 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14664 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14665 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14668 if(mapping_block_end_pos < 0)
14670 tng_block_destroy(&block);
14671 tng_data->input_file = temp;
14673 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14674 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14675 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14676 return(TNG_FAILURE);
14678 fseek(tng_data->output_file, (long)mapping_block_end_pos, SEEK_SET);
14681 /* Read all block headers until next frame set block or
14682 * until the wanted block id is found */
14683 stat = tng_block_header_read(tng_data, block);
14684 while(file_pos < output_file_len &&
14685 stat != TNG_CRITICAL &&
14686 block->id != block_id &&
14687 block->id != TNG_PARTICLE_MAPPING &&
14688 block->id != TNG_TRAJECTORY_FRAME_SET &&
14691 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
14692 file_pos = ftell(tng_data->output_file);
14693 if(file_pos < output_file_len)
14695 stat = tng_block_header_read(tng_data, block);
14698 if(stat == TNG_CRITICAL)
14700 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14701 file_pos, __FILE__, __LINE__);
14702 tng_block_destroy(&block);
14703 tng_data->input_file = temp;
14705 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14706 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14707 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14711 contents_size = block->block_contents_size;
14712 header_size = block->header_contents_size;
14714 header_pos = ftell(tng_data->output_file) - header_size;
14715 frame_set = &tng_data->current_trajectory_frame_set;
14717 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14719 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14720 tng_block_destroy(&block);
14721 return(TNG_CRITICAL);
14724 data.datatype = datatype;
14726 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14728 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14729 tng_block_destroy(&block);
14730 return(TNG_CRITICAL);
14733 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14734 !(dependency & TNG_PARTICLE_DEPENDENT))
14736 tng_block_destroy(&block);
14737 tng_data->input_file = temp;
14739 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14740 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14741 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14742 return(TNG_FAILURE);
14745 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14747 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14748 tng_block_destroy(&block);
14749 return(TNG_CRITICAL);
14752 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14753 tng_data->input_file) == 0)
14755 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14756 tng_block_destroy(&block);
14757 return(TNG_CRITICAL);
14759 if(tng_data->output_endianness_swap_func_64)
14761 if(tng_data->output_endianness_swap_func_64(tng_data,
14762 &data.n_values_per_frame)
14765 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14766 __FILE__, __LINE__);
14770 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14771 tng_data->input_file) == 0)
14773 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14774 tng_block_destroy(&block);
14775 return(TNG_CRITICAL);
14777 if(tng_data->output_endianness_swap_func_64)
14779 if(tng_data->output_endianness_swap_func_64(tng_data,
14783 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14784 __FILE__, __LINE__);
14788 if(data.codec_id != TNG_UNCOMPRESSED)
14790 if(fread(&data.compression_multiplier,
14791 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14794 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14795 tng_block_destroy(&block);
14796 return(TNG_CRITICAL);
14799 if(tng_data->output_endianness_swap_func_64)
14801 if(tng_data->output_endianness_swap_func_64(tng_data,
14802 (int64_t *)&data.compression_multiplier)
14805 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14806 __FILE__, __LINE__);
14812 data.compression_multiplier = 1;
14817 if(fread(&data.first_frame_with_data,
14818 sizeof(data.first_frame_with_data),
14819 1, tng_data->input_file) == 0)
14821 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14822 tng_block_destroy(&block);
14823 return(TNG_CRITICAL);
14825 if(tng_data->output_endianness_swap_func_64)
14827 if(tng_data->output_endianness_swap_func_64(tng_data,
14828 &data.first_frame_with_data)
14831 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14832 __FILE__, __LINE__);
14836 if(fread(&data.stride_length, sizeof(data.stride_length),
14837 1, tng_data->input_file) == 0)
14839 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14840 tng_block_destroy(&block);
14841 return(TNG_CRITICAL);
14843 if(tng_data->output_endianness_swap_func_64)
14845 if(tng_data->output_endianness_swap_func_64(tng_data,
14846 &data.stride_length)
14849 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14850 __FILE__, __LINE__);
14856 data.first_frame_with_data = 0;
14857 data.stride_length = 1;
14859 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14861 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14862 tng_data->input_file) == 0)
14864 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14865 tng_block_destroy(&block);
14866 return(TNG_CRITICAL);
14868 if(tng_data->output_endianness_swap_func_64)
14870 if(tng_data->output_endianness_swap_func_64(tng_data,
14871 &num_first_particle)
14874 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14875 __FILE__, __LINE__);
14879 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14880 tng_data->input_file) == 0)
14882 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14883 tng_block_destroy(&block);
14884 return(TNG_CRITICAL);
14886 if(tng_data->output_endianness_swap_func_64)
14888 if(tng_data->output_endianness_swap_func_64(tng_data,
14889 &block_n_particles)
14892 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14893 __FILE__, __LINE__);
14898 tng_data->input_file = temp;
14900 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14901 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14902 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14905 switch(data.datatype)
14907 case(TNG_INT_DATA):
14908 size = sizeof(int64_t);
14910 case(TNG_FLOAT_DATA):
14911 size = sizeof(float);
14913 case(TNG_DOUBLE_DATA):
14914 size = sizeof(double);
14917 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14919 tng_block_destroy(&block);
14920 return(TNG_FAILURE);
14923 n_values_per_frame = data.n_values_per_frame;
14925 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14926 data.first_frame_with_data)) /
14927 data.stride_length;
14928 file_pos *= block_n_particles * size * n_values_per_frame;
14930 if(file_pos > contents_size)
14932 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14934 tng_block_destroy(&block);
14935 return(TNG_FAILURE);
14938 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14940 /* If the endianness is not big endian the data needs to be swapped */
14941 if((data.datatype == TNG_INT_DATA ||
14942 data.datatype == TNG_DOUBLE_DATA) &&
14943 tng_data->output_endianness_swap_func_64)
14945 copy = malloc(val_n_particles * n_values_per_frame * size);
14946 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14947 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14949 if(tng_data->output_endianness_swap_func_64(tng_data,
14950 (int64_t *) copy+i)
14953 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14954 __FILE__, __LINE__);
14957 fwrite(copy, val_n_particles * n_values_per_frame, size,
14958 tng_data->output_file);
14961 else if(data.datatype == TNG_FLOAT_DATA &&
14962 tng_data->output_endianness_swap_func_32)
14964 copy = malloc(val_n_particles * n_values_per_frame * size);
14965 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14966 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14968 if(tng_data->output_endianness_swap_func_32(tng_data,
14969 (int32_t *) copy+i)
14972 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14973 __FILE__, __LINE__);
14976 fwrite(copy, val_n_particles * n_values_per_frame, size,
14977 tng_data->output_file);
14983 fwrite(values, val_n_particles * n_values_per_frame, size,
14984 tng_data->output_file);
14986 fflush(tng_data->output_file);
14988 /* Update the number of written frames in the frame set. */
14989 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14991 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14994 /* If the last frame has been written update the hash */
14995 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14996 data.first_frame_with_data) >=
14997 frame_set->n_frames)
14999 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
15003 tng_block_destroy(&block);
15004 return(TNG_SUCCESS);
15007 static tng_function_status tng_data_values_alloc
15008 (const tng_trajectory_t tng_data,
15009 union data_values ***values,
15010 const int64_t n_frames,
15011 const int64_t n_values_per_frame,
15015 tng_function_status stat;
15017 if(n_frames <= 0 || n_values_per_frame <= 0)
15019 return(TNG_FAILURE);
15024 stat = tng_data_values_free(tng_data, *values, n_frames,
15025 n_values_per_frame,
15027 if(stat != TNG_SUCCESS)
15029 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15030 __FILE__, __LINE__);
15034 *values = malloc(sizeof(union data_values *) * n_frames);
15037 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15038 sizeof(union data_values **) * n_frames,
15039 __FILE__, __LINE__);
15040 return(TNG_CRITICAL);
15044 for(i = 0; i < n_frames; i++)
15046 (*values)[i] = malloc(sizeof(union data_values) *
15047 n_values_per_frame);
15050 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15051 sizeof(union data_values) * n_values_per_frame,
15052 __FILE__, __LINE__);
15055 return(TNG_CRITICAL);
15058 return(TNG_SUCCESS);
15061 /* FIXME: This needs ***values */
15062 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15063 (const tng_trajectory_t tng_data,
15064 union data_values **values,
15065 const int64_t n_frames,
15066 const int64_t n_values_per_frame,
15074 for(i = 0; i < n_frames; i++)
15078 if(type == TNG_CHAR_DATA)
15080 for(j = 0; j < n_values_per_frame; j++)
15084 free(values[i][j].c);
15085 values[i][j].c = 0;
15097 return(TNG_SUCCESS);
15100 static tng_function_status tng_particle_data_values_alloc
15101 (const tng_trajectory_t tng_data,
15102 union data_values ****values,
15103 const int64_t n_frames,
15104 const int64_t n_particles,
15105 const int64_t n_values_per_frame,
15109 tng_function_status stat;
15111 if(n_particles == 0 || n_values_per_frame == 0)
15113 return(TNG_FAILURE);
15118 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15119 n_particles, n_values_per_frame,
15121 if(stat != TNG_SUCCESS)
15123 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15124 __FILE__, __LINE__);
15128 *values = malloc(sizeof(union data_values **) * n_frames);
15131 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15132 sizeof(union data_values **) * n_frames,
15133 __FILE__, __LINE__);
15134 return(TNG_CRITICAL);
15138 for(i = 0; i < n_frames; i++)
15140 (*values)[i] = malloc(sizeof(union data_values *) *
15144 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15145 sizeof(union data_values *) * n_particles,
15146 __FILE__, __LINE__);
15149 return(TNG_CRITICAL);
15151 for(j = 0; j < n_particles; j++)
15153 (*values)[i][j] = malloc(sizeof(union data_values) *
15154 n_values_per_frame);
15155 if(!(*values)[i][j])
15157 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15158 sizeof(union data_values *) * n_particles,
15159 __FILE__, __LINE__);
15160 tng_particle_data_values_free(tng_data, *values, n_frames,
15161 n_particles, n_values_per_frame,
15164 return(TNG_CRITICAL);
15168 return(TNG_SUCCESS);
15171 /* FIXME: This needs ****values */
15172 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15173 (const tng_trajectory_t tng_data,
15174 union data_values ***values,
15175 const int64_t n_frames,
15176 const int64_t n_particles,
15177 const int64_t n_values_per_frame,
15185 for(i = 0; i < n_frames; i++)
15189 for(j = 0; j < n_particles; j++)
15191 if(type == TNG_CHAR_DATA)
15193 for(k = 0; k < n_values_per_frame; k++)
15195 if(values[i][j][k].c)
15197 free(values[i][j][k].c);
15198 values[i][j][k].c = 0;
15202 free(values[i][j]);
15213 return(TNG_SUCCESS);
15217 tng_function_status DECLSPECDLLEXPORT tng_data_get
15218 (tng_trajectory_t tng_data,
15219 const int64_t block_id,
15220 union data_values ***values,
15222 int64_t *n_values_per_frame,
15225 int64_t i, j, file_pos, block_index;
15228 tng_non_particle_data_t data;
15229 tng_trajectory_frame_set_t frame_set;
15230 tng_gen_block_t block;
15231 tng_function_status stat;
15233 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15234 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15235 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15236 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15238 frame_set = &tng_data->current_trajectory_frame_set;
15243 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15245 tng_block_init(&block);
15246 file_pos = ftell(tng_data->input_file);
15247 /* Read all blocks until next frame set block */
15248 stat = tng_block_header_read(tng_data, block);
15249 while(file_pos < tng_data->input_file_len &&
15250 stat != TNG_CRITICAL &&
15251 block->id != TNG_TRAJECTORY_FRAME_SET &&
15254 /* Use hash by default */
15255 stat = tng_block_read_next(tng_data, block,
15257 if(stat != TNG_CRITICAL)
15259 file_pos = ftell(tng_data->input_file);
15260 if(file_pos < tng_data->input_file_len)
15262 stat = tng_block_header_read(tng_data, block);
15266 tng_block_destroy(&block);
15267 if(stat == TNG_CRITICAL)
15269 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15270 file_pos, __FILE__, __LINE__);
15274 for(i = 0; i < frame_set->n_data_blocks; i++)
15276 data = &frame_set->tr_data[i];
15277 if(data->block_id == block_id)
15283 if(block_index < 0)
15285 return(TNG_FAILURE);
15289 *n_frames = tng_max_i64(1, data->n_frames);
15290 *n_values_per_frame = data->n_values_per_frame;
15291 *type = data->datatype;
15295 if(tng_data_values_alloc(tng_data, values, *n_frames,
15296 *n_values_per_frame,
15300 return(TNG_CRITICAL);
15306 case TNG_CHAR_DATA:
15307 for(i = 0; i < *n_frames; i++)
15309 for(j = 0; j < *n_values_per_frame; j++)
15311 len = strlen(data->strings[i][j]) + 1;
15312 (*values)[i][j].c = malloc(len);
15313 strncpy((*values)[i][j].c, data->strings[i][j], len);
15318 size = sizeof(int);
15319 for(i = 0; i < *n_frames; i++)
15321 for(j = 0; j < *n_values_per_frame; j++)
15323 (*values)[i][j].i = *(int *)((char *)data->values + size *
15324 (i*(*n_values_per_frame) + j));
15328 case TNG_FLOAT_DATA:
15329 size = sizeof(float);
15330 for(i = 0; i < *n_frames; i++)
15332 for(j = 0; j < *n_values_per_frame; j++)
15334 (*values)[i][j].f = *(float *)((char *)data->values + size *
15335 (i*(*n_values_per_frame) + j));
15339 case TNG_DOUBLE_DATA:
15341 size = sizeof(double);
15342 for(i = 0; i < *n_frames; i++)
15344 for(j = 0; j < *n_values_per_frame; j++)
15346 (*values)[i][j].d = *(double *)((char *)data->values + size *
15347 (i*(*n_values_per_frame) + j));
15352 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15354 return(TNG_SUCCESS);
15357 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15358 const int64_t block_id,
15361 int64_t *stride_length,
15362 int64_t *n_values_per_frame,
15365 int64_t file_pos, data_size, n_frames_div, block_index;
15367 tng_non_particle_data_t data;
15368 tng_trajectory_frame_set_t frame_set;
15369 tng_gen_block_t block;
15371 tng_function_status stat;
15373 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15374 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15375 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15376 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15377 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15379 frame_set = &tng_data->current_trajectory_frame_set;
15384 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15386 tng_block_init(&block);
15387 file_pos = ftell(tng_data->input_file);
15388 /* Read all blocks until next frame set block */
15389 stat = tng_block_header_read(tng_data, block);
15390 while(file_pos < tng_data->input_file_len &&
15391 stat != TNG_CRITICAL &&
15392 block->id != TNG_TRAJECTORY_FRAME_SET &&
15395 /* Use hash by default */
15396 stat = tng_block_read_next(tng_data, block,
15398 if(stat != TNG_CRITICAL)
15400 file_pos = ftell(tng_data->input_file);
15401 if(file_pos < tng_data->input_file_len)
15403 stat = tng_block_header_read(tng_data, block);
15407 tng_block_destroy(&block);
15408 if(stat == TNG_CRITICAL)
15410 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15411 file_pos, __FILE__, __LINE__);
15415 for(i = 0; i < frame_set->n_data_blocks; i++)
15417 data = &frame_set->tr_data[i];
15418 if(data->block_id == block_id)
15424 if(block_index < 0)
15426 return(TNG_FAILURE);
15430 *type = data->datatype;
15434 case TNG_CHAR_DATA:
15435 return(TNG_FAILURE);
15437 size = sizeof(int64_t);
15439 case TNG_FLOAT_DATA:
15440 size = sizeof(float);
15442 case TNG_DOUBLE_DATA:
15444 size = sizeof(double);
15447 *n_frames = data->n_frames;
15448 *n_values_per_frame = data->n_values_per_frame;
15449 *stride_length = data->stride_length;
15450 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15451 *n_frames / *stride_length;
15453 data_size = n_frames_div * size *
15454 *n_values_per_frame;
15456 temp = realloc(*values, data_size);
15459 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15460 data_size, __FILE__, __LINE__);
15463 return(TNG_CRITICAL);
15468 memcpy(*values, data->values, data_size);
15470 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15472 return(TNG_SUCCESS);
15475 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15476 (tng_trajectory_t tng_data,
15477 const int64_t block_id,
15478 const int64_t start_frame_nr,
15479 const int64_t end_frame_nr,
15480 const char hash_mode,
15481 union data_values ***values,
15482 int64_t *n_values_per_frame,
15485 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15486 int64_t block_index;
15489 tng_non_particle_data_t data;
15490 tng_trajectory_frame_set_t frame_set;
15491 tng_gen_block_t block;
15492 tng_function_status stat;
15494 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15495 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15496 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15497 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15501 frame_set = &tng_data->current_trajectory_frame_set;
15502 first_frame = frame_set->first_frame;
15504 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15505 if(stat != TNG_SUCCESS)
15511 /* Do not re-read the frame set. */
15512 if(first_frame != frame_set->first_frame ||
15513 frame_set->n_data_blocks <= 0)
15515 tng_block_init(&block);
15516 file_pos = ftell(tng_data->input_file);
15517 /* Read all blocks until next frame set block */
15518 stat = tng_block_header_read(tng_data, block);
15519 while(file_pos < tng_data->input_file_len &&
15520 stat != TNG_CRITICAL &&
15521 block->id != TNG_TRAJECTORY_FRAME_SET &&
15524 stat = tng_block_read_next(tng_data, block,
15526 if(stat != TNG_CRITICAL)
15528 file_pos = ftell(tng_data->input_file);
15529 if(file_pos < tng_data->input_file_len)
15531 stat = tng_block_header_read(tng_data, block);
15535 tng_block_destroy(&block);
15536 if(stat == TNG_CRITICAL)
15538 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15539 file_pos, __FILE__, __LINE__);
15545 /* See if there is a data block of this ID.
15546 * Start checking the last read frame set */
15547 for(i = 0; i < frame_set->n_data_blocks; i++)
15549 data = &frame_set->tr_data[i];
15550 if(data->block_id == block_id)
15557 if(block_index < 0)
15559 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15560 block_id, __FILE__, __LINE__);
15561 return(TNG_FAILURE);
15564 n_frames = end_frame_nr - start_frame_nr + 1;
15565 *n_values_per_frame = data->n_values_per_frame;
15566 *type = data->datatype;
15570 if(tng_data_values_alloc(tng_data, values, n_frames,
15571 *n_values_per_frame,
15572 *type) != TNG_SUCCESS)
15574 return(TNG_CRITICAL);
15578 current_frame_pos = start_frame_nr - frame_set->first_frame;
15579 /* It's not very elegant to reuse so much of the code in the different case
15580 * statements, but it's unnecessarily slow to have the switch-case block
15581 * inside the for loops. */
15584 case TNG_CHAR_DATA:
15585 for(i=0; i<n_frames; i++)
15587 if(current_frame_pos == frame_set->n_frames)
15589 stat = tng_frame_set_read_next(tng_data, hash_mode);
15590 if(stat != TNG_SUCCESS)
15594 current_frame_pos = 0;
15596 for(j = 0; j < *n_values_per_frame; j++)
15598 len = strlen(data->strings[current_frame_pos][j]) + 1;
15599 (*values)[i][j].c = malloc(len);
15600 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15602 current_frame_pos++;
15606 size = sizeof(int);
15607 for(i=0; i<n_frames; i++)
15609 if(current_frame_pos == frame_set->n_frames)
15611 stat = tng_frame_set_read_next(tng_data, hash_mode);
15612 if(stat != TNG_SUCCESS)
15616 current_frame_pos = 0;
15618 for(j = 0; j < *n_values_per_frame; j++)
15620 (*values)[i][j].i = *(int *)((char *)data->values + size *
15621 (current_frame_pos *
15622 (*n_values_per_frame) + j));
15624 current_frame_pos++;
15627 case TNG_FLOAT_DATA:
15628 size = sizeof(float);
15629 for(i=0; i<n_frames; i++)
15631 if(current_frame_pos == frame_set->n_frames)
15633 stat = tng_frame_set_read_next(tng_data, hash_mode);
15634 if(stat != TNG_SUCCESS)
15638 current_frame_pos = 0;
15640 for(j = 0; j < *n_values_per_frame; j++)
15642 (*values)[i][j].f = *(float *)((char *)data->values + size *
15643 (current_frame_pos *
15644 (*n_values_per_frame) + j));
15646 current_frame_pos++;
15649 case TNG_DOUBLE_DATA:
15651 size = sizeof(double);
15652 for(i=0; i<n_frames; i++)
15654 if(current_frame_pos == frame_set->n_frames)
15656 stat = tng_frame_set_read_next(tng_data, hash_mode);
15657 if(stat != TNG_SUCCESS)
15661 current_frame_pos = 0;
15663 for(j = 0; j < *n_values_per_frame; j++)
15665 (*values)[i][j].d = *(double *)((char *)data->values + size *
15666 (current_frame_pos *
15667 (*n_values_per_frame) + j));
15669 current_frame_pos++;
15673 data->last_retrieved_frame = end_frame_nr;
15675 return(TNG_SUCCESS);
15678 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15679 (tng_trajectory_t tng_data,
15680 const int64_t block_id,
15681 const int64_t start_frame_nr,
15682 const int64_t end_frame_nr,
15683 const char hash_mode,
15685 int64_t *stride_length,
15686 int64_t *n_values_per_frame,
15689 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15690 int64_t file_pos, current_frame_pos, data_size, frame_size;
15691 int64_t last_frame_pos;
15693 tng_trajectory_frame_set_t frame_set;
15694 tng_non_particle_data_t np_data;
15695 tng_gen_block_t block;
15696 void *current_values = 0, *temp;
15697 tng_function_status stat;
15699 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15700 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15701 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15702 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15703 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15705 frame_set = &tng_data->current_trajectory_frame_set;
15706 first_frame = frame_set->first_frame;
15708 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15709 if(stat != TNG_SUCCESS)
15714 /* Do not re-read the frame set and only need the requested block. */
15715 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15716 stat = tng_data_find(tng_data, block_id, &np_data);
15717 if(first_frame != frame_set->first_frame ||
15718 stat != TNG_SUCCESS)
15720 tng_block_init(&block);
15721 if(stat != TNG_SUCCESS)
15723 fseek(tng_data->input_file,
15724 (long)tng_data->current_trajectory_frame_set_input_file_pos,
15726 stat = tng_block_header_read(tng_data, block);
15727 if(stat != TNG_SUCCESS)
15729 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15730 __FILE__, __LINE__);
15734 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15736 file_pos = ftell(tng_data->input_file);
15737 /* Read until next frame set block */
15738 stat = tng_block_header_read(tng_data, block);
15739 while(file_pos < tng_data->input_file_len &&
15740 stat != TNG_CRITICAL &&
15741 block->id != TNG_TRAJECTORY_FRAME_SET &&
15744 if(block->id == block_id)
15746 stat = tng_block_read_next(tng_data, block,
15748 if(stat != TNG_CRITICAL)
15750 file_pos = ftell(tng_data->input_file);
15751 if(file_pos < tng_data->input_file_len)
15753 stat = tng_block_header_read(tng_data, block);
15759 file_pos += block->block_contents_size + block->header_contents_size;
15760 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15761 if(file_pos < tng_data->input_file_len)
15763 stat = tng_block_header_read(tng_data, block);
15767 tng_block_destroy(&block);
15768 if(stat == TNG_CRITICAL)
15770 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15771 file_pos, __FILE__, __LINE__);
15776 stat = tng_data_find(tng_data, block_id, &np_data);
15777 if(stat != TNG_SUCCESS)
15782 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15783 &n_frames, stride_length,
15784 n_values_per_frame, type);
15786 if(stat != TNG_SUCCESS)
15790 free(current_values);
15795 if(n_frames == 1 && n_frames < frame_set->n_frames)
15801 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15806 case TNG_CHAR_DATA:
15807 return(TNG_FAILURE);
15809 size = sizeof(int64_t);
15811 case TNG_FLOAT_DATA:
15812 size = sizeof(float);
15814 case TNG_DOUBLE_DATA:
15816 size = sizeof(double);
15819 n_frames_div = (tot_n_frames % *stride_length) ?
15820 tot_n_frames / *stride_length + 1:
15821 tot_n_frames / *stride_length;
15822 data_size = n_frames_div * size * (*n_values_per_frame);
15824 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15825 size, n_frames_div, data_size);
15827 temp = realloc(*values, data_size);
15830 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15831 data_size, __FILE__, __LINE__);
15834 return(TNG_CRITICAL);
15839 if( n_frames == 1 && n_frames < frame_set->n_frames)
15841 memcpy(*values, current_values, size * (*n_values_per_frame));
15845 current_frame_pos = start_frame_nr - frame_set->first_frame;
15847 frame_size = size * (*n_values_per_frame);
15849 last_frame_pos = tng_min_i64(n_frames,
15850 end_frame_nr - start_frame_nr);
15852 n_frames_div = current_frame_pos / *stride_length;
15853 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15854 last_frame_pos / *stride_length + 1:
15855 last_frame_pos / *stride_length;
15856 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15858 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15859 n_frames_div_2 * frame_size);
15861 current_frame_pos += n_frames - current_frame_pos;
15863 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15865 stat = tng_frame_set_read_next(tng_data, hash_mode);
15866 if(stat != TNG_SUCCESS)
15870 free(current_values);
15877 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15878 &n_frames, stride_length,
15879 n_values_per_frame, type);
15881 if(stat != TNG_SUCCESS)
15885 free(current_values);
15892 last_frame_pos = tng_min_i64(n_frames,
15893 end_frame_nr - current_frame_pos);
15895 n_frames_div = current_frame_pos / *stride_length;
15896 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15897 last_frame_pos / *stride_length + 1:
15898 last_frame_pos / *stride_length;
15899 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15901 memcpy(((char *)*values) + n_frames_div * frame_size,
15903 n_frames_div_2 * frame_size);
15905 current_frame_pos += n_frames;
15911 free(current_values);
15914 np_data->last_retrieved_frame = end_frame_nr;
15916 return(TNG_SUCCESS);
15919 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15920 (tng_trajectory_t tng_data,
15921 const int64_t block_id,
15922 union data_values ****values,
15924 int64_t *n_particles,
15925 int64_t *n_values_per_frame,
15928 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15931 tng_particle_data_t data;
15932 tng_trajectory_frame_set_t frame_set;
15933 tng_gen_block_t block;
15934 char block_type_flag;
15935 tng_function_status stat;
15937 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15938 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15939 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15940 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15941 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15943 frame_set = &tng_data->current_trajectory_frame_set;
15948 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15950 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15952 block_type_flag = TNG_TRAJECTORY_BLOCK;
15956 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15959 tng_block_init(&block);
15960 file_pos = ftell(tng_data->input_file);
15961 /* Read all blocks until next frame set block */
15962 stat = tng_block_header_read(tng_data, block);
15963 while(file_pos < tng_data->input_file_len &&
15964 stat != TNG_CRITICAL &&
15965 block->id != TNG_TRAJECTORY_FRAME_SET &&
15968 /* Use hash by default */
15969 stat = tng_block_read_next(tng_data, block,
15971 if(stat != TNG_CRITICAL)
15973 file_pos = ftell(tng_data->input_file);
15974 if(file_pos < tng_data->input_file_len)
15976 stat = tng_block_header_read(tng_data, block);
15980 tng_block_destroy(&block);
15981 if(stat == TNG_CRITICAL)
15983 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15984 file_pos, __FILE__, __LINE__);
15988 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
15990 data = &frame_set->tr_particle_data[i];
15991 if(data->block_id == block_id)
15994 block_type_flag = TNG_TRAJECTORY_BLOCK;
15998 if(block_index < 0)
16000 return(TNG_FAILURE);
16005 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16007 block_type_flag = TNG_TRAJECTORY_BLOCK;
16011 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16015 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16016 tng_data->var_num_atoms_flag)
16018 *n_particles = frame_set->n_particles;
16022 *n_particles = tng_data->n_particles;
16025 *n_frames = tng_max_i64(1, data->n_frames);
16026 *n_values_per_frame = data->n_values_per_frame;
16027 *type = data->datatype;
16031 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16032 *n_particles, *n_values_per_frame,
16036 return(TNG_CRITICAL);
16040 /* It's not very elegant to reuse so much of the code in the different case
16041 * statements, but it's unnecessarily slow to have the switch-case block
16042 * inside the for loops. */
16045 case TNG_CHAR_DATA:
16046 for(i = 0; i < *n_frames; i++)
16048 for(j = 0; j < *n_particles; j++)
16050 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16051 for(k = 0; k < *n_values_per_frame; k++)
16053 len = strlen(data->strings[i][j][k]) + 1;
16054 (*values)[i][mapping][k].c = malloc(len);
16055 strncpy((*values)[i][mapping][k].c,
16056 data->strings[i][j][k], len);
16062 size = sizeof(int);
16063 i_step = (*n_particles) * (*n_values_per_frame);
16064 for(i = 0; i < *n_frames; i++)
16066 for(j = 0; j < *n_particles; j++)
16068 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16069 for(k = 0; k < *n_values_per_frame; k++)
16071 (*values)[i][mapping][k].i = *(int *)
16072 ((char *)data->values + size *
16074 (*n_values_per_frame) + k));
16079 case TNG_FLOAT_DATA:
16080 size = sizeof(float);
16081 i_step = (*n_particles) * (*n_values_per_frame);
16082 for(i = 0; i < *n_frames; i++)
16084 for(j = 0; j < *n_particles; j++)
16086 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16087 for(k = 0; k < *n_values_per_frame; k++)
16089 (*values)[i][mapping][k].f = *(float *)
16090 ((char *)data->values + size *
16092 (*n_values_per_frame) + k));
16097 case TNG_DOUBLE_DATA:
16099 size = sizeof(double);
16100 i_step = (*n_particles) * (*n_values_per_frame);
16101 for(i = 0; i < *n_frames; i++)
16103 for(j = 0; j < *n_particles; j++)
16105 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16106 for(k = 0; k < *n_values_per_frame; k++)
16108 (*values)[i][mapping][k].d = *(double *)
16109 ((char *)data->values + size *
16111 (*n_values_per_frame) + k));
16117 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16119 return(TNG_SUCCESS);
16122 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16123 (tng_trajectory_t tng_data,
16124 const int64_t block_id,
16127 int64_t *stride_length,
16128 int64_t *n_particles,
16129 int64_t *n_values_per_frame,
16132 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16133 int64_t block_index;
16135 tng_particle_data_t data;
16136 tng_trajectory_frame_set_t frame_set;
16137 tng_gen_block_t block;
16139 char block_type_flag;
16140 tng_function_status stat;
16142 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16143 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16144 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16145 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16146 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16148 frame_set = &tng_data->current_trajectory_frame_set;
16153 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16155 tng_block_init(&block);
16156 file_pos = ftell(tng_data->input_file);
16157 /* Read all blocks until next frame set block */
16158 stat = tng_block_header_read(tng_data, block);
16159 while(file_pos < tng_data->input_file_len &&
16160 stat != TNG_CRITICAL &&
16161 block->id != TNG_TRAJECTORY_FRAME_SET &&
16164 /* Use hash by default */
16165 stat = tng_block_read_next(tng_data, block,
16167 if(stat != TNG_CRITICAL)
16169 file_pos = ftell(tng_data->input_file);
16170 if(file_pos < tng_data->input_file_len)
16172 stat = tng_block_header_read(tng_data, block);
16176 tng_block_destroy(&block);
16177 if(stat == TNG_CRITICAL)
16179 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16180 file_pos, __FILE__, __LINE__);
16184 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16186 data = &frame_set->tr_particle_data[i];
16187 if(data->block_id == block_id)
16193 if(block_index < 0)
16195 return(TNG_FAILURE);
16199 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16201 block_type_flag = TNG_TRAJECTORY_BLOCK;
16205 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16208 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16209 tng_data->var_num_atoms_flag)
16211 *n_particles = frame_set->n_particles;
16215 *n_particles = tng_data->n_particles;
16218 *type = data->datatype;
16222 case TNG_CHAR_DATA:
16223 return(TNG_FAILURE);
16225 size = sizeof(int64_t);
16227 case TNG_FLOAT_DATA:
16228 size = sizeof(float);
16230 case TNG_DOUBLE_DATA:
16232 size = sizeof(double);
16235 *n_frames = tng_max_i64(1, data->n_frames);
16236 *n_values_per_frame = data->n_values_per_frame;
16237 *stride_length = data->stride_length;
16239 n_frames_div = (*n_frames % *stride_length) ?
16240 *n_frames / *stride_length + 1:
16241 *n_frames / *stride_length;
16243 data_size = n_frames_div * size * (*n_particles) *
16244 (*n_values_per_frame);
16246 temp = realloc(*values, data_size);
16249 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16250 data_size, __FILE__, __LINE__);
16253 return(TNG_CRITICAL);
16258 if(frame_set->n_mapping_blocks <= 0)
16260 memcpy(*values, data->values, data_size);
16264 i_step = (*n_particles) * (*n_values_per_frame);
16265 for(i = 0; i < *n_frames; i++)
16267 for(j = 0; j < *n_particles; j++)
16269 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16270 memcpy(((char *)*values) + size * (i * i_step + mapping *
16271 (*n_values_per_frame)),
16272 (char *)data->values + size *
16273 (i * i_step + j * (*n_values_per_frame)),
16274 size * (*n_values_per_frame));
16279 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16281 return(TNG_SUCCESS);
16284 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16285 (tng_trajectory_t tng_data,
16286 const int64_t block_id,
16287 const int64_t start_frame_nr,
16288 const int64_t end_frame_nr,
16289 const char hash_mode,
16290 union data_values ****values,
16291 int64_t *n_particles,
16292 int64_t *n_values_per_frame,
16295 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16296 int64_t first_frame, block_index;
16299 tng_particle_data_t data;
16300 tng_trajectory_frame_set_t frame_set;
16301 tng_gen_block_t block;
16302 char block_type_flag;
16303 tng_function_status stat;
16305 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16306 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16307 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16308 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16309 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16313 frame_set = &tng_data->current_trajectory_frame_set;
16314 first_frame = frame_set->first_frame;
16316 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16317 if(stat != TNG_SUCCESS)
16322 /* Do not re-read the frame set. */
16323 if(first_frame != frame_set->first_frame ||
16324 frame_set->n_particle_data_blocks <= 0)
16326 tng_block_init(&block);
16327 file_pos = ftell(tng_data->input_file);
16328 /* Read all blocks until next frame set block */
16329 stat = tng_block_header_read(tng_data, block);
16330 while(file_pos < tng_data->input_file_len &&
16331 stat != TNG_CRITICAL &&
16332 block->id != TNG_TRAJECTORY_FRAME_SET &&
16335 stat = tng_block_read_next(tng_data, block,
16337 if(stat != TNG_CRITICAL)
16339 file_pos = ftell(tng_data->input_file);
16340 if(file_pos < tng_data->input_file_len)
16342 stat = tng_block_header_read(tng_data, block);
16346 tng_block_destroy(&block);
16347 if(stat == TNG_CRITICAL)
16349 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16350 file_pos, __FILE__, __LINE__);
16355 /* See if there is already a data block of this ID.
16356 * Start checking the last read frame set */
16357 for(i = frame_set->n_particle_data_blocks; i-- ;)
16359 data = &frame_set->tr_particle_data[i];
16360 if(data->block_id == block_id)
16363 block_type_flag = TNG_TRAJECTORY_BLOCK;
16368 if(block_index < 0)
16370 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16371 block_id, __FILE__, __LINE__);
16372 return(TNG_FAILURE);
16375 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16376 tng_data->var_num_atoms_flag)
16378 *n_particles = frame_set->n_particles;
16382 *n_particles = tng_data->n_particles;
16385 n_frames = end_frame_nr - start_frame_nr + 1;
16386 *n_values_per_frame = data->n_values_per_frame;
16387 *type = data->datatype;
16391 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16392 *n_particles, *n_values_per_frame,
16396 return(TNG_CRITICAL);
16400 current_frame_pos = start_frame_nr - frame_set->first_frame;
16401 /* It's not very elegant to reuse so much of the code in the different case
16402 * statements, but it's unnecessarily slow to have the switch-case block
16403 * inside the for loops. */
16406 case TNG_CHAR_DATA:
16407 for(i=0; i<n_frames; i++)
16409 if(current_frame_pos == frame_set->n_frames)
16411 stat = tng_frame_set_read_next(tng_data, hash_mode);
16412 if(stat != TNG_SUCCESS)
16416 current_frame_pos = 0;
16418 for(j = 0; j < *n_particles; j++)
16420 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16421 for(k = 0; k < *n_values_per_frame; k++)
16423 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16424 (*values)[i][mapping][k].c = malloc(len);
16425 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16428 current_frame_pos++;
16432 size = sizeof(int);
16433 i_step = (*n_particles) * (*n_values_per_frame);
16434 for(i=0; i<n_frames; i++)
16436 if(current_frame_pos == frame_set->n_frames)
16438 stat = tng_frame_set_read_next(tng_data, hash_mode);
16439 if(stat != TNG_SUCCESS)
16443 current_frame_pos = 0;
16445 for(j = 0; j < *n_particles; j++)
16447 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16448 for(k = 0; k < *n_values_per_frame; k++)
16450 (*values)[i][mapping][k].i = *(int *)
16451 ((char *)data->values + size *
16452 (current_frame_pos *
16454 (*n_values_per_frame) + k));
16457 current_frame_pos++;
16460 case TNG_FLOAT_DATA:
16461 size = sizeof(float);
16462 i_step = (*n_particles) * (*n_values_per_frame);
16463 for(i=0; i<n_frames; i++)
16465 if(current_frame_pos == frame_set->n_frames)
16467 stat = tng_frame_set_read_next(tng_data, hash_mode);
16468 if(stat != TNG_SUCCESS)
16472 current_frame_pos = 0;
16474 for(j=0; j<*n_particles; j++)
16476 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16477 for(k=0; k<*n_values_per_frame; k++)
16479 (*values)[i][mapping][k].f = *(float *)
16480 ((char *)data->values + size *
16481 (current_frame_pos *
16483 (*n_values_per_frame) + k));
16486 current_frame_pos++;
16489 case TNG_DOUBLE_DATA:
16491 size = sizeof(double);
16492 i_step = (*n_particles) * (*n_values_per_frame);
16493 for(i=0; i<n_frames; i++)
16495 if(current_frame_pos == frame_set->n_frames)
16497 stat = tng_frame_set_read_next(tng_data, hash_mode);
16498 if(stat != TNG_SUCCESS)
16502 current_frame_pos = 0;
16504 for(j=0; j<*n_particles; j++)
16506 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16507 for(k=0; k<*n_values_per_frame; k++)
16509 (*values)[i][mapping][k].d = *(double *)
16510 ((char *)data->values + size *
16511 (current_frame_pos *
16513 (*n_values_per_frame) + k));
16516 current_frame_pos++;
16520 data->last_retrieved_frame = end_frame_nr;
16522 return(TNG_SUCCESS);
16525 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16526 (tng_trajectory_t tng_data,
16527 const int64_t block_id,
16528 const int64_t start_frame_nr,
16529 const int64_t end_frame_nr,
16530 const char hash_mode,
16532 int64_t *n_particles,
16533 int64_t *stride_length,
16534 int64_t *n_values_per_frame,
16537 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16538 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16540 tng_trajectory_frame_set_t frame_set;
16541 tng_particle_data_t p_data;
16542 tng_gen_block_t block;
16543 void *current_values = 0, *temp;
16544 tng_function_status stat;
16546 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16547 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16548 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16549 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16550 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16551 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16553 frame_set = &tng_data->current_trajectory_frame_set;
16554 first_frame = frame_set->first_frame;
16556 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16557 if(stat != TNG_SUCCESS)
16562 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16563 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16564 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16565 if(first_frame != frame_set->first_frame ||
16566 stat != TNG_SUCCESS)
16568 tng_block_init(&block);
16569 if(stat != TNG_SUCCESS)
16571 fseek(tng_data->input_file,
16572 (long)tng_data->current_trajectory_frame_set_input_file_pos,
16574 stat = tng_block_header_read(tng_data, block);
16575 if(stat != TNG_SUCCESS)
16577 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16578 __FILE__, __LINE__);
16582 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
16584 file_pos = ftell(tng_data->input_file);
16585 /* Read until next frame set block */
16586 stat = tng_block_header_read(tng_data, block);
16587 while(file_pos < tng_data->input_file_len &&
16588 stat != TNG_CRITICAL &&
16589 block->id != TNG_TRAJECTORY_FRAME_SET &&
16592 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16594 stat = tng_block_read_next(tng_data, block,
16596 if(stat != TNG_CRITICAL)
16598 file_pos = ftell(tng_data->input_file);
16599 if(file_pos < tng_data->input_file_len)
16601 stat = tng_block_header_read(tng_data, block);
16607 file_pos += block->block_contents_size + block->header_contents_size;
16608 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
16609 if(file_pos < tng_data->input_file_len)
16611 stat = tng_block_header_read(tng_data, block);
16615 tng_block_destroy(&block);
16616 if(stat == TNG_CRITICAL)
16618 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16619 file_pos, __FILE__, __LINE__);
16623 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16624 if(stat != TNG_SUCCESS)
16629 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16630 &n_frames, stride_length, n_particles,
16631 n_values_per_frame, type);
16633 if(stat != TNG_SUCCESS || *n_particles == 0)
16637 free(current_values);
16642 if(n_frames == 1 && n_frames < frame_set->n_frames)
16648 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16653 case TNG_CHAR_DATA:
16654 return(TNG_FAILURE);
16656 size = sizeof(int64_t);
16658 case TNG_FLOAT_DATA:
16659 size = sizeof(float);
16661 case TNG_DOUBLE_DATA:
16663 size = sizeof(double);
16666 n_frames_div = (tot_n_frames % *stride_length) ?
16667 tot_n_frames / *stride_length + 1:
16668 tot_n_frames / *stride_length;
16670 data_size = n_frames_div * size * (*n_particles) *
16671 (*n_values_per_frame);
16673 temp = realloc(*values, data_size);
16676 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16677 data_size, __FILE__, __LINE__);
16680 return(TNG_CRITICAL);
16685 if( n_frames == 1 && n_frames < frame_set->n_frames)
16687 memcpy(*values, current_values, size * (*n_particles) *
16688 (*n_values_per_frame));
16692 current_frame_pos = start_frame_nr - frame_set->first_frame;
16694 frame_size = size * (*n_particles) * (*n_values_per_frame);
16696 last_frame_pos = tng_min_i64(n_frames,
16697 end_frame_nr - start_frame_nr);
16699 n_frames_div = current_frame_pos / *stride_length;
16700 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16701 last_frame_pos / *stride_length + 1:
16702 last_frame_pos / *stride_length;
16703 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16705 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16706 n_frames_div_2 * frame_size);
16708 current_frame_pos += n_frames - current_frame_pos;
16710 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16712 stat = tng_frame_set_read_next(tng_data, hash_mode);
16713 if(stat != TNG_SUCCESS)
16717 free(current_values);
16724 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16725 &n_frames, stride_length, n_particles,
16726 n_values_per_frame, type);
16728 if(stat != TNG_SUCCESS)
16732 free(current_values);
16739 last_frame_pos = tng_min_i64(n_frames,
16740 end_frame_nr - current_frame_pos);
16742 n_frames_div = current_frame_pos / *stride_length;
16743 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16744 last_frame_pos / *stride_length + 1:
16745 last_frame_pos / *stride_length;
16746 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16748 memcpy(((char *)*values) + n_frames_div * frame_size,
16750 n_frames_div_2 * frame_size);
16752 current_frame_pos += n_frames;
16758 free(current_values);
16761 p_data->last_retrieved_frame = end_frame_nr;
16763 return(TNG_SUCCESS);
16766 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16767 (const tng_trajectory_t tng_data,
16768 const int64_t block_id,
16770 int64_t *stride_length)
16772 tng_function_status stat;
16773 tng_non_particle_data_t np_data;
16774 tng_particle_data_t p_data;
16775 long orig_file_pos, file_pos;
16776 int is_particle_data;
16778 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16785 stat = tng_frame_set_of_frame_find(tng_data, frame);
16786 if(stat != TNG_SUCCESS)
16791 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16792 stat = tng_data_find(tng_data, block_id, &np_data);
16793 if(stat != TNG_SUCCESS)
16795 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16796 if(stat != TNG_SUCCESS)
16798 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16799 /* If no specific frame was required read until this data block is found */
16802 file_pos = ftell(tng_data->input_file);
16803 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16805 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16806 file_pos = ftell(tng_data->input_file);
16809 if(stat != TNG_SUCCESS)
16811 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16815 stat = tng_data_find(tng_data, block_id, &np_data);
16816 if(stat != TNG_SUCCESS)
16818 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16819 if(stat != TNG_SUCCESS)
16821 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16827 is_particle_data = 1;
16832 is_particle_data = 0;
16837 is_particle_data = 1;
16842 is_particle_data = 0;
16844 if(is_particle_data)
16846 *stride_length = p_data->stride_length;
16850 *stride_length = np_data->stride_length;
16852 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16854 return(TNG_SUCCESS);
16857 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16858 (const tng_trajectory_t tng_data,
16861 struct tm *time_data;
16864 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16865 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16867 secs = tng_data->time;
16869 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16870 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16871 "%4d-%02d-%02d %02d:%02d:%02d",
16872 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16873 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16875 return(TNG_SUCCESS);
16879 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16880 (const char *filename,
16882 tng_trajectory_t *tng_data_p)
16884 tng_function_status stat;
16886 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16888 if(mode != 'r' && mode != 'w' && mode != 'a')
16890 return(TNG_FAILURE);
16893 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16895 tng_trajectory_destroy(tng_data_p);
16896 return(TNG_CRITICAL);
16899 if(mode == 'r' || mode == 'a')
16901 tng_input_file_set(*tng_data_p, filename);
16903 /* Read the file headers */
16904 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16906 tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16911 tng_output_file_set(*tng_data_p, filename);
16913 else if(mode == 'a')
16915 if((*tng_data_p)->output_file)
16917 fclose((*tng_data_p)->output_file);
16919 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
16920 fseek((*tng_data_p)->input_file,
16921 (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16924 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16925 if(stat != TNG_SUCCESS)
16927 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16928 __FILE__, __LINE__);
16930 (*tng_data_p)->output_file = 0;
16932 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16933 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16934 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16935 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16936 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16937 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16938 if((*tng_data_p)->input_file)
16940 fclose((*tng_data_p)->input_file);
16941 (*tng_data_p)->input_file = 0;
16943 if((*tng_data_p)->input_file_path)
16945 free((*tng_data_p)->input_file_path);
16946 (*tng_data_p)->input_file_path = 0;
16948 tng_output_append_file_set(*tng_data_p, filename);
16950 fseek((*tng_data_p)->output_file, 0, SEEK_END);
16953 return(TNG_SUCCESS);
16956 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
16957 (tng_trajectory_t *tng_data_p)
16959 tng_trajectory_frame_set_t frame_set;
16961 if(tng_data_p == 0)
16963 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
16964 __FILE__, __LINE__);
16965 return(TNG_FAILURE);
16968 if(*tng_data_p == 0)
16970 return(TNG_SUCCESS);
16973 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
16975 if(frame_set->n_unwritten_frames > 0)
16977 frame_set->n_frames = frame_set->n_unwritten_frames;
16978 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
16981 return(tng_trajectory_destroy(tng_data_p));
16984 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
16985 (tng_trajectory_t tng_data,
16986 const int64_t frame_nr,
16989 int64_t first_frame;
16990 tng_trajectory_frame_set_t frame_set;
16991 tng_function_status stat;
16993 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16994 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16996 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
16997 if(stat != TNG_SUCCESS)
16999 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
17000 frame_nr, __FILE__, __LINE__);
17004 frame_set = &tng_data->current_trajectory_frame_set;
17005 first_frame = frame_set->first_frame;
17007 if(tng_data->time_per_frame <= 0)
17009 return(TNG_FAILURE);
17012 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
17014 return(TNG_SUCCESS);
17018 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17019 (tng_trajectory_t tng_data,
17021 int64_t **molecule_cnt_list,
17022 tng_molecule_t *mols)
17024 tng_trajectory_frame_set_t frame_set;
17026 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17027 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17029 *n_mols = tng_data->n_molecules;
17031 frame_set = &tng_data->current_trajectory_frame_set;
17032 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17034 *molecule_cnt_list = frame_set->molecule_cnt_list;
17038 *molecule_cnt_list = tng_data->molecule_cnt_list;
17041 *mols = tng_data->molecules;
17043 return(TNG_SUCCESS);
17047 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17048 (tng_trajectory_t tng_data,
17051 tng_molecule_t *mol)
17053 tng_function_status stat;
17055 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17056 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17058 stat = tng_molecule_add(tng_data, name, mol);
17059 if(stat != TNG_SUCCESS)
17063 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17068 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17069 (tng_trajectory_t tng_data,
17070 const tng_molecule_t mol,
17071 int64_t *n_particles,
17076 char ***chain_names,
17077 int64_t **chain_ids)
17085 *n_particles = mol->n_atoms;
17087 *names = malloc(sizeof(char *) * *n_particles);
17088 *types = malloc(sizeof(char *) * *n_particles);
17089 *res_names = malloc(sizeof(char *) * *n_particles);
17090 *chain_names = malloc(sizeof(char *) * *n_particles);
17091 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17092 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17094 for(i = 0; i < *n_particles; i++)
17096 atom = &mol->atoms[i];
17097 res = atom->residue;
17098 chain = res->chain;
17099 (*names)[i] = malloc(strlen(atom->name));
17100 strcpy(*names[i], atom->name);
17101 (*types)[i] = malloc(strlen(atom->atom_type));
17102 strcpy(*types[i], atom->atom_type);
17103 (*res_names)[i] = malloc(strlen(res->name));
17104 strcpy(*res_names[i], res->name);
17105 (*chain_names)[i] = malloc(strlen(chain->name));
17106 strcpy(*chain_names[i], chain->name);
17107 (*res_ids)[i] = res->id;
17108 (*chain_ids)[i] = chain->id;
17111 return(TNG_SUCCESS);
17114 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17115 (tng_trajectory_t tng_data,
17116 tng_molecule_t mol,
17117 const int64_t n_particles,
17118 const char **names,
17119 const char **types,
17120 const char **res_names,
17121 const int64_t *res_ids,
17122 const char **chain_names,
17123 const int64_t *chain_ids)
17127 tng_residue_t residue;
17129 tng_function_status stat;
17131 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17132 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17133 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17134 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17135 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17136 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17137 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17139 for(i = 0; i < n_particles; i++)
17141 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17142 &chain) == TNG_FAILURE)
17144 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17146 if(stat != TNG_SUCCESS)
17151 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17152 &residue) == TNG_FAILURE)
17154 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17156 if(stat != TNG_SUCCESS)
17161 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17162 if(stat != TNG_SUCCESS)
17167 return(TNG_SUCCESS);
17170 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17171 (tng_trajectory_t tng_data,
17172 float **positions, int64_t *stride_length)
17174 int64_t n_frames, n_particles, n_values_per_frame;
17176 tng_function_status stat;
17178 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17179 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17180 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17182 stat = tng_num_frames_get(tng_data, &n_frames);
17183 if(stat != TNG_SUCCESS)
17188 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17189 0, n_frames - 1, TNG_USE_HASH,
17190 (void **)positions,
17193 &n_values_per_frame,
17199 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17200 (tng_trajectory_t tng_data,
17201 float **velocities, int64_t *stride_length)
17203 int64_t n_frames, n_particles, n_values_per_frame;
17205 tng_function_status stat;
17207 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17208 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17209 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17211 stat = tng_num_frames_get(tng_data, &n_frames);
17212 if(stat != TNG_SUCCESS)
17217 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17218 0, n_frames - 1, TNG_USE_HASH,
17219 (void **)velocities,
17222 &n_values_per_frame,
17228 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17229 (tng_trajectory_t tng_data,
17230 float **forces, int64_t *stride_length)
17232 int64_t n_frames, n_particles, n_values_per_frame;
17234 tng_function_status stat;
17236 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17237 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17238 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17240 stat = tng_num_frames_get(tng_data, &n_frames);
17241 if(stat != TNG_SUCCESS)
17246 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17247 0, n_frames - 1, TNG_USE_HASH,
17251 &n_values_per_frame,
17257 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17258 (tng_trajectory_t tng_data,
17260 int64_t *stride_length)
17262 int64_t n_frames, n_values_per_frame;
17264 tng_function_status stat;
17266 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17267 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17268 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17270 stat = tng_num_frames_get(tng_data, &n_frames);
17271 if(stat != TNG_SUCCESS)
17276 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17277 0, n_frames - 1, TNG_USE_HASH,
17278 (void **)box_shape,
17280 &n_values_per_frame,
17286 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17287 (tng_trajectory_t tng_data,
17288 const int64_t block_id,
17291 int64_t *retrieved_frame_number,
17292 double *retrieved_time)
17294 tng_trajectory_frame_set_t frame_set;
17295 tng_particle_data_t data = 0;
17296 tng_function_status stat;
17298 int64_t i, data_size, n_particles;
17302 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17303 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17304 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17305 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17306 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17308 frame_set = &tng_data->current_trajectory_frame_set;
17310 stat = tng_particle_data_find(tng_data, block_id, &data);
17311 if(stat != TNG_SUCCESS)
17313 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17314 file_pos = ftell(tng_data->input_file);
17315 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17317 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17318 file_pos = ftell(tng_data->input_file);
17320 if(stat != TNG_SUCCESS)
17324 stat = tng_particle_data_find(tng_data, block_id, &data);
17325 if(stat != TNG_SUCCESS)
17330 if(data->last_retrieved_frame < 0)
17332 fseek(tng_data->input_file,
17333 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17335 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17336 if(stat != TNG_SUCCESS)
17340 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17341 if(stat != TNG_SUCCESS)
17346 i = data->first_frame_with_data;
17350 if(data->n_frames == 1)
17352 i = data->last_retrieved_frame + 1;
17356 i = data->last_retrieved_frame + data->stride_length;
17358 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17360 stat = tng_frame_set_of_frame_find(tng_data, i);
17361 if(stat != TNG_SUCCESS)
17363 /* If the frame set search found the frame set after the starting
17364 * frame set there is a gap in the frame sets. So, even if the frame
17365 * was not found the next frame with data is still in the found
17367 if(stat == TNG_CRITICAL)
17371 i = frame_set->first_frame;
17374 if(data->last_retrieved_frame < frame_set->first_frame)
17376 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17377 if(stat != TNG_SUCCESS)
17383 data->last_retrieved_frame = i;
17384 *retrieved_frame_number = i;
17385 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17387 *retrieved_time = frame_set->first_frame_time +
17388 (i - frame_set->first_frame) *
17389 tng_data->time_per_frame;
17393 *retrieved_time = 0;
17396 if(data->stride_length > 1)
17398 i = (i - data->first_frame_with_data) / data->stride_length;
17402 i = (i - frame_set->first_frame);
17405 tng_num_particles_get(tng_data, &n_particles);
17407 *data_type = data->datatype;
17411 case TNG_CHAR_DATA:
17412 return(TNG_FAILURE);
17414 size = sizeof(int64_t);
17416 case TNG_FLOAT_DATA:
17417 size = sizeof(float);
17419 case TNG_DOUBLE_DATA:
17421 size = sizeof(double);
17424 data_size = size * n_particles * data->n_values_per_frame;
17426 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17427 // i, data_size, size, n_particles, data->n_values_per_frame);
17429 temp = realloc(*values, data_size);
17432 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17433 data_size, __FILE__, __LINE__);
17436 return(TNG_CRITICAL);
17441 memcpy(*values, (char *)data->values + i * data_size, data_size);
17443 return(TNG_SUCCESS);
17446 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17447 (tng_trajectory_t tng_data,
17448 const int64_t block_id,
17451 int64_t *retrieved_frame_number,
17452 double *retrieved_time)
17454 tng_trajectory_frame_set_t frame_set;
17455 tng_non_particle_data_t data = 0;
17456 tng_function_status stat;
17458 int64_t i, data_size;
17462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17463 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17464 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17465 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17466 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17468 frame_set = &tng_data->current_trajectory_frame_set;
17470 stat = tng_data_find(tng_data, block_id, &data);
17471 if(stat != TNG_SUCCESS)
17473 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17474 file_pos = ftell(tng_data->input_file);
17475 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17477 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17478 file_pos = ftell(tng_data->input_file);
17480 if(stat != TNG_SUCCESS)
17484 stat = tng_data_find(tng_data, block_id, &data);
17485 if(stat != TNG_SUCCESS)
17490 if(data->last_retrieved_frame < 0)
17492 fseek(tng_data->input_file,
17493 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17495 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17496 if(stat != TNG_SUCCESS)
17500 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17501 if(stat != TNG_SUCCESS)
17506 i = data->first_frame_with_data;
17510 if(data->n_frames == 1)
17512 i = data->last_retrieved_frame + 1;
17516 i = data->last_retrieved_frame + data->stride_length;
17518 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17520 stat = tng_frame_set_of_frame_find(tng_data, i);
17521 if(stat != TNG_SUCCESS)
17523 /* If the frame set search found the frame set after the starting
17524 * frame set there is a gap in the frame sets. So, even if the frame
17525 * was not found the next frame with data is still in the found
17527 if(stat == TNG_CRITICAL)
17531 i = frame_set->first_frame;
17534 if(data->last_retrieved_frame < frame_set->first_frame)
17536 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17537 if(stat != TNG_SUCCESS)
17543 data->last_retrieved_frame = i;
17544 *retrieved_frame_number = i;
17545 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17547 *retrieved_time = frame_set->first_frame_time +
17548 (i - frame_set->first_frame) *
17549 tng_data->time_per_frame;
17553 *retrieved_time = 0;
17556 if(data->stride_length > 1)
17558 i = (i - data->first_frame_with_data) / data->stride_length;
17562 i = (i - frame_set->first_frame);
17565 *data_type = data->datatype;
17569 case TNG_CHAR_DATA:
17570 return(TNG_FAILURE);
17572 size = sizeof(int64_t);
17574 case TNG_FLOAT_DATA:
17575 size = sizeof(float);
17577 case TNG_DOUBLE_DATA:
17579 size = sizeof(double);
17582 data_size = size * data->n_values_per_frame;
17584 temp = realloc(*values, data_size);
17587 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17588 data_size, __FILE__, __LINE__);
17591 return(TNG_CRITICAL);
17596 memcpy(*values, (char *)data->values + i * data_size, data_size);
17598 return(TNG_SUCCESS);
17601 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17602 (tng_trajectory_t tng_data,
17603 const int64_t first_frame,
17604 const int64_t last_frame,
17606 int64_t *stride_length)
17608 int64_t n_particles, n_values_per_frame;
17610 tng_function_status stat;
17612 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17613 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17614 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17615 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17617 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17618 first_frame, last_frame,
17620 (void **)positions,
17623 &n_values_per_frame,
17629 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17630 (tng_trajectory_t tng_data,
17631 const int64_t first_frame,
17632 const int64_t last_frame,
17633 float **velocities,
17634 int64_t *stride_length)
17636 int64_t n_particles, n_values_per_frame;
17638 tng_function_status stat;
17640 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17641 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17642 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17643 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17645 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17646 first_frame, last_frame,
17648 (void **)velocities,
17651 &n_values_per_frame,
17657 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17658 (tng_trajectory_t tng_data,
17659 const int64_t first_frame,
17660 const int64_t last_frame,
17662 int64_t *stride_length)
17664 int64_t n_particles, n_values_per_frame;
17666 tng_function_status stat;
17668 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17669 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17670 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17671 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17673 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17674 first_frame, last_frame,
17679 &n_values_per_frame,
17685 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17686 (tng_trajectory_t tng_data,
17687 const int64_t first_frame,
17688 const int64_t last_frame,
17690 int64_t *stride_length)
17692 int64_t n_values_per_frame;
17694 tng_function_status stat;
17696 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17697 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17698 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17699 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17701 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17702 first_frame, last_frame,
17704 (void **)box_shape,
17706 &n_values_per_frame,
17712 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17713 (tng_trajectory_t tng_data,
17715 const int64_t n_values_per_frame,
17716 const int64_t block_id,
17717 const char *block_name,
17718 const char particle_dependency,
17719 const char compression)
17721 tng_trajectory_frame_set_t frame_set;
17722 tng_particle_data_t p_data;
17723 tng_non_particle_data_t np_data;
17724 int64_t n_particles, n_frames;
17725 tng_function_status stat;
17727 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17728 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17732 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17733 i, __FILE__, __LINE__);
17734 return(TNG_FAILURE);
17737 frame_set = &tng_data->current_trajectory_frame_set;
17739 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17741 n_frames = tng_data->frame_set_n_frames;
17743 stat = tng_frame_set_new(tng_data, 0, n_frames);
17744 if(stat != TNG_SUCCESS)
17746 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17753 n_frames = frame_set->n_frames;
17756 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17758 tng_num_particles_get(tng_data, &n_particles);
17759 if(n_particles <= 0)
17761 return(TNG_FAILURE);
17764 if(tng_particle_data_find(tng_data, block_id, &p_data)
17767 stat = tng_particle_data_block_add(tng_data, block_id,
17770 TNG_TRAJECTORY_BLOCK,
17771 n_frames, n_values_per_frame, i,
17774 if(stat != TNG_SUCCESS)
17776 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17777 __FILE__, __LINE__);
17780 p_data = &frame_set->tr_particle_data[frame_set->
17781 n_particle_data_blocks - 1];
17782 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17784 n_values_per_frame);
17785 if(stat != TNG_SUCCESS)
17787 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17788 __FILE__, __LINE__);
17794 if(p_data->stride_length != i)
17796 p_data->stride_length = i;
17797 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17799 n_values_per_frame);
17800 if(stat != TNG_SUCCESS)
17802 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17803 __FILE__, __LINE__);
17811 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17813 stat = tng_data_block_add(tng_data, block_id, block_name,
17814 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17815 n_frames, n_values_per_frame,
17816 i, compression, 0);
17817 if(stat != TNG_SUCCESS)
17819 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17820 __FILE__, __LINE__);
17823 np_data = &frame_set->tr_data[frame_set->
17824 n_data_blocks - 1];
17825 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17826 i, n_values_per_frame);
17827 if(stat != TNG_SUCCESS)
17829 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17830 __FILE__, __LINE__);
17836 if(np_data->stride_length != i)
17838 np_data->stride_length = i;
17839 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17840 i, n_values_per_frame);
17841 if(stat != TNG_SUCCESS)
17843 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17844 __FILE__, __LINE__);
17851 return(TNG_SUCCESS);
17854 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17855 (tng_trajectory_t tng_data,
17857 const int64_t n_values_per_frame,
17858 const int64_t block_id,
17859 const char *block_name,
17860 const char particle_dependency,
17861 const char compression)
17863 tng_trajectory_frame_set_t frame_set;
17864 tng_particle_data_t p_data;
17865 tng_non_particle_data_t np_data;
17866 int64_t n_particles, n_frames;
17867 tng_function_status stat;
17869 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17870 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17874 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17875 i, __FILE__, __LINE__);
17876 return(TNG_FAILURE);
17879 frame_set = &tng_data->current_trajectory_frame_set;
17881 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17883 n_frames = tng_data->frame_set_n_frames;
17885 stat = tng_frame_set_new(tng_data, 0, n_frames);
17886 if(stat != TNG_SUCCESS)
17888 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17895 n_frames = frame_set->n_frames;
17898 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17900 tng_num_particles_get(tng_data, &n_particles);
17902 if(n_particles <= 0)
17904 return(TNG_FAILURE);
17907 if(tng_particle_data_find(tng_data, block_id, &p_data)
17910 stat = tng_particle_data_block_add(tng_data, block_id,
17913 TNG_TRAJECTORY_BLOCK,
17914 n_frames, n_values_per_frame, i,
17917 if(stat != TNG_SUCCESS)
17919 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17920 __FILE__, __LINE__);
17923 p_data = &frame_set->tr_particle_data[frame_set->
17924 n_particle_data_blocks - 1];
17925 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17927 n_values_per_frame);
17928 if(stat != TNG_SUCCESS)
17930 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17931 __FILE__, __LINE__);
17937 p_data->stride_length = i;
17942 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17944 stat = tng_data_block_add(tng_data, block_id, block_name,
17945 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
17946 n_frames, n_values_per_frame,
17947 i, compression, 0);
17948 if(stat != TNG_SUCCESS)
17950 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17951 __FILE__, __LINE__);
17954 np_data = &frame_set->tr_data[frame_set->
17955 n_data_blocks - 1];
17956 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17957 i, n_values_per_frame);
17958 if(stat != TNG_SUCCESS)
17960 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17961 __FILE__, __LINE__);
17967 np_data->stride_length = i;
17971 return(TNG_SUCCESS);
17974 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
17975 (tng_trajectory_t tng_data,
17977 const int64_t n_values_per_frame,
17978 const int64_t block_id,
17979 const char *block_name,
17980 const char particle_dependency,
17981 const char compression)
17983 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
17984 "See documentation. %s: %d", __FILE__, __LINE__);
17985 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
17986 block_id, block_name,
17987 particle_dependency,
17990 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
17991 (tng_trajectory_t tng_data,
17994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17995 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17997 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17998 TNG_TRAJ_POSITIONS,
18000 TNG_PARTICLE_BLOCK_DATA,
18001 TNG_TNG_COMPRESSION));
18004 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18005 (tng_trajectory_t tng_data,
18008 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18009 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18011 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18012 TNG_TRAJ_POSITIONS,
18014 TNG_PARTICLE_BLOCK_DATA,
18015 TNG_TNG_COMPRESSION));
18018 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18019 (tng_trajectory_t tng_data,
18022 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18023 "See documentation. %s: %d", __FILE__, __LINE__);
18024 return(tng_util_pos_write_interval_set(tng_data, i));
18027 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18028 (tng_trajectory_t tng_data,
18031 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18032 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18034 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18035 TNG_TRAJ_VELOCITIES,
18037 TNG_PARTICLE_BLOCK_DATA,
18038 TNG_TNG_COMPRESSION));
18041 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18042 (tng_trajectory_t tng_data,
18045 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18046 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18048 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18049 TNG_TRAJ_VELOCITIES,
18051 TNG_PARTICLE_BLOCK_DATA,
18052 TNG_TNG_COMPRESSION));
18055 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18056 (tng_trajectory_t tng_data,
18059 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18060 "See documentation. %s: %d", __FILE__, __LINE__);
18061 return(tng_util_vel_write_interval_set(tng_data, i));
18064 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18065 (tng_trajectory_t tng_data,
18068 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18069 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18071 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18074 TNG_PARTICLE_BLOCK_DATA,
18075 TNG_GZIP_COMPRESSION));
18078 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18079 (tng_trajectory_t tng_data,
18082 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18083 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18085 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18088 TNG_PARTICLE_BLOCK_DATA,
18089 TNG_GZIP_COMPRESSION));
18092 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18093 (tng_trajectory_t tng_data,
18096 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18097 "See documentation. %s: %d", __FILE__, __LINE__);
18098 return(tng_util_force_write_interval_set(tng_data, i));
18101 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18102 (tng_trajectory_t tng_data,
18105 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18106 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18108 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18109 TNG_TRAJ_BOX_SHAPE,
18111 TNG_NON_PARTICLE_BLOCK_DATA,
18112 TNG_GZIP_COMPRESSION));
18115 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18116 (tng_trajectory_t tng_data,
18119 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18120 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18122 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18123 TNG_TRAJ_BOX_SHAPE,
18125 TNG_NON_PARTICLE_BLOCK_DATA,
18126 TNG_GZIP_COMPRESSION));
18129 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18130 (tng_trajectory_t tng_data,
18133 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18134 "See documentation. %s: %d", __FILE__, __LINE__);
18135 return(tng_util_box_shape_write_interval_set(tng_data, i));
18138 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18139 (tng_trajectory_t tng_data,
18140 const int64_t frame_nr,
18141 const float *values,
18142 const int64_t n_values_per_frame,
18143 const int64_t block_id,
18144 const char *block_name,
18145 const char particle_dependency,
18146 const char compression)
18148 tng_trajectory_frame_set_t frame_set;
18149 tng_particle_data_t p_data;
18150 tng_non_particle_data_t np_data;
18151 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18152 int64_t last_frame;
18153 int is_first_frame_flag = 0;
18154 char block_type_flag;
18155 tng_function_status stat;
18157 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18158 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18159 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18161 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18163 tng_num_particles_get(tng_data, &n_particles);
18164 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18169 return(TNG_FAILURE);
18172 frame_set = &tng_data->current_trajectory_frame_set;
18176 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18177 n_frames = stride_length = 1;
18181 block_type_flag = TNG_TRAJECTORY_BLOCK;
18183 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18185 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18186 if(stat != TNG_SUCCESS)
18188 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18193 last_frame = frame_set->first_frame +
18194 frame_set->n_frames - 1;
18195 if(frame_nr > last_frame)
18197 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18198 if(stat != TNG_SUCCESS)
18200 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18204 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18206 last_frame = frame_nr - 1;
18208 stat = tng_frame_set_new(tng_data, last_frame + 1,
18209 tng_data->frame_set_n_frames);
18210 if(stat != TNG_SUCCESS)
18212 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18217 if(frame_set->n_unwritten_frames == 0)
18219 is_first_frame_flag = 1;
18221 frame_set->n_unwritten_frames = frame_nr -
18222 frame_set->first_frame + 1;
18224 n_frames = frame_set->n_frames;
18227 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18229 if(tng_particle_data_find(tng_data, block_id, &p_data)
18232 stat = tng_particle_data_block_add(tng_data, block_id,
18236 n_frames, n_values_per_frame,
18240 if(stat != TNG_SUCCESS)
18242 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18243 __FILE__, __LINE__);
18246 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18248 p_data = &frame_set->tr_particle_data[frame_set->
18249 n_particle_data_blocks - 1];
18253 p_data = &tng_data->non_tr_particle_data[tng_data->
18254 n_particle_data_blocks - 1];
18256 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18257 stride_length, n_particles,
18258 n_values_per_frame);
18259 if(stat != TNG_SUCCESS)
18261 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18262 __FILE__, __LINE__);
18267 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18269 stride_length = p_data->stride_length;
18271 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18273 p_data->first_frame_with_data = frame_nr;
18278 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18281 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18282 n_values_per_frame, values, sizeof(float) *
18283 n_particles * n_values_per_frame);
18287 memcpy(p_data->values, values, sizeof(float) * n_particles *
18288 n_values_per_frame);
18293 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18295 stat = tng_data_block_add(tng_data, block_id, block_name,
18296 TNG_FLOAT_DATA, block_type_flag,
18297 n_frames, n_values_per_frame,
18298 stride_length, compression, 0);
18299 if(stat != TNG_SUCCESS)
18301 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18302 __FILE__, __LINE__);
18305 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18307 np_data = &frame_set->tr_data[frame_set->
18308 n_data_blocks - 1];
18312 np_data = &tng_data->non_tr_data[tng_data->
18313 n_data_blocks - 1];
18315 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18316 stride_length, n_values_per_frame);
18317 if(stat != TNG_SUCCESS)
18319 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18320 __FILE__, __LINE__);
18325 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18327 stride_length = np_data->stride_length;
18329 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18331 np_data->first_frame_with_data = frame_nr;
18336 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18339 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18340 n_values_per_frame, values, sizeof(float) *
18341 n_values_per_frame);
18345 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18349 return(TNG_SUCCESS);
18352 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18353 (tng_trajectory_t tng_data,
18354 const int64_t frame_nr,
18355 const double *values,
18356 const int64_t n_values_per_frame,
18357 const int64_t block_id,
18358 const char *block_name,
18359 const char particle_dependency,
18360 const char compression)
18362 tng_trajectory_frame_set_t frame_set;
18363 tng_particle_data_t p_data;
18364 tng_non_particle_data_t np_data;
18365 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18366 int64_t last_frame;
18367 int is_first_frame_flag = 0;
18368 char block_type_flag;
18369 tng_function_status stat;
18371 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18372 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18373 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18375 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18377 tng_num_particles_get(tng_data, &n_particles);
18378 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18383 return(TNG_FAILURE);
18386 frame_set = &tng_data->current_trajectory_frame_set;
18390 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18391 n_frames = stride_length = 1;
18395 block_type_flag = TNG_TRAJECTORY_BLOCK;
18397 n_frames = tng_data->frame_set_n_frames;
18399 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18401 stat = tng_frame_set_new(tng_data, 0, n_frames);
18402 if(stat != TNG_SUCCESS)
18404 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18411 n_frames = frame_set->n_frames;
18413 last_frame = frame_set->first_frame +
18414 frame_set->n_frames - 1;
18415 if(frame_nr > last_frame)
18417 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18418 if(stat != TNG_SUCCESS)
18420 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18424 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18426 last_frame = frame_nr - 1;
18428 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18429 if(stat != TNG_SUCCESS)
18431 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18436 if(frame_set->n_unwritten_frames == 0)
18438 is_first_frame_flag = 1;
18440 frame_set->n_unwritten_frames = frame_nr -
18441 frame_set->first_frame + 1;
18444 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18446 if(tng_particle_data_find(tng_data, block_id, &p_data)
18449 stat = tng_particle_data_block_add(tng_data, block_id,
18453 n_frames, n_values_per_frame,
18457 if(stat != TNG_SUCCESS)
18459 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18460 __FILE__, __LINE__);
18463 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18465 p_data = &frame_set->tr_particle_data[frame_set->
18466 n_particle_data_blocks - 1];
18470 p_data = &tng_data->non_tr_particle_data[tng_data->
18471 n_particle_data_blocks - 1];
18473 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18474 stride_length, n_particles,
18475 n_values_per_frame);
18476 if(stat != TNG_SUCCESS)
18478 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18479 __FILE__, __LINE__);
18484 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18486 stride_length = p_data->stride_length;
18488 if(is_first_frame_flag)
18490 p_data->first_frame_with_data = frame_nr;
18495 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18498 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18499 n_values_per_frame, values, sizeof(double) *
18500 n_particles * n_values_per_frame);
18504 memcpy(p_data->values, values, sizeof(double) * n_particles *
18505 n_values_per_frame);
18510 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18512 stat = tng_data_block_add(tng_data, block_id, block_name,
18513 TNG_DOUBLE_DATA, block_type_flag,
18514 n_frames, n_values_per_frame,
18515 stride_length, compression, 0);
18516 if(stat != TNG_SUCCESS)
18518 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18519 __FILE__, __LINE__);
18522 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18524 np_data = &frame_set->tr_data[frame_set->
18525 n_data_blocks - 1];
18529 np_data = &tng_data->non_tr_data[tng_data->
18530 n_data_blocks - 1];
18532 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18533 stride_length, n_values_per_frame);
18534 if(stat != TNG_SUCCESS)
18536 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18537 __FILE__, __LINE__);
18542 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18544 stride_length = np_data->stride_length;
18546 if(is_first_frame_flag)
18548 np_data->first_frame_with_data = frame_nr;
18553 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18556 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18557 n_values_per_frame, values, sizeof(double) *
18558 n_values_per_frame);
18562 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18566 return(TNG_SUCCESS);
18569 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18570 (tng_trajectory_t tng_data,
18571 const int64_t frame_nr,
18572 const float *positions)
18574 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18575 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18576 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18578 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18579 TNG_TRAJ_POSITIONS, "POSITIONS",
18580 TNG_PARTICLE_BLOCK_DATA,
18581 TNG_TNG_COMPRESSION));
18584 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18585 (tng_trajectory_t tng_data,
18586 const int64_t frame_nr,
18587 const double *positions)
18589 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18590 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18591 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18593 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18594 TNG_TRAJ_POSITIONS, "POSITIONS",
18595 TNG_PARTICLE_BLOCK_DATA,
18596 TNG_TNG_COMPRESSION));
18599 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18600 (tng_trajectory_t tng_data,
18601 const int64_t frame_nr,
18602 const float *velocities)
18604 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18605 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18606 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18608 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18609 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18610 TNG_PARTICLE_BLOCK_DATA,
18611 TNG_TNG_COMPRESSION));
18614 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18615 (tng_trajectory_t tng_data,
18616 const int64_t frame_nr,
18617 const double *velocities)
18619 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18620 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18621 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18623 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18624 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18625 TNG_PARTICLE_BLOCK_DATA,
18626 TNG_TNG_COMPRESSION));
18629 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18630 (tng_trajectory_t tng_data,
18631 const int64_t frame_nr,
18632 const float *forces)
18634 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18635 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18636 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18638 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18639 TNG_TRAJ_FORCES, "FORCES",
18640 TNG_PARTICLE_BLOCK_DATA,
18641 TNG_GZIP_COMPRESSION));
18644 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18645 (tng_trajectory_t tng_data,
18646 const int64_t frame_nr,
18647 const double *forces)
18649 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18650 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18651 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18653 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18654 TNG_TRAJ_FORCES, "FORCES",
18655 TNG_PARTICLE_BLOCK_DATA,
18656 TNG_GZIP_COMPRESSION));
18659 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18660 (tng_trajectory_t tng_data,
18661 const int64_t frame_nr,
18662 const float *box_shape)
18664 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18665 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18666 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18668 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18669 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18670 TNG_NON_PARTICLE_BLOCK_DATA,
18671 TNG_GZIP_COMPRESSION));
18674 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18675 (tng_trajectory_t tng_data,
18676 const int64_t frame_nr,
18677 const double *box_shape)
18679 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18680 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18681 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18683 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18684 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18685 TNG_NON_PARTICLE_BLOCK_DATA,
18686 TNG_GZIP_COMPRESSION));
18689 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18690 (tng_trajectory_t tng_data,
18691 const int64_t frame_nr,
18693 const float *values,
18694 const int64_t n_values_per_frame,
18695 const int64_t block_id,
18696 const char *block_name,
18697 const char particle_dependency,
18698 const char compression)
18700 tng_trajectory_frame_set_t frame_set;
18701 tng_function_status stat;
18703 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18704 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18705 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18706 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18708 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18709 block_id, block_name,
18710 particle_dependency,
18713 if(stat != TNG_SUCCESS)
18718 frame_set = &tng_data->current_trajectory_frame_set;
18720 /* first_frame_time is -1 when it is not yet set. */
18721 if(frame_set->first_frame_time < -0.1)
18723 if(frame_nr > frame_set->first_frame)
18725 stat = tng_frame_set_first_frame_time_set(tng_data,
18728 frame_set->first_frame) *
18729 tng_data->time_per_frame);
18733 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18739 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18740 (tng_trajectory_t tng_data,
18741 const int64_t frame_nr,
18743 const double *values,
18744 const int64_t n_values_per_frame,
18745 const int64_t block_id,
18746 const char *block_name,
18747 const char particle_dependency,
18748 const char compression)
18750 tng_trajectory_frame_set_t frame_set;
18751 tng_function_status stat;
18753 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18754 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18755 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18756 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18758 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18759 block_id, block_name,
18760 particle_dependency,
18763 if(stat != TNG_SUCCESS)
18768 frame_set = &tng_data->current_trajectory_frame_set;
18770 /* first_frame_time is -1 when it is not yet set. */
18771 if(frame_set->first_frame_time < -0.1)
18773 if(frame_nr > frame_set->first_frame)
18775 stat = tng_frame_set_first_frame_time_set(tng_data,
18778 frame_set->first_frame) *
18779 tng_data->time_per_frame);
18783 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18789 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18790 (tng_trajectory_t tng_data,
18791 const int64_t frame_nr,
18793 const float *positions)
18795 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18796 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18797 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18798 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18800 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18801 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18802 TNG_PARTICLE_BLOCK_DATA,
18803 TNG_TNG_COMPRESSION));
18806 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18807 (tng_trajectory_t tng_data,
18808 const int64_t frame_nr,
18810 const double *positions)
18812 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18813 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18814 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18815 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18817 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18819 TNG_TRAJ_POSITIONS,
18821 TNG_PARTICLE_BLOCK_DATA,
18822 TNG_TNG_COMPRESSION));
18825 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18826 (tng_trajectory_t tng_data,
18827 const int64_t frame_nr,
18829 const float *velocities)
18831 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18832 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18833 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18834 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18836 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18838 TNG_TRAJ_VELOCITIES,
18840 TNG_PARTICLE_BLOCK_DATA,
18841 TNG_TNG_COMPRESSION));
18844 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18845 (tng_trajectory_t tng_data,
18846 const int64_t frame_nr,
18848 const double *velocities)
18850 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18851 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18852 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18853 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18855 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18857 TNG_TRAJ_VELOCITIES,
18859 TNG_PARTICLE_BLOCK_DATA,
18860 TNG_TNG_COMPRESSION));
18863 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18864 (tng_trajectory_t tng_data,
18865 const int64_t frame_nr,
18867 const float *forces)
18869 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18870 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18871 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18872 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18874 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18875 3, TNG_TRAJ_FORCES, "FORCES",
18876 TNG_PARTICLE_BLOCK_DATA,
18877 TNG_GZIP_COMPRESSION));
18880 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18881 (tng_trajectory_t tng_data,
18882 const int64_t frame_nr,
18884 const double *forces)
18886 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18887 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18888 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18889 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18891 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18893 TNG_TRAJ_FORCES, "FORCES",
18894 TNG_PARTICLE_BLOCK_DATA,
18895 TNG_GZIP_COMPRESSION));
18898 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18899 (tng_trajectory_t tng_data,
18900 const int64_t frame_nr,
18902 const float *box_shape)
18904 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18905 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18906 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18907 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18909 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18910 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18911 TNG_NON_PARTICLE_BLOCK_DATA,
18912 TNG_GZIP_COMPRESSION));
18915 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18916 (tng_trajectory_t tng_data,
18917 const int64_t frame_nr,
18919 const double *box_shape)
18921 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18922 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18923 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18924 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18926 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18927 time, box_shape, 9,
18928 TNG_TRAJ_BOX_SHAPE,
18930 TNG_NON_PARTICLE_BLOCK_DATA,
18931 TNG_GZIP_COMPRESSION));
18934 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18935 (tng_trajectory_t tng_data,
18936 const int64_t block_id,
18940 tng_trajectory_frame_set_t frame_set;
18941 tng_particle_data_t p_data = 0;
18942 tng_non_particle_data_t np_data = 0;
18943 tng_function_status stat;
18945 int block_type = -1;
18947 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18948 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
18949 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
18951 frame_set = &tng_data->current_trajectory_frame_set;
18953 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18954 if(stat == TNG_SUCCESS)
18956 block_type = TNG_PARTICLE_BLOCK_DATA;
18960 stat = tng_data_find(tng_data, block_id, &np_data);
18961 if(stat == TNG_SUCCESS)
18963 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18967 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18968 if(stat != TNG_SUCCESS)
18972 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18973 if(stat == TNG_SUCCESS)
18975 block_type = TNG_PARTICLE_BLOCK_DATA;
18979 stat = tng_data_find(tng_data, block_id, &np_data);
18980 if(stat == TNG_SUCCESS)
18982 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18991 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18993 if(p_data->last_retrieved_frame < 0)
18995 i = p_data->first_frame_with_data;
18999 i = p_data->last_retrieved_frame;
19002 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19004 if(np_data->last_retrieved_frame < 0)
19006 i = np_data->first_frame_with_data;
19010 i = np_data->last_retrieved_frame;
19015 return(TNG_FAILURE);
19017 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
19019 stat = tng_frame_set_of_frame_find(tng_data, i);
19020 if(stat != TNG_SUCCESS)
19024 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19025 if(stat != TNG_SUCCESS)
19027 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19028 __FILE__, __LINE__);
19032 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19034 *codec_id = p_data->codec_id;
19035 *factor = p_data->compression_multiplier;
19037 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19039 *codec_id = np_data->codec_id;
19040 *factor = np_data->compression_multiplier;
19042 return(TNG_SUCCESS);
19045 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19046 (tng_trajectory_t tng_data,
19047 int64_t current_frame,
19048 const int64_t n_requested_data_block_ids,
19049 const int64_t *requested_data_block_ids,
19050 int64_t *next_frame,
19051 int64_t *n_data_blocks_in_next_frame,
19052 int64_t **data_block_ids_in_next_frame)
19054 tng_trajectory_frame_set_t frame_set;
19055 tng_function_status stat;
19056 tng_particle_data_t p_data;
19057 tng_non_particle_data_t np_data;
19058 tng_gen_block_t block;
19059 int64_t i, j, block_id, *temp;
19060 int64_t data_frame, frame_diff, min_diff;
19061 int64_t size, frame_set_file_pos;
19062 int found, read_all = 0;
19065 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19066 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19067 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19068 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19070 if(n_requested_data_block_ids)
19072 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.");
19073 size = sizeof(int64_t) * n_requested_data_block_ids;
19074 temp = realloc(*data_block_ids_in_next_frame, size);
19077 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19078 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19079 __FILE__, __LINE__);
19080 free(*data_block_ids_in_next_frame);
19081 *data_block_ids_in_next_frame = 0;
19082 return(TNG_CRITICAL);
19084 *data_block_ids_in_next_frame = temp;
19087 frame_set = &tng_data->current_trajectory_frame_set;
19089 current_frame += 1;
19091 if(current_frame < frame_set->first_frame ||
19092 current_frame >= frame_set->first_frame + frame_set->n_frames)
19094 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19095 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19096 if(stat != TNG_SUCCESS)
19098 /* If the frame set search found the frame set after the starting
19099 * frame set there is a gap in the frame sets. So, even if the frame
19100 * was not found the next frame with data is still in the found
19102 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19103 frame_set_file_pos)
19107 current_frame = frame_set->first_frame;
19111 /* Check for data blocks only if they have not already been found. */
19112 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19114 file_pos = ftell(tng_data->input_file);
19115 if(file_pos < tng_data->input_file_len)
19117 tng_block_init(&block);
19118 stat = tng_block_header_read(tng_data, block);
19119 while(file_pos < tng_data->input_file_len &&
19120 stat != TNG_CRITICAL &&
19121 block->id != TNG_TRAJECTORY_FRAME_SET &&
19124 stat = tng_block_read_next(tng_data, block,
19126 if(stat != TNG_CRITICAL)
19128 file_pos = ftell(tng_data->input_file);
19129 if(file_pos < tng_data->input_file_len)
19131 stat = tng_block_header_read(tng_data, block);
19135 tng_block_destroy(&block);
19136 if(stat == TNG_CRITICAL)
19138 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
19139 file_pos, __FILE__, __LINE__);
19148 *n_data_blocks_in_next_frame = 0;
19150 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19152 p_data = &frame_set->tr_particle_data[i];
19153 block_id = p_data->block_id;
19155 if(n_requested_data_block_ids > 0)
19158 for(j = 0; j < n_requested_data_block_ids; j++)
19160 if(block_id == requested_data_block_ids[j])
19172 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19173 p_data->last_retrieved_frame >=
19174 frame_set->first_frame + frame_set->n_frames))
19176 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19177 TNG_USE_HASH, block_id);
19178 if(stat == TNG_CRITICAL)
19180 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19181 __FILE__, __LINE__);
19184 if(stat == TNG_FAILURE)
19189 if(frame_set->first_frame != current_frame &&
19190 p_data->last_retrieved_frame >= 0)
19192 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19196 data_frame = p_data->first_frame_with_data;
19198 frame_diff = data_frame - current_frame;
19203 if(min_diff == -1 || frame_diff <= min_diff)
19205 if(frame_diff < min_diff)
19207 *n_data_blocks_in_next_frame = 1;
19211 *n_data_blocks_in_next_frame += 1;
19213 if(n_requested_data_block_ids <= 0)
19215 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19216 temp = realloc(*data_block_ids_in_next_frame, size);
19219 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19220 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19221 __FILE__, __LINE__);
19222 free(*data_block_ids_in_next_frame);
19223 *data_block_ids_in_next_frame = 0;
19224 return(TNG_CRITICAL);
19226 *data_block_ids_in_next_frame = temp;
19230 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19232 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19234 min_diff = frame_diff;
19237 for(i = 0; i < frame_set->n_data_blocks; i++)
19239 np_data = &frame_set->tr_data[i];
19240 block_id = np_data->block_id;
19242 if(n_requested_data_block_ids > 0)
19245 for(j = 0; j < n_requested_data_block_ids; j++)
19247 if(block_id == requested_data_block_ids[j])
19259 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19260 np_data->last_retrieved_frame >=
19261 frame_set->first_frame + frame_set->n_frames))
19263 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19264 TNG_USE_HASH, block_id);
19265 if(stat == TNG_CRITICAL)
19267 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19268 __FILE__, __LINE__);
19271 if(stat == TNG_FAILURE)
19276 if(frame_set->first_frame != current_frame &&
19277 np_data->last_retrieved_frame >= 0)
19279 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19283 data_frame = np_data->first_frame_with_data;
19285 frame_diff = data_frame - current_frame;
19290 if(min_diff == -1 || frame_diff <= min_diff)
19292 if(frame_diff < min_diff)
19294 *n_data_blocks_in_next_frame = 1;
19298 *n_data_blocks_in_next_frame += 1;
19300 if(n_requested_data_block_ids <= 0)
19302 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19303 temp = realloc(*data_block_ids_in_next_frame, size);
19306 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19307 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19308 __FILE__, __LINE__);
19309 free(*data_block_ids_in_next_frame);
19310 *data_block_ids_in_next_frame = 0;
19311 return(TNG_CRITICAL);
19313 *data_block_ids_in_next_frame = temp;
19317 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19319 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19321 min_diff = frame_diff;
19326 return(TNG_FAILURE);
19328 *next_frame = current_frame + min_diff;
19330 return(TNG_SUCCESS);
19334 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19335 (tng_trajectory_t tng_data,
19336 int64_t *n_data_blocks,
19337 int64_t **data_block_ids,
19338 char ***data_block_names,
19339 int64_t **stride_lengths,
19340 int64_t **n_values_per_frame,
19341 char **block_types,
19342 char **dependencies,
19343 char **compressions)
19345 tng_gen_block_t block;
19346 long orig_file_pos, file_pos;
19348 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19349 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19350 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19351 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19352 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19354 orig_file_pos = ftell(tng_data->input_file);
19356 if(!tng_data->input_file_len)
19358 fseek(tng_data->input_file, 0, SEEK_END);
19359 tng_data->input_file_len = ftell(tng_data->input_file);
19362 fseek(tng_data->input_file, 0, SEEK_SET);
19365 *n_data_blocks = 0;
19367 tng_block_init(&block);
19369 while(file_pos < tng_data->input_file_len &&
19370 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19372 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19376 file_pos += (long)(block->block_contents_size + block->header_contents_size);
19377 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
19380 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
19382 return(TNG_SUCCESS);
19385 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19386 (tng_trajectory_t tng_data,
19387 const int64_t prev_frame)
19389 tng_function_status stat;
19390 FILE *temp = tng_data->input_file;
19392 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19393 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19395 tng_data->input_file = tng_data->output_file;
19397 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19398 if(stat != TNG_SUCCESS)
19403 tng_data->current_trajectory_frame_set_output_file_pos =
19404 tng_data->current_trajectory_frame_set_input_file_pos;
19406 tng_data->input_file = temp;
19408 return(TNG_SUCCESS);