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 #define _FILE_OFFSET_BITS 64
13 /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
14 #define _LARGEFILE_SOURCE
15 /* Define for large files, on AIX-style hosts. */
18 #include "tng/tng_io.h"
20 #ifdef USE_STD_INTTYPES_H
34 #include "compression/tng_compress.h"
35 #include "tng/version.h"
38 #define fseeko _fseeki64
39 #define ftello _ftelli64
43 /** One of the atoms of the bond */
45 /** The other atom of the bond */
50 /** The residue containing this atom */
51 tng_residue_t residue;
52 /** A unique (per molecule) ID number of the atom */
54 /** The atom_type (depending on the forcefield) */
56 /** The name of the atom */
61 /** The chain containing this residue */
63 /** A unique (per chain) ID number of the residue */
65 /** The name of the residue */
67 /** The number of atoms in the residue */
69 /** A list of atoms in the residue */
74 /** The molecule containing this chain */
75 tng_molecule_t molecule;
76 /** A unique (per molecule) ID number of the chain */
78 /** The name of the chain */
80 /** The number of residues in the chain */
82 /** A list of residues in the chain */
83 tng_residue_t residues;
87 /** A unique ID number of the molecule */
89 /** Quaternary structure of the molecule.
94 int64_t quaternary_str;
95 /** The number of chains in the molecule */
97 /** The number of residues in the molecule */
99 /** The number of atoms in the molecule */
101 /** The number of bonds in the molecule. If the bonds are not specified this
104 /** The name of the molecule */
106 /** A list of chains in the molecule */
108 /** A list of residues in the molecule */
109 tng_residue_t residues;
110 /** A list of the atoms in the molecule */
112 /** A list of the bonds in the molecule */
116 struct tng_gen_block {
117 /** The size of the block header in bytes */
118 int64_t header_contents_size;
119 /** The size of the block contents in bytes */
120 int64_t block_contents_size;
121 /** The ID of the block to determine its type */
123 /** The MD5 hash of the block to verify integrity */
124 char md5_hash[TNG_MD5_HASH_LEN];
125 /** The name of the block */
127 /** The library version used to write the block */
128 int64_t block_version;
129 int64_t alt_hash_type;
130 int64_t alt_hash_len;
132 int64_t signature_type;
133 int64_t signature_len;
135 /** The full block header contents */
136 char *header_contents;
137 /** The full block contents */
138 char *block_contents;
141 struct tng_particle_mapping {
142 /** The index number of the first particle in this mapping block */
143 int64_t num_first_particle;
144 /** The number of particles list in this mapping block */
146 /** the mapping of index numbers to the real particle numbers in the
147 * trajectory. real_particle_numbers[0] is the real particle number
148 * (as it is numbered in the molecular system) of the first particle
149 * in the data blocks covered by this particle mapping block */
150 int64_t *real_particle_numbers;
153 struct tng_trajectory_frame_set {
154 /** The number of different particle mapping blocks present. */
155 int64_t n_mapping_blocks;
156 /** The atom mappings of this frame set */
157 struct tng_particle_mapping *mappings;
158 /** The first frame of this frame set */
160 /** The number of frames in this frame set */
162 /** The number of written frames in this frame set (used when writing one
163 * frame at a time). */
164 int64_t n_written_frames;
165 /** The number of frames not yet written to file in this frame set
166 * (used from the utility functions to finish the writing properly. */
167 int64_t n_unwritten_frames;
170 /** A list of the number of each molecule type - only used when using
171 * variable number of atoms */
172 int64_t *molecule_cnt_list;
173 /** The number of particles/atoms - only used when using variable number
176 /** The file position of the next frame set */
177 int64_t next_frame_set_file_pos;
178 /** The file position of the previous frame set */
179 int64_t prev_frame_set_file_pos;
180 /** The file position of the frame set one long stride step ahead */
181 int64_t medium_stride_next_frame_set_file_pos;
182 /** The file position of the frame set one long stride step behind */
183 int64_t medium_stride_prev_frame_set_file_pos;
184 /** The file position of the frame set one long stride step ahead */
185 int64_t long_stride_next_frame_set_file_pos;
186 /** The file position of the frame set one long stride step behind */
187 int64_t long_stride_prev_frame_set_file_pos;
188 /** Time stamp (in seconds) of first frame in frame set */
189 double first_frame_time;
191 /* The data blocks in a frame set are trajectory data blocks */
192 /** The number of trajectory data blocks of particle dependent data */
193 int n_particle_data_blocks;
194 /** A list of data blocks containing particle dependent data */
195 struct tng_particle_data *tr_particle_data;
196 /** The number of trajectory data blocks independent of particles */
198 /** A list of data blocks containing particle indepdendent data */
199 struct tng_non_particle_data *tr_data;
202 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
203 /* FIXME: Make only one data block struct */
204 struct tng_particle_data {
205 /** The block ID of the data block containing this particle data.
206 * This is used to determine the kind of data that is stored */
208 /** The name of the data block. This is used to determine the kind of
209 * data that is stored */
211 /** The type of data stored. */
213 /** The frame number of the first data value */
214 int64_t first_frame_with_data;
215 /** The number of frames in this frame set */
217 /** The number of values stored per frame */
218 int64_t n_values_per_frame;
219 /** The number of frames between each data point - e.g. when
220 * storing sparse data. */
221 int64_t stride_length;
222 /** ID of the CODEC used for compression 0 == no compression. */
224 /** If reading one frame at a time this is the last read frame */
225 int64_t last_retrieved_frame;
226 /** The multiplier used for getting integer values for compression */
227 double compression_multiplier;
228 /** A 1-dimensional array of values of length
229 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
231 /** If storing character data store it in a 3-dimensional array */
235 struct tng_non_particle_data {
236 /** The ID of the data block */
238 /** The name of the data block. This is used to determine the kind of
239 * data that is stored */
241 /** The type of data stored. */
243 /** The first frame number of the first data value */
244 int64_t first_frame_with_data;
245 /** The number of frames in this data block */
247 /** The number of values stored per frame */
248 int64_t n_values_per_frame;
249 /** The number of frames between each data value, e.g. if storing data
250 * that is not saved every frame. */
251 int64_t stride_length;
252 /** ID of the CODEC used for compression. 0 == no compression. */
254 /** If reading one frame at a time this is the last read frame */
255 int64_t last_retrieved_frame;
256 /** Compressed data is stored as integers. This compression multiplier is
257 * the multiplication factor to convert from integer to float/double */
258 double compression_multiplier;
259 /** A 1-dimensional array of values of length
260 * [sizeof (datatype)] * n_frames * n_values_per_frame */
262 /** If storing character data store it in a 2-dimensional array */
268 struct tng_trajectory {
269 /** The path of the input trajectory file */
270 char *input_file_path;
271 /** A handle to the input file */
273 /** The length of the input file */
274 int64_t input_file_len;
275 /** The path of the output trajectory file */
276 char *output_file_path;
277 /** A handle to the output file */
279 /** Function to swap 32 bit values to and from the endianness of the
281 tng_function_status (*input_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
282 /** Function to swap 64 bit values to and from the endianness of the
284 tng_function_status (*input_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
285 /** Function to swap 32 bit values to and from the endianness of the
287 tng_function_status (*output_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
288 /** Function to swap 64 bit values to and from the endianness of the
290 tng_function_status (*output_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
291 /** The endianness of 32 bit values of the current computer */
293 /** The endianness of 64 bit values of the current computer */
296 /** The name of the program producing this trajectory */
297 char *first_program_name;
298 /** The forcefield used in the simulations */
299 char *forcefield_name;
300 /** The name of the user running the simulations */
301 char *first_user_name;
302 /** The name of the computer on which the simulations were performed */
303 char *first_computer_name;
304 /** The PGP signature of the user creating the file. */
305 char *first_pgp_signature;
306 /** The name of the program used when making last modifications to the
308 char *last_program_name;
309 /** The name of the user making the last modifications to the file */
310 char *last_user_name;
311 /** The name of the computer on which the last modifications were made */
312 char *last_computer_name;
313 /** The PGP signature of the user making the last modifications to the
315 char *last_pgp_signature;
316 /** The time (n seconds since 1970) when the file was created */
318 /** The exponential of the value of the distance unit used. The default
319 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
320 * the measurements are in Ã… the distance_unit_exponential = -10. */
321 int64_t distance_unit_exponential;
323 /** A flag indicating if the number of atoms can vary throughout the
324 * simulation, e.g. using a grand canonical ensemble */
325 char var_num_atoms_flag;
326 /** The number of frames in a frame set. It is allowed to have frame sets
327 * with fewer frames, but this will help searching for specific frames */
328 int64_t frame_set_n_frames;
329 /** The number of frame sets in a medium stride step */
330 int64_t medium_stride_length;
331 /** The number of frame sets in a long stride step */
332 int64_t long_stride_length;
333 /** The current (can change from one frame set to another) time length
334 * (in seconds) of one frame */
335 double time_per_frame;
337 /** The number of different kinds of molecules in the trajectory */
339 /** A list of molecules in the trajectory */
340 tng_molecule_t molecules;
341 /** A list of the count of each molecule - if using variable number of
342 * particles this will be specified in each frame set */
343 int64_t *molecule_cnt_list;
344 /** The total number of particles/atoms. If using variable number of
345 * particles this will be specified in each frame set */
348 /** The pos in the src file of the first frame set */
349 int64_t first_trajectory_frame_set_input_file_pos;
350 /** The pos in the dest file of the first frame set */
351 int64_t first_trajectory_frame_set_output_file_pos;
352 /** The pos in the src file of the last frame set */
353 int64_t last_trajectory_frame_set_input_file_pos;
354 /** The pos in the dest file of the last frame set */
355 int64_t last_trajectory_frame_set_output_file_pos;
356 /** The currently active frame set */
357 struct tng_trajectory_frame_set current_trajectory_frame_set;
358 /** The pos in the src file of the current frame set */
359 int64_t current_trajectory_frame_set_input_file_pos;
360 /** The pos in the dest file of the current frame set */
361 int64_t current_trajectory_frame_set_output_file_pos;
362 /** The number of frame sets in the trajectory N.B. Not saved in file and
363 * cannot be trusted to be up-to-date */
364 int64_t n_trajectory_frame_sets;
366 /* These data blocks are non-trajectory data blocks */
367 /** The number of non-frame dependent particle dependent data blocks */
368 int n_particle_data_blocks;
369 /** A list of data blocks containing particle dependent data */
370 struct tng_particle_data *non_tr_particle_data;
372 /** The number of frame and particle independent data blocks */
374 /** A list of frame and particle indepdendent data blocks */
375 struct tng_non_particle_data *non_tr_data;
377 /** TNG compression algorithm for compressing positions */
378 int *compress_algo_pos;
379 /** TNG compression algorithm for compressing velocities */
380 int *compress_algo_vel;
381 /** The precision used for lossy compression */
382 double compression_precision;
386 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
388 #endif /* win32... */
389 #endif /* not defined USE_WINDOWS */
392 #define TNG_INLINE __inline
393 #define TNG_SNPRINTF _snprintf
395 #define TNG_INLINE inline
396 #define TNG_SNPRINTF snprintf
399 static TNG_INLINE int tng_min_i(int a, int b)
401 return (a < b ? a : b);
405 static TNG_INLINE int tng_max_i(int a, int b)
407 return (a > b ? a : b);
410 static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
412 return (a < b ? a : b);
415 static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
417 return (a > b ? a : b);
421 static TNG_INLINE float tng_min_f(float a, float b)
423 return (a < b ? a : b);
426 static TNG_INLINE float tng_max_f(float a, float b)
428 return (a > b ? a : b);
431 static TNG_INLINE double tng_min_d(double a, double b)
433 return (a < b ? a : b);
436 static TNG_INLINE double tng_max_d(double a, double b)
438 return (a > b ? a : b);
442 /** This function swaps the byte order of a 32 bit numerical variable
444 * It does not only work with integer, but e.g. floats need casting.
445 * If the byte order is already big endian no change is needed.
446 * @param tng_data is a trajectory data container.
447 * @param v is a pointer to a 32 bit numerical value (float or integer).
448 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
449 * byte order is not recognised.
451 static tng_function_status tng_swap_byte_order_big_endian_32
452 (const tng_trajectory_t tng_data, int32_t *v)
454 switch(tng_data->endianness_32)
456 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
457 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
458 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
459 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
460 ((*v & 0x000000FF) << 24); /* Move last byte to first */
464 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
465 *v = ((*v & 0xFFFF0000) >> 16) |
466 ((*v & 0x0000FFFF) << 16);
470 case TNG_BIG_ENDIAN_32: /* Already correct */
478 /** This function swaps the byte order of a 64 bit numerical variable
480 * It does not only work with integer, but e.g. floats need casting.
481 * The byte order swapping routine can convert four different byte
482 * orders to big endian.
483 * If the byte order is already big endian no change is needed.
484 * @param tng_data is a trajectory data container.
485 * @param v is a pointer to a 64 bit numerical value (double or integer).
486 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
487 * byte order is not recognised.
489 static tng_function_status tng_swap_byte_order_big_endian_64
490 (const tng_trajectory_t tng_data, int64_t *v)
492 switch(tng_data->endianness_64)
494 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
495 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
496 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
497 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
498 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
499 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
500 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
501 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
502 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
506 case TNG_QUAD_SWAP_64: /* Byte quad swap */
507 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
508 ((*v & 0x00000000FFFFFFFFLL) << 32);
512 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
513 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
514 ((*v & 0x0000FFFF0000FFFFLL) << 16);
518 case TNG_BYTE_SWAP_64: /* Byte swap */
519 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
520 ((*v & 0x00FF00FF00FF00FFLL) << 8);
524 case TNG_BIG_ENDIAN_64: /* Already correct */
532 /** This function swaps the byte order of a 32 bit numerical variable
534 * It does not only work with integer, but e.g. floats need casting.
535 * If the byte order is already little endian no change is needed.
536 * @param tng_data is a trajectory data container.
537 * @param v is a pointer to a 32 bit numerical value (float or integer).
538 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
539 * byte order is not recognised.
541 static tng_function_status tng_swap_byte_order_little_endian_32
542 (const tng_trajectory_t tng_data, int32_t *v)
544 switch(tng_data->endianness_32)
546 case TNG_LITTLE_ENDIAN_32: /* Already correct */
549 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
550 *v = ((*v & 0xFF00FF00) >> 8) |
551 ((*v & 0x00FF00FF) << 8);
555 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
556 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
557 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
558 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
559 ((*v & 0x000000FF) << 24); /* Move last byte to first */
568 /** This function swaps the byte order of a 64 bit numerical variable
570 * It does not only work with integer, but e.g. floats need casting.
571 * The byte order swapping routine can convert four different byte
572 * orders to little endian.
573 * If the byte order is already little endian no change is needed.
574 * @param tng_data is a trajectory data container.
575 * @param v is a pointer to a 64 bit numerical value (double or integer).
576 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
577 * byte order is not recognised.
579 static tng_function_status tng_swap_byte_order_little_endian_64
580 (const tng_trajectory_t tng_data, int64_t *v)
582 switch(tng_data->endianness_64)
584 case TNG_LITTLE_ENDIAN_64: /* Already correct */
587 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
588 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
589 ((*v & 0x00FF000000FF0000LL) >> 8) |
590 ((*v & 0x0000FF000000FF00LL) << 8) |
591 ((*v & 0x000000FF000000FFLL) << 24);
595 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
596 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
597 ((*v & 0x00FF00FF00000000LL) >> 24) |
598 ((*v & 0x00000000FF00FF00LL) << 24) |
599 ((*v & 0x0000000000FF00FFLL) << 40);
603 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
604 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
605 ((*v & 0x0000FFFF00000000LL) >> 16) |
606 ((*v & 0x00000000FFFF0000LL) << 16) |
607 ((*v & 0x000000000000FFFFLL) << 48);
611 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
612 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
613 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
614 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
615 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
616 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
617 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
618 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
619 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
627 /** Generate the md5 hash of a block.
628 * The hash is created based on the actual block contents.
629 * @param block is a general block container.
630 * @return TNG_SUCCESS (0) if successful.
632 static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
634 md5_state_t md5_state;
636 md5_init(&md5_state);
637 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
638 (int)block->block_contents_size);
639 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
644 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
645 * calculated from the current contents.
646 * If the current md5 hash is not set skip the comparison.
647 * @param block is a general block container.
648 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
649 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
650 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
653 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
656 md5_state_t md5_state;
657 char hash[TNG_MD5_HASH_LEN];
659 TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
662 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
666 md5_init(&md5_state);
667 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
668 (int)block->block_contents_size);
669 md5_finish(&md5_state, (md5_byte_t *)hash);
671 if(strncmp(block->md5_hash, hash, 16) != 0)
673 *results = TNG_FALSE;
679 /** Open the input file if it is not already opened.
680 * @param tng_data is a trajectory data container.
681 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
684 static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
686 if(!tng_data->input_file)
688 if(!tng_data->input_file_path)
690 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
692 return(TNG_CRITICAL);
694 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
695 if(!tng_data->input_file)
697 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
698 tng_data->input_file_path, __FILE__, __LINE__);
699 return(TNG_CRITICAL);
705 /** Open the output file if it is not already opened
706 * @param tng_data is a trajectory data container.
707 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
710 static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
712 if(!tng_data->output_file)
714 if(!tng_data->output_file_path)
716 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
718 return(TNG_CRITICAL);
721 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
723 if(!tng_data->output_file)
725 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
726 tng_data->output_file_path, __FILE__, __LINE__);
727 return(TNG_CRITICAL);
733 /** Setup a file block container.
734 * @param block_p a pointer to memory to initialise as a file block container.
735 * @details Memory is allocated during initialisation.
736 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
739 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
741 tng_gen_block_t block;
743 *block_p = malloc(sizeof(struct tng_gen_block));
746 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
747 sizeof(struct tng_gen_block), __FILE__, __LINE__);
748 return(TNG_CRITICAL);
754 /* Reset the md5_hash */
755 memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
757 block->block_version = TNG_API_VERSION;
758 block->header_contents = 0;
759 block->header_contents_size = 0;
760 block->block_contents = 0;
761 block->block_contents_size = 0;
767 * @brief Clean up a file block container.
768 * @param block_p a pointer to the file block container to destroy.
769 * @details All allocated memory in the data structure is freed, as well as
771 * @return TNG_SUCCESS (0) if successful.
773 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
775 tng_gen_block_t block = *block_p;
782 /* fprintf(stderr, "TNG library: Destroying block\n"); */
788 if(block->header_contents)
790 free(block->header_contents);
791 block->header_contents = 0;
793 if(block->block_contents)
795 free(block->block_contents);
796 block->block_contents = 0;
805 /** Read the header of a data block, regardless of its type
806 * @param tng_data is a trajectory data container.
807 * @param block is a general block container.
808 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
809 * error has occured (not able to read the header size, thus skipping
810 * the block) or TNG_CRITICAL (2) if a major error has occured.
812 static tng_function_status tng_block_header_read
813 (tng_trajectory_t tng_data, tng_gen_block_t block)
818 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
820 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
822 return(TNG_CRITICAL);
825 /* First read the header size to be able to read the whole header. */
826 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
827 1, tng_data->input_file) == 0)
829 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
831 return(TNG_CRITICAL);
834 if(block->header_contents_size == 0)
840 /* If this was the size of the general info block check the endianness */
841 if(ftello(tng_data->input_file) < 9)
843 /* File is little endian */
844 if ( *((const char*)&block->header_contents_size) != 0x00 &&
845 *((const char*)(&block->header_contents_size) + 7) == 0x00)
847 /* If the architecture endianness is little endian no byte swap
848 * will be needed. Otherwise use the functions to swap to little
850 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
852 tng_data->input_endianness_swap_func_32 = 0;
856 tng_data->input_endianness_swap_func_32 =
857 &tng_swap_byte_order_little_endian_32;
859 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
861 tng_data->input_endianness_swap_func_64 = 0;
865 tng_data->input_endianness_swap_func_64 =
866 &tng_swap_byte_order_little_endian_64;
869 /* File is big endian */
872 /* If the architecture endianness is big endian no byte swap
873 * will be needed. Otherwise use the functions to swap to big
875 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
877 tng_data->input_endianness_swap_func_32 = 0;
881 tng_data->input_endianness_swap_func_32 =
882 &tng_swap_byte_order_big_endian_32;
884 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
886 tng_data->input_endianness_swap_func_64 = 0;
890 tng_data->input_endianness_swap_func_64 =
891 &tng_swap_byte_order_big_endian_64;
896 if(tng_data->input_endianness_swap_func_64)
898 if(tng_data->input_endianness_swap_func_64(tng_data,
899 &block->header_contents_size)
902 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
907 /* Move the reading position to the beginning of the header. */
908 fseeko(tng_data->input_file, -(int64_t)sizeof(block->header_contents_size),
911 /* If there is already memory allocated for the contents free it (we do not
912 * know if the size is correct). */
913 if(block->header_contents)
915 free(block->header_contents);
918 block->header_contents = malloc(block->header_contents_size);
919 if(!block->header_contents)
921 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
922 block->header_contents_size, __FILE__, __LINE__);
923 return(TNG_CRITICAL);
926 /* Read the whole header into header_contents. This way it can be saved
927 * even if it cannot be interpreted
928 * for one reason or another. */
929 if(fread(block->header_contents, block->header_contents_size, 1,
930 tng_data->input_file) == 0)
932 fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
933 return(TNG_CRITICAL);
936 /* The header contents size has already been read. Skip ahead. */
937 offset = sizeof(block->header_contents_size);
940 /* Copy the respective parameters from the header contents block */
941 memcpy(&block->block_contents_size, block->header_contents+offset,
942 sizeof(block->block_contents_size));
943 if(tng_data->input_endianness_swap_func_64)
945 if(tng_data->input_endianness_swap_func_64(tng_data,
946 &block->block_contents_size)
949 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
954 offset += sizeof(block->block_contents_size);
956 memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
957 if(tng_data->input_endianness_swap_func_64)
959 if(tng_data->input_endianness_swap_func_64(tng_data,
963 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
968 offset += sizeof(block->id);
970 memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
971 offset += TNG_MD5_HASH_LEN;
973 if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
978 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
981 block->name = malloc(len);
984 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
986 return(TNG_CRITICAL);
988 strncpy(block->name, block->header_contents+offset, len);
992 memcpy(&block->block_version, block->header_contents+offset,
993 sizeof(block->block_version));
994 if(tng_data->input_endianness_swap_func_64)
996 if(tng_data->input_endianness_swap_func_64(tng_data,
997 &block->block_version)
1000 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1001 __FILE__, __LINE__);
1005 return(TNG_SUCCESS);
1008 /** Write a whole block, both header and contents, regardless of it type
1009 * @param tng_data is a trajectory data container.
1010 * @param block is a general block container.
1011 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1012 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1014 /* Disabled until it is used.*/
1016 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1017 // tng_gen_block_t block)
1019 // if(!block->header_contents)
1021 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1022 // return(TNG_FAILURE);
1024 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1025 // tng_data->output_file) != 1)
1027 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1028 // __FILE__, __LINE__);
1029 // return(TNG_CRITICAL);
1032 // if(!block->block_contents)
1034 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1035 // __FILE__, __LINE__);
1036 // return(TNG_FAILURE);
1038 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1039 // tng_data->output_file) != 1)
1041 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1042 // __FILE__, __LINE__);
1043 // return(TNG_CRITICAL);
1045 // return(TNG_SUCCESS);
1049 /** Update the md5 hash of a block already written to the file
1050 * @param tng_data is a trajectory data container.
1051 * @param block is the block, of which to update the md5 hash.
1052 * @param header_start_pos is the file position where the block header starts.
1053 * @param contents_start_pos is the file position where the block contents
1055 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1056 * error has occured.
1058 static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
1059 tng_gen_block_t block,
1060 const int64_t header_start_pos,
1061 const int64_t contents_start_pos)
1063 if(block->block_contents)
1065 free(block->block_contents);
1068 block->block_contents = malloc(block->block_contents_size);
1069 if(!block->block_contents)
1071 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1072 block->block_contents_size, __FILE__, __LINE__);
1073 return(TNG_CRITICAL);
1076 fseeko(tng_data->output_file, contents_start_pos, SEEK_SET);
1077 if(fread(block->block_contents, block->block_contents_size, 1,
1078 tng_data->output_file) == 0)
1080 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1081 return(TNG_CRITICAL);
1084 tng_block_md5_hash_generate(block);
1086 fseeko(tng_data->output_file, header_start_pos + 3 * sizeof(int64_t),
1088 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
1090 return(TNG_SUCCESS);
1093 /** Update the frame set pointers in the file header (general info block),
1094 * already written to disk
1095 * @param tng_data is a trajectory data container.
1096 * @param hash_mode specifies whether to update the block md5 hash when
1097 * updating the pointers.
1098 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1099 * error has occured.
1101 static tng_function_status tng_header_pointers_update
1102 (tng_trajectory_t tng_data, const char hash_mode)
1104 tng_gen_block_t block;
1105 FILE *temp = tng_data->input_file;
1106 int64_t output_file_pos, pos, contents_start_pos;
1108 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1110 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1111 __FILE__, __LINE__);
1112 return(TNG_CRITICAL);
1115 tng_data->input_file = tng_data->output_file;
1117 tng_block_init(&block);
1119 output_file_pos = ftello(tng_data->output_file);
1120 fseeko(tng_data->output_file, 0, SEEK_SET);
1122 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1124 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
1125 __FILE__, __LINE__);
1126 tng_data->input_file = temp;
1127 tng_block_destroy(&block);
1128 return(TNG_CRITICAL);
1131 contents_start_pos = ftello(tng_data->output_file);
1133 fseeko(tng_data->output_file, block->block_contents_size - 5 *
1134 sizeof(int64_t), SEEK_CUR);
1136 tng_data->input_file = temp;
1138 pos = tng_data->first_trajectory_frame_set_output_file_pos;
1140 if(tng_data->input_endianness_swap_func_64)
1142 if(tng_data->input_endianness_swap_func_64(tng_data,
1146 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1147 __FILE__, __LINE__);
1151 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1153 tng_block_destroy(&block);
1154 return(TNG_CRITICAL);
1157 pos = tng_data->last_trajectory_frame_set_output_file_pos;
1159 if(tng_data->input_endianness_swap_func_64)
1161 if(tng_data->input_endianness_swap_func_64(tng_data,
1165 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1166 __FILE__, __LINE__);
1171 sizeof(int64_t), 1, tng_data->output_file) != 1)
1173 tng_block_destroy(&block);
1174 return(TNG_CRITICAL);
1177 if(hash_mode == TNG_USE_HASH)
1179 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
1182 tng_block_destroy(&block);
1184 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1186 return(TNG_SUCCESS);
1189 /** Update the frame set pointers in the current frame set block, already
1190 * written to disk. It also updates the pointers of the blocks pointing to
1191 * the current frame set block.
1192 * @param tng_data is a trajectory data container.
1193 * @param hash_mode specifies whether to update the block md5 hash when
1194 * updating the pointers.
1195 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1196 * error has occured.
1198 static tng_function_status tng_frame_set_pointers_update
1199 (tng_trajectory_t tng_data, const char hash_mode)
1201 tng_gen_block_t block;
1202 tng_trajectory_frame_set_t frame_set;
1203 FILE *temp = tng_data->input_file;
1204 int64_t pos, output_file_pos, contents_start_pos;
1206 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1208 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1209 __FILE__, __LINE__);
1210 return(TNG_CRITICAL);
1213 tng_block_init(&block);
1214 output_file_pos = ftello(tng_data->output_file);
1216 tng_data->input_file = tng_data->output_file;
1218 frame_set = &tng_data->current_trajectory_frame_set;
1220 pos = tng_data->current_trajectory_frame_set_output_file_pos;
1222 /* Update next frame set */
1223 if(frame_set->next_frame_set_file_pos > 0)
1225 fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos,
1228 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1230 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1231 __FILE__, __LINE__);
1232 tng_data->input_file = temp;
1233 tng_block_destroy(&block);
1234 return(TNG_CRITICAL);
1237 contents_start_pos = ftello(tng_data->output_file);
1239 fseeko(tng_data->output_file, block->block_contents_size - (5 *
1240 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1242 if(tng_data->input_endianness_swap_func_64)
1244 if(tng_data->input_endianness_swap_func_64(tng_data,
1248 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1249 __FILE__, __LINE__);
1253 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1255 tng_data->input_file = temp;
1256 tng_block_destroy(&block);
1257 return(TNG_CRITICAL);
1260 if(hash_mode == TNG_USE_HASH)
1262 tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
1263 contents_start_pos);
1265 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1267 /* Update previous frame set */
1268 if(frame_set->prev_frame_set_file_pos > 0)
1270 fseeko(tng_data->output_file, frame_set->prev_frame_set_file_pos,
1273 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1275 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1276 __FILE__, __LINE__);
1277 tng_data->input_file = temp;
1278 tng_block_destroy(&block);
1279 return(TNG_CRITICAL);
1282 contents_start_pos = ftello(tng_data->output_file);
1284 fseeko(tng_data->output_file, block->block_contents_size - (6 *
1285 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1287 if(tng_data->input_endianness_swap_func_64)
1289 if(tng_data->input_endianness_swap_func_64(tng_data,
1293 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1294 __FILE__, __LINE__);
1298 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1300 tng_data->input_file = temp;
1301 tng_block_destroy(&block);
1302 return(TNG_CRITICAL);
1305 if(hash_mode == TNG_USE_HASH)
1307 tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
1308 contents_start_pos);
1310 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1313 /* Update the frame set one medium stride step after */
1314 if(frame_set->medium_stride_next_frame_set_file_pos > 0)
1316 fseeko(tng_data->output_file,
1317 frame_set->medium_stride_next_frame_set_file_pos,
1320 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1322 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1323 __FILE__, __LINE__);
1324 tng_data->input_file = temp;
1325 tng_block_destroy(&block);
1326 return(TNG_CRITICAL);
1329 contents_start_pos = ftello(tng_data->output_file);
1331 fseeko(tng_data->output_file, block->block_contents_size - (3 *
1332 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1334 if(tng_data->input_endianness_swap_func_64)
1336 if(tng_data->input_endianness_swap_func_64(tng_data,
1340 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1341 __FILE__, __LINE__);
1345 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1347 tng_data->input_file = temp;
1348 tng_block_destroy(&block);
1349 return(TNG_CRITICAL);
1352 if(hash_mode == TNG_USE_HASH)
1354 tng_md5_hash_update(tng_data, block,
1355 frame_set->medium_stride_next_frame_set_file_pos,
1356 contents_start_pos);
1359 /* Update the frame set one medium stride step before */
1360 if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
1362 fseeko(tng_data->output_file,
1363 frame_set->medium_stride_prev_frame_set_file_pos,
1366 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1368 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1369 __FILE__, __LINE__);
1370 tng_data->input_file = temp;
1371 tng_block_destroy(&block);
1372 return(TNG_CRITICAL);
1375 contents_start_pos = ftello(tng_data->output_file);
1377 fseeko(tng_data->output_file, block->block_contents_size - (4 *
1378 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1380 if(tng_data->input_endianness_swap_func_64)
1382 if(tng_data->input_endianness_swap_func_64(tng_data,
1386 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1387 __FILE__, __LINE__);
1391 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1393 tng_data->input_file = temp;
1394 tng_block_destroy(&block);
1395 return(TNG_CRITICAL);
1398 if(hash_mode == TNG_USE_HASH)
1400 tng_md5_hash_update(tng_data, block,
1401 frame_set->medium_stride_prev_frame_set_file_pos,
1402 contents_start_pos);
1406 /* Update the frame set one long stride step after */
1407 if(frame_set->long_stride_next_frame_set_file_pos > 0)
1409 fseeko(tng_data->output_file,
1410 frame_set->long_stride_next_frame_set_file_pos,
1413 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1415 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1416 __FILE__, __LINE__);
1417 tng_data->input_file = temp;
1418 tng_block_destroy(&block);
1419 return(TNG_CRITICAL);
1422 contents_start_pos = ftello(tng_data->output_file);
1424 fseeko(tng_data->output_file, block->block_contents_size - (1 *
1425 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1427 if(tng_data->input_endianness_swap_func_64)
1429 if(tng_data->input_endianness_swap_func_64(tng_data,
1433 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1434 __FILE__, __LINE__);
1438 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1440 tng_data->input_file = temp;
1441 tng_block_destroy(&block);
1442 return(TNG_CRITICAL);
1445 if(hash_mode == TNG_USE_HASH)
1447 tng_md5_hash_update(tng_data, block,
1448 frame_set->long_stride_next_frame_set_file_pos,
1449 contents_start_pos);
1452 /* Update the frame set one long stride step before */
1453 if(frame_set->long_stride_prev_frame_set_file_pos > 0)
1455 fseeko(tng_data->output_file,
1456 frame_set->long_stride_prev_frame_set_file_pos,
1459 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1461 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1462 __FILE__, __LINE__);
1463 tng_data->input_file = temp;
1464 tng_block_destroy(&block);
1465 return(TNG_CRITICAL);
1468 contents_start_pos = ftello(tng_data->output_file);
1470 fseeko(tng_data->output_file, block->block_contents_size - (2 *
1471 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1473 if(tng_data->input_endianness_swap_func_64)
1475 if(tng_data->input_endianness_swap_func_64(tng_data,
1479 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1480 __FILE__, __LINE__);
1484 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1486 tng_data->input_file = temp;
1487 tng_block_destroy(&block);
1488 return(TNG_CRITICAL);
1491 if(hash_mode == TNG_USE_HASH)
1493 tng_md5_hash_update(tng_data, block,
1494 frame_set->long_stride_prev_frame_set_file_pos,
1495 contents_start_pos);
1499 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1501 tng_data->input_file = temp;
1503 tng_block_destroy(&block);
1505 return(TNG_SUCCESS);
1508 static tng_function_status tng_reread_frame_set_at_file_pos
1509 (tng_trajectory_t tng_data,
1512 tng_gen_block_t block;
1513 tng_function_status stat;
1515 tng_block_init(&block);
1517 fseeko(tng_data->input_file, pos, SEEK_SET);
1520 stat = tng_block_header_read(tng_data, block);
1521 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1523 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
1524 __FILE__, __LINE__);
1525 tng_block_destroy(&block);
1526 return(TNG_FAILURE);
1529 if(tng_block_read_next(tng_data, block,
1530 TNG_SKIP_HASH) != TNG_SUCCESS)
1532 tng_block_destroy(&block);
1533 return(TNG_CRITICAL);
1537 tng_block_destroy(&block);
1539 return(TNG_SUCCESS);
1542 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1543 (tng_trajectory_t tng_data,
1546 int64_t orig_pos, curr_frame_set_pos;
1547 tng_gen_block_t block;
1548 tng_function_status stat;
1549 tng_trajectory_frame_set_t frame_set =
1550 &tng_data->current_trajectory_frame_set;
1552 orig_pos = ftello(tng_data->input_file);
1553 curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
1555 *pos = tng_data->first_trajectory_frame_set_input_file_pos;
1559 return(TNG_SUCCESS);
1562 fseeko(tng_data->input_file, *pos, SEEK_SET);
1564 tng_block_init(&block);
1565 /* Read block headers first to see that a frame set block is found. */
1566 stat = tng_block_header_read(tng_data, block);
1567 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1569 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1570 __FILE__, __LINE__);
1571 tng_block_destroy(&block);
1572 return(TNG_FAILURE);
1575 if(tng_block_read_next(tng_data, block,
1576 TNG_SKIP_HASH) != TNG_SUCCESS)
1578 tng_block_destroy(&block);
1579 return(TNG_CRITICAL);
1582 /* Read all frame set blocks (not the blocks between them) */
1583 while(frame_set->next_frame_set_file_pos > 0)
1585 fseeko(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1586 stat = tng_block_header_read(tng_data, block);
1587 if(stat == TNG_CRITICAL)
1589 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1590 __FILE__, __LINE__);
1591 tng_block_destroy(&block);
1592 return(TNG_CRITICAL);
1594 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1596 return(TNG_FAILURE);
1599 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
1600 if(stat != TNG_SUCCESS)
1602 tng_block_destroy(&block);
1605 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1606 if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
1607 tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
1609 *pos = tng_data->current_trajectory_frame_set_input_file_pos;
1613 /* Re-read the frame set that used to be the current one */
1614 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1616 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1618 tng_block_destroy(&block);
1620 return(TNG_SUCCESS);
1623 static tng_function_status tng_frame_set_complete_migrate
1624 (tng_trajectory_t tng_data,
1625 int64_t block_start_pos,
1630 tng_bool updated = TNG_FALSE;
1634 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1636 return(TNG_CRITICAL);
1639 fseeko(tng_data->input_file, block_start_pos, SEEK_SET);
1641 contents = malloc(block_len);
1644 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1645 block_len, __FILE__, __LINE__);
1646 return(TNG_CRITICAL);
1649 if(fread(contents, block_len, 1, tng_data->input_file) == 0)
1651 fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1652 __FILE__, __LINE__);
1654 return(TNG_CRITICAL);
1656 fseeko(tng_data->output_file, new_pos, SEEK_SET);
1658 if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
1660 fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1661 __FILE__, __LINE__);
1663 return(TNG_CRITICAL);
1666 tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
1668 tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
1670 /* Update the general info block if needed */
1671 if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
1673 tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
1676 if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
1678 tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
1683 tng_header_pointers_update(tng_data, TNG_USE_HASH);
1686 /* Fill the block with NULL to avoid confusion. */
1687 for(i = 0; i < block_len; i++)
1691 fseeko(tng_data->output_file, block_start_pos, SEEK_SET);
1693 /* FIXME: casting block_len to size_t is dangerous */
1694 fwrite(contents, 1, block_len, tng_data->output_file);
1698 return(TNG_SUCCESS);
1701 static tng_function_status tng_length_of_current_frame_set_contents_get
1702 (tng_trajectory_t tng_data,
1705 int64_t orig_pos, pos, curr_frame_set_pos;
1706 tng_gen_block_t block;
1707 tng_function_status stat;
1709 orig_pos = ftello(tng_data->input_file);
1710 curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
1714 fseeko(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
1716 tng_block_init(&block);
1717 /* Read block headers first to see that a frame set block is found. */
1718 stat = tng_block_header_read(tng_data, block);
1719 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1721 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
1722 curr_frame_set_pos, __FILE__, __LINE__);
1723 tng_block_destroy(&block);
1724 return(TNG_FAILURE);
1727 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1728 while(stat == TNG_SUCCESS)
1730 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
1731 *len += block->header_contents_size + block->block_contents_size;
1732 pos += block->header_contents_size + block->block_contents_size;
1733 if(pos >= tng_data->input_file_len)
1737 stat = tng_block_header_read(tng_data, block);
1738 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1744 /* Re-read the frame set that used to be the current one */
1745 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1747 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1749 tng_block_destroy(&block);
1751 return(TNG_SUCCESS);
1754 /** Migrate blocks in the file to make room for new data in a block. This
1755 * is required e.g. when adding data to a block or extending strings in a
1757 * @param tng_data is a trajectory data container.
1758 * @param start_pos is the position from which to start moving data, usually
1759 * the byte after the end of the block to which data was added.
1760 * @param offset is the number of bytes that were inserted.
1761 * @details Trajectory blocks (frame sets and their related blocks) are moved
1762 * to the end of the file (if needed) in order to make room for non-trajectory
1765 static tng_function_status tng_migrate_data_in_file
1766 (tng_trajectory_t tng_data,
1770 int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
1771 tng_gen_block_t block;
1772 tng_function_status stat;
1777 return(TNG_SUCCESS);
1780 temp = tng_data->input_file;
1782 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1783 if(stat != TNG_SUCCESS)
1785 tng_data->input_file = temp;
1789 tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
1791 empty_space = traj_start_pos - (start_pos - 1);
1793 if(empty_space >= offset)
1795 return(TNG_SUCCESS);
1798 orig_file_pos = ftello(tng_data->input_file);
1799 tng_block_init(&block);
1801 while(empty_space < offset)
1803 fseeko(tng_data->input_file, traj_start_pos, SEEK_SET);
1804 stat = tng_block_header_read(tng_data, block);
1805 if(stat == TNG_CRITICAL)
1807 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
1808 __FILE__, __LINE__);
1809 tng_block_destroy(&block);
1810 tng_data->input_file = temp;
1811 return(TNG_CRITICAL);
1813 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1815 tng_data->input_file = temp;
1816 tng_block_destroy(&block);
1817 return(TNG_FAILURE);
1819 stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
1820 if(stat != TNG_SUCCESS)
1822 tng_data->input_file = temp;
1823 tng_block_destroy(&block);
1826 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1827 frame_set_length, tng_data->input_file_len);
1828 if(stat != TNG_SUCCESS)
1830 tng_data->input_file = temp;
1831 tng_block_destroy(&block);
1835 empty_space += frame_set_length;
1837 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
1838 tng_block_destroy(&block);
1840 return(TNG_SUCCESS);
1843 static tng_function_status tng_block_header_len_calculate
1844 (const tng_trajectory_t tng_data,
1845 tng_gen_block_t block,
1851 /* If the string is unallocated allocate memory for just string
1855 block->name = malloc(1);
1858 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1859 __FILE__, __LINE__);
1860 return(TNG_CRITICAL);
1865 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1867 /* Calculate the size of the header to write */
1868 *len = sizeof(block->header_contents_size) +
1869 sizeof(block->block_contents_size) +
1871 sizeof(block->block_version) +
1875 return (TNG_SUCCESS);
1878 /** Write the header of a data block, regardless of its type
1879 * @param tng_data is a trajectory data container.
1880 * @param block is a general block container.
1881 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1882 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1883 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1884 * error has occured.
1886 static tng_function_status tng_block_header_write
1887 (tng_trajectory_t tng_data,
1888 tng_gen_block_t block,
1889 const char hash_mode)
1891 int name_len, offset = 0;
1893 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1895 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1897 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1898 __FILE__, __LINE__);
1899 return(TNG_CRITICAL);
1902 if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
1905 fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
1906 __FILE__, __LINE__);
1907 return(TNG_CRITICAL);
1910 if(hash_mode == TNG_USE_HASH)
1912 tng_block_md5_hash_generate(block);
1915 if(block->header_contents)
1917 free(block->header_contents);
1920 block->header_contents = malloc(block->header_contents_size);
1921 if(!block->header_contents)
1923 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1924 block->header_contents_size, __FILE__, __LINE__);
1925 return(TNG_CRITICAL);
1928 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1930 /* First copy all data into the header_contents block and finally write
1931 * the whole block at once. */
1932 memcpy(block->header_contents, &block->header_contents_size,
1933 sizeof(block->header_contents_size));
1934 if(tng_data->output_endianness_swap_func_64)
1936 if(tng_data->output_endianness_swap_func_64(tng_data,
1937 (int64_t *)block->header_contents+offset)
1940 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1941 __FILE__, __LINE__);
1944 offset += sizeof(block->header_contents_size);
1946 memcpy(block->header_contents+offset, &block->block_contents_size,
1947 sizeof(block->block_contents_size));
1948 if(tng_data->output_endianness_swap_func_64)
1950 if(tng_data->output_endianness_swap_func_64(tng_data,
1951 (int64_t *)block->header_contents+offset)
1954 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1955 __FILE__, __LINE__);
1958 offset += sizeof(block->block_contents_size);
1960 memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
1961 if(tng_data->output_endianness_swap_func_64)
1963 if(tng_data->output_endianness_swap_func_64(tng_data,
1964 (int64_t *)block->header_contents+offset)
1967 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1968 __FILE__, __LINE__);
1971 offset += sizeof(block->id);
1973 memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
1974 offset += TNG_MD5_HASH_LEN;
1976 strncpy(block->header_contents+offset, block->name, name_len);
1979 memcpy(block->header_contents+offset, &block->block_version,
1980 sizeof(block->block_version));
1981 if(tng_data->output_endianness_swap_func_64)
1983 if(tng_data->output_endianness_swap_func_64(tng_data,
1984 (int64_t *)block->header_contents+offset)
1987 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1988 __FILE__, __LINE__);
1992 if(fwrite(block->header_contents, block->header_contents_size,
1993 1, tng_data->output_file) != 1)
1995 fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
1996 return(TNG_CRITICAL);
1998 return(TNG_SUCCESS);
2001 static tng_function_status tng_general_info_block_len_calculate
2002 (tng_trajectory_t tng_data,
2005 int first_program_name_len, first_user_name_len;
2006 int first_computer_name_len, first_pgp_signature_len;
2007 int last_program_name_len, last_user_name_len;
2008 int last_computer_name_len, last_pgp_signature_len;
2009 int forcefield_name_len;
2011 /* If the strings are unallocated allocate memory for just string
2013 if(!tng_data->first_program_name)
2015 tng_data->first_program_name = malloc(1);
2016 if(!tng_data->first_program_name)
2018 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2019 __FILE__, __LINE__);
2020 return(TNG_CRITICAL);
2022 tng_data->first_program_name[0] = 0;
2024 if(!tng_data->last_program_name)
2026 tng_data->last_program_name = malloc(1);
2027 if(!tng_data->last_program_name)
2029 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2030 __FILE__, __LINE__);
2031 return(TNG_CRITICAL);
2033 tng_data->last_program_name[0] = 0;
2035 if(!tng_data->first_user_name)
2037 tng_data->first_user_name = malloc(1);
2038 if(!tng_data->first_user_name)
2040 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2041 __FILE__, __LINE__);
2042 return(TNG_CRITICAL);
2044 tng_data->first_user_name[0] = 0;
2046 if(!tng_data->last_user_name)
2048 tng_data->last_user_name = malloc(1);
2049 if(!tng_data->last_user_name)
2051 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2052 __FILE__, __LINE__);
2053 return(TNG_CRITICAL);
2055 tng_data->last_user_name[0] = 0;
2057 if(!tng_data->first_computer_name)
2059 tng_data->first_computer_name = malloc(1);
2060 if(!tng_data->first_computer_name)
2062 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2063 __FILE__, __LINE__);
2064 return(TNG_CRITICAL);
2066 tng_data->first_computer_name[0] = 0;
2068 if(!tng_data->last_computer_name)
2070 tng_data->last_computer_name = malloc(1);
2071 if(!tng_data->last_computer_name)
2073 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2074 __FILE__, __LINE__);
2075 return(TNG_CRITICAL);
2077 tng_data->last_computer_name[0] = 0;
2079 if(!tng_data->first_pgp_signature)
2081 tng_data->first_pgp_signature = malloc(1);
2082 if(!tng_data->first_pgp_signature)
2084 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2085 __FILE__, __LINE__);
2086 return(TNG_CRITICAL);
2088 tng_data->first_pgp_signature[0] = 0;
2090 if(!tng_data->last_pgp_signature)
2092 tng_data->last_pgp_signature = malloc(1);
2093 if(!tng_data->last_pgp_signature)
2095 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2096 __FILE__, __LINE__);
2097 return(TNG_CRITICAL);
2099 tng_data->last_pgp_signature[0] = 0;
2101 if(!tng_data->forcefield_name)
2103 tng_data->forcefield_name = malloc(1);
2104 if(!tng_data->forcefield_name)
2106 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2107 __FILE__, __LINE__);
2108 return(TNG_CRITICAL);
2110 tng_data->forcefield_name[0] = 0;
2113 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2115 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2117 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2119 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2121 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2123 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2125 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2127 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2129 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2132 *len = sizeof(tng_data->time) +
2133 sizeof(tng_data->var_num_atoms_flag) +
2134 sizeof(tng_data->frame_set_n_frames) +
2135 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
2136 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
2137 sizeof(tng_data->medium_stride_length) +
2138 sizeof(tng_data->long_stride_length) +
2139 sizeof(tng_data->distance_unit_exponential) +
2140 first_program_name_len +
2141 last_program_name_len +
2142 first_user_name_len +
2143 last_user_name_len +
2144 first_computer_name_len +
2145 last_computer_name_len +
2146 first_pgp_signature_len +
2147 last_pgp_signature_len +
2148 forcefield_name_len;
2150 return(TNG_SUCCESS);
2153 /** Read a general info block. This is the first block of a TNG file.
2154 * Populate the fields in tng_data.
2155 * @param tng_data is a trajectory data container.
2156 * @param block is a general block container.
2157 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2158 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2159 * compared to the md5 hash of the read contents to ensure valid data.
2160 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2161 * error has occured.
2163 static tng_function_status tng_general_info_block_read
2164 (tng_trajectory_t tng_data, tng_gen_block_t block,
2165 const char hash_mode)
2167 int len, offset = 0;
2172 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2174 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2176 return(TNG_CRITICAL);
2179 temp = realloc(block->block_contents, block->block_contents_size);
2182 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2183 block->block_contents_size, __FILE__, __LINE__);
2184 free(block->block_contents);
2185 block->block_contents = 0;
2186 return(TNG_CRITICAL);
2188 block->block_contents = temp;
2190 /* Read the whole block into block_contents to be able to write it to disk
2191 * even if it cannot be interpreted. */
2192 if(fread(block->block_contents, block->block_contents_size, 1,
2193 tng_data->input_file) == 0)
2195 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
2196 return(TNG_CRITICAL);
2199 /* FIXME: Does not check if the size of the contents matches the expected
2200 * size or if the contents can be read. */
2202 if(hash_mode == TNG_USE_HASH)
2204 tng_md5_hash_match_verify(block, &same_hash);
2205 if(same_hash != TNG_TRUE)
2207 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
2209 __FILE__, __LINE__);
2210 /* return(TNG_FAILURE); */
2214 len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
2215 temp = realloc(tng_data->first_program_name, len);
2218 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2219 __FILE__, __LINE__);
2220 free(tng_data->first_program_name);
2221 tng_data->first_program_name = 0;
2222 return(TNG_CRITICAL);
2224 tng_data->first_program_name = temp;
2225 strncpy(tng_data->first_program_name, block->block_contents, len);
2228 len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
2229 temp = realloc(tng_data->last_program_name, len);
2232 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2233 __FILE__, __LINE__);
2234 free(tng_data->last_program_name);
2235 tng_data->last_program_name = 0;
2236 return(TNG_CRITICAL);
2238 tng_data->last_program_name = temp;
2239 strncpy(tng_data->last_program_name, block->block_contents + offset, len);
2242 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2243 temp = realloc(tng_data->first_user_name, len);
2246 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2247 __FILE__, __LINE__);
2248 free(tng_data->first_user_name);
2249 tng_data->first_user_name = 0;
2250 return(TNG_CRITICAL);
2252 tng_data->first_user_name = temp;
2253 strncpy(tng_data->first_user_name, block->block_contents+offset, len);
2256 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2257 temp = realloc(tng_data->last_user_name, len);
2260 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2261 __FILE__, __LINE__);
2262 free(tng_data->last_user_name);
2263 tng_data->last_user_name = 0;
2264 return(TNG_CRITICAL);
2266 tng_data->last_user_name = temp;
2267 strncpy(tng_data->last_user_name, block->block_contents+offset, len);
2270 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2271 temp = realloc(tng_data->first_computer_name, len);
2274 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2275 __FILE__, __LINE__);
2276 free(tng_data->first_computer_name);
2277 tng_data->first_computer_name = 0;
2278 return(TNG_CRITICAL);
2280 tng_data->first_computer_name = temp;
2281 strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
2284 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2285 temp = realloc(tng_data->last_computer_name, len);
2288 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2289 __FILE__, __LINE__);
2290 free(tng_data->last_computer_name);
2291 tng_data->last_computer_name = 0;
2292 return(TNG_CRITICAL);
2294 tng_data->last_computer_name = temp;
2295 strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
2298 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2299 temp = realloc(tng_data->first_pgp_signature, len);
2302 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2303 __FILE__, __LINE__);
2304 free(tng_data->first_pgp_signature);
2305 tng_data->first_pgp_signature = 0;
2306 return(TNG_CRITICAL);
2308 tng_data->first_pgp_signature = temp;
2309 strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
2312 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2313 temp = realloc(tng_data->last_pgp_signature, len);
2316 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2317 __FILE__, __LINE__);
2318 free(tng_data->last_pgp_signature);
2319 tng_data->last_pgp_signature = 0;
2320 return(TNG_CRITICAL);
2322 tng_data->last_pgp_signature = temp;
2323 strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
2326 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2327 temp = realloc(tng_data->forcefield_name, len);
2330 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2331 __FILE__, __LINE__);
2332 free(tng_data->forcefield_name);
2333 tng_data->forcefield_name = 0;
2334 return(TNG_CRITICAL);
2336 tng_data->forcefield_name = temp;
2337 strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
2340 memcpy(&tng_data->time, block->block_contents+offset,
2341 sizeof(tng_data->time));
2342 if(tng_data->input_endianness_swap_func_64)
2344 if(tng_data->input_endianness_swap_func_64(tng_data,
2348 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2349 __FILE__, __LINE__);
2352 offset += sizeof(tng_data->time);
2354 memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
2355 sizeof(tng_data->var_num_atoms_flag));
2356 offset += sizeof(tng_data->var_num_atoms_flag);
2358 memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
2359 sizeof(tng_data->frame_set_n_frames));
2360 if(tng_data->input_endianness_swap_func_64)
2362 if(tng_data->input_endianness_swap_func_64(tng_data,
2363 &tng_data->frame_set_n_frames)
2366 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2367 __FILE__, __LINE__);
2370 offset += sizeof(tng_data->frame_set_n_frames);
2372 memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
2373 block->block_contents+offset,
2374 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
2375 if(tng_data->input_endianness_swap_func_64)
2377 if(tng_data->input_endianness_swap_func_64(tng_data,
2378 &tng_data->first_trajectory_frame_set_input_file_pos)
2381 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2382 __FILE__, __LINE__);
2385 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
2387 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
2388 tng_data->first_trajectory_frame_set_input_file_pos;
2391 memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
2392 block->block_contents+offset,
2393 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
2394 if(tng_data->input_endianness_swap_func_64)
2396 if(tng_data->input_endianness_swap_func_64(tng_data,
2397 &tng_data->last_trajectory_frame_set_input_file_pos)
2400 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2401 __FILE__, __LINE__);
2404 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
2406 memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
2407 sizeof(tng_data->medium_stride_length));
2408 if(tng_data->input_endianness_swap_func_64)
2410 if(tng_data->input_endianness_swap_func_64(tng_data,
2411 &tng_data->medium_stride_length)
2414 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2415 __FILE__, __LINE__);
2418 offset += sizeof(tng_data->medium_stride_length);
2420 memcpy(&tng_data->long_stride_length, block->block_contents+offset,
2421 sizeof(tng_data->long_stride_length));
2422 if(tng_data->input_endianness_swap_func_64)
2424 if(tng_data->input_endianness_swap_func_64(tng_data,
2425 &tng_data->long_stride_length)
2428 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2429 __FILE__, __LINE__);
2432 offset += sizeof(tng_data->long_stride_length);
2434 if(block->block_version >= 3)
2436 memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
2437 sizeof(tng_data->distance_unit_exponential));
2438 if(tng_data->input_endianness_swap_func_64)
2440 if(tng_data->input_endianness_swap_func_64(tng_data,
2441 &tng_data->distance_unit_exponential)
2444 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2445 __FILE__, __LINE__);
2450 return(TNG_SUCCESS);
2453 /** Write a general info block. This is the first block of a TNG file.
2454 * @param tng_data is a trajectory data container.
2455 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2456 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2457 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2458 * error has occured.
2460 static tng_function_status tng_general_info_block_write
2461 (tng_trajectory_t tng_data,
2462 const char hash_mode)
2464 int first_program_name_len, first_user_name_len;
2465 int first_computer_name_len, first_pgp_signature_len;
2466 int last_program_name_len, last_user_name_len;
2467 int last_computer_name_len, last_pgp_signature_len;
2468 int forcefield_name_len, name_len;
2470 tng_gen_block_t block;
2472 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2474 return(TNG_CRITICAL);
2477 fseeko(tng_data->output_file, 0, SEEK_SET);
2479 tng_block_init(&block);
2481 name_len = (int)strlen("GENERAL INFO");
2483 block->name = malloc(name_len + 1);
2486 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2487 name_len+1, __FILE__, __LINE__);
2488 tng_block_destroy(&block);
2489 return(TNG_CRITICAL);
2492 strcpy(block->name, "GENERAL INFO");
2493 block->id = TNG_GENERAL_INFO;
2495 if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
2498 fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2499 __FILE__, __LINE__);
2500 tng_block_destroy(&block);
2501 return(TNG_CRITICAL);
2504 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2506 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2508 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2510 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2512 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2514 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2516 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2518 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2520 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2523 if(block->block_contents)
2525 free(block->block_contents);
2527 block->block_contents = malloc(block->block_contents_size);
2528 if(!block->block_contents)
2530 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2531 block->block_contents_size, __FILE__, __LINE__);
2532 tng_block_destroy(&block);
2533 return(TNG_CRITICAL);
2536 strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
2537 offset += first_program_name_len;
2539 strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
2540 offset += last_program_name_len;
2542 strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
2543 offset += first_user_name_len;
2545 strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
2546 offset += last_user_name_len;
2548 strncpy(block->block_contents+offset, tng_data->first_computer_name,
2549 first_computer_name_len);
2550 offset += first_computer_name_len;
2552 strncpy(block->block_contents+offset, tng_data->last_computer_name,
2553 last_computer_name_len);
2554 offset += last_computer_name_len;
2556 strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
2557 first_pgp_signature_len);
2558 offset += first_pgp_signature_len;
2560 strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
2561 last_pgp_signature_len);
2562 offset += last_pgp_signature_len;
2564 strncpy(block->block_contents+offset, tng_data->forcefield_name,
2565 forcefield_name_len);
2566 offset += forcefield_name_len;
2568 memcpy(block->block_contents+offset, &tng_data->time,
2569 sizeof(tng_data->time));
2570 if(tng_data->output_endianness_swap_func_64)
2572 if(tng_data->output_endianness_swap_func_64(tng_data,
2573 (int64_t *)block->header_contents+offset)
2576 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2577 __FILE__, __LINE__);
2580 offset += sizeof(tng_data->time);
2582 memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
2583 sizeof(tng_data->var_num_atoms_flag));
2584 offset += sizeof(tng_data->var_num_atoms_flag);
2586 memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
2587 sizeof(tng_data->frame_set_n_frames));
2588 if(tng_data->output_endianness_swap_func_64)
2590 if(tng_data->output_endianness_swap_func_64(tng_data,
2591 (int64_t *)block->header_contents+offset)
2594 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2595 __FILE__, __LINE__);
2598 offset += sizeof(tng_data->frame_set_n_frames);
2600 memcpy(block->block_contents+offset,
2601 &tng_data->first_trajectory_frame_set_output_file_pos,
2602 sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
2603 if(tng_data->output_endianness_swap_func_64)
2605 if(tng_data->output_endianness_swap_func_64(tng_data,
2606 (int64_t *)block->header_contents+offset)
2609 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2610 __FILE__, __LINE__);
2613 offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
2615 memcpy(block->block_contents+offset,
2616 &tng_data->last_trajectory_frame_set_output_file_pos,
2617 sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
2618 if(tng_data->output_endianness_swap_func_64)
2620 if(tng_data->output_endianness_swap_func_64(tng_data,
2621 (int64_t *)block->header_contents+offset)
2624 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2625 __FILE__, __LINE__);
2628 offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
2630 memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
2631 sizeof(tng_data->medium_stride_length));
2632 if(tng_data->output_endianness_swap_func_64)
2634 if(tng_data->output_endianness_swap_func_64(tng_data,
2635 (int64_t *)block->header_contents+offset)
2638 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2639 __FILE__, __LINE__);
2642 offset += sizeof(tng_data->medium_stride_length);
2644 memcpy(block->block_contents+offset, &tng_data->long_stride_length,
2645 sizeof(tng_data->long_stride_length));
2646 if(tng_data->output_endianness_swap_func_64)
2648 if(tng_data->output_endianness_swap_func_64(tng_data,
2649 (int64_t *)block->header_contents+offset)
2652 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2653 __FILE__, __LINE__);
2656 offset += sizeof(tng_data->long_stride_length);
2658 memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
2659 sizeof(tng_data->distance_unit_exponential));
2660 if(tng_data->output_endianness_swap_func_64)
2662 if(tng_data->output_endianness_swap_func_64(tng_data,
2663 (int64_t *)block->header_contents+offset)
2666 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2667 __FILE__, __LINE__);
2671 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
2673 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2674 tng_data->output_file_path, __FILE__, __LINE__);
2675 tng_block_destroy(&block);
2676 return(TNG_CRITICAL);
2679 if(fwrite(block->block_contents, block->block_contents_size, 1,
2680 tng_data->output_file) != 1)
2682 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
2683 tng_block_destroy(&block);
2684 return(TNG_CRITICAL);
2687 tng_block_destroy(&block);
2689 return(TNG_SUCCESS);
2692 /** Read the chain data of a molecules block.
2693 * @param tng_data is a trajectory data container.
2694 * @param block is a general block container.
2695 * @param chain is the chain data container.
2696 * @param offset is the offset of the block input and is updated when reading.
2697 * @return TNG_SUCCESS(0) is successful.
2699 static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
2700 tng_gen_block_t block,
2706 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2708 memcpy(&chain->id, block->block_contents+*offset,
2710 if(tng_data->input_endianness_swap_func_64)
2712 if(tng_data->input_endianness_swap_func_64(tng_data,
2716 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2717 __FILE__, __LINE__);
2720 *offset += sizeof(chain->id);
2722 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2724 chain->name = malloc(len);
2725 strncpy(chain->name,
2726 block->block_contents+*offset, len);
2729 memcpy(&chain->n_residues, block->block_contents+*offset,
2730 sizeof(chain->n_residues));
2731 if(tng_data->input_endianness_swap_func_64)
2733 if(tng_data->input_endianness_swap_func_64(tng_data,
2737 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2738 __FILE__, __LINE__);
2741 *offset += sizeof(chain->n_residues);
2743 return(TNG_SUCCESS);
2746 /** Write the chain data of a molecules block.
2747 * @param tng_data is a trajectory data container.
2748 * @param block is a general block container.
2749 * @param chain is the chain data container.
2750 * @param offset is the offset of the block output and is updated when writing.
2751 * @return TNG_SUCCESS(0) is successful.
2753 static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
2754 tng_gen_block_t block,
2760 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2762 memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
2763 if(tng_data->output_endianness_swap_func_64)
2765 if(tng_data->output_endianness_swap_func_64(tng_data,
2766 (int64_t *)block->header_contents+*offset)
2769 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2770 __FILE__, __LINE__);
2773 *offset += sizeof(chain->id);
2775 len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2776 strncpy(block->block_contents + *offset, chain->name, len);
2779 memcpy(block->block_contents+*offset, &chain->n_residues,
2780 sizeof(chain->n_residues));
2781 if(tng_data->output_endianness_swap_func_64)
2783 if(tng_data->output_endianness_swap_func_64(tng_data,
2784 (int64_t *)block->header_contents+*offset)
2787 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2788 __FILE__, __LINE__);
2791 *offset += sizeof(chain->n_residues);
2793 return(TNG_SUCCESS);
2796 /** Read the residue data of a molecules block.
2797 * @param tng_data is a trajectory data container.
2798 * @param block is a general block container.
2799 * @param residue is the residue data container.
2800 * @param offset is the offset of the block input and is updated when reading.
2801 * @return TNG_SUCCESS(0) is successful.
2803 static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
2804 tng_gen_block_t block,
2805 tng_residue_t residue,
2810 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2812 memcpy(&residue->id, block->block_contents+*offset,
2813 sizeof(residue->id));
2814 if(tng_data->input_endianness_swap_func_64)
2816 if(tng_data->input_endianness_swap_func_64(tng_data,
2820 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2821 __FILE__, __LINE__);
2824 *offset += sizeof(residue->id);
2826 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2828 residue->name = malloc(len);
2829 strncpy(residue->name,
2830 block->block_contents+*offset, len);
2833 memcpy(&residue->n_atoms, block->block_contents+*offset,
2834 sizeof(residue->n_atoms));
2835 if(tng_data->input_endianness_swap_func_64)
2837 if(tng_data->input_endianness_swap_func_64(tng_data,
2841 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2842 __FILE__, __LINE__);
2845 *offset += sizeof(residue->n_atoms);
2847 return(TNG_SUCCESS);
2850 /** Write the residue data of a molecules block.
2851 * @param tng_data is a trajectory data container.
2852 * @param block is a general block container.
2853 * @param residue is the residue data container.
2854 * @param offset is the offset of the block output and is updated when writing.
2855 * @return TNG_SUCCESS(0) is successful.
2857 static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
2858 tng_gen_block_t block,
2859 tng_residue_t residue,
2864 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2866 memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
2867 if(tng_data->output_endianness_swap_func_64)
2869 if(tng_data->output_endianness_swap_func_64(tng_data,
2870 (int64_t *)block->header_contents+*offset)
2873 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2874 __FILE__, __LINE__);
2877 *offset += sizeof(residue->id);
2879 len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2880 strncpy(block->block_contents + *offset, residue->name, len);
2883 memcpy(block->block_contents+*offset, &residue->n_atoms,
2884 sizeof(residue->n_atoms));
2885 if(tng_data->output_endianness_swap_func_64)
2887 if(tng_data->output_endianness_swap_func_64(tng_data,
2888 (int64_t *)block->header_contents+*offset)
2891 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2892 __FILE__, __LINE__);
2895 *offset += sizeof(residue->n_atoms);
2897 return(TNG_SUCCESS);
2900 /** Read the atom data of a molecules block.
2901 * @param tng_data is a trajectory data container.
2902 * @param block is a general block container.
2903 * @param atom is the atom data container.
2904 * @param offset is the offset of the block input and is updated when reading.
2905 * @return TNG_SUCCESS(0) is successful.
2907 static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
2908 tng_gen_block_t block,
2914 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2916 memcpy(&atom->id, block->block_contents+*offset,
2918 if(tng_data->input_endianness_swap_func_64)
2920 if(tng_data->input_endianness_swap_func_64(tng_data,
2924 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2925 __FILE__, __LINE__);
2928 *offset += sizeof(atom->id);
2930 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2932 atom->name = malloc(len);
2934 block->block_contents+*offset, len);
2937 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2939 atom->atom_type = malloc(len);
2940 strncpy(atom->atom_type,
2941 block->block_contents+*offset, len);
2944 return(TNG_SUCCESS);
2947 /** Write the atom data of a molecules block.
2948 * @param tng_data is a trajectory data container.
2949 * @param block is a general block container.
2950 * @param atom is the atom data container.
2951 * @param offset is the offset of the block output and is updated when writing.
2952 * @return TNG_SUCCESS(0) is successful.
2954 static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
2955 tng_gen_block_t block,
2961 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2963 memcpy(block->block_contents+*offset, &atom->id,
2965 if(tng_data->output_endianness_swap_func_64)
2967 if(tng_data->output_endianness_swap_func_64(tng_data,
2968 (int64_t *)block->header_contents+*offset)
2971 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2972 __FILE__, __LINE__);
2975 *offset += sizeof(atom->id);
2977 len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2978 strncpy(block->block_contents + *offset, atom->name, len);
2981 len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2982 strncpy(block->block_contents + *offset, atom->atom_type, len);
2985 return(TNG_SUCCESS);
2988 static tng_function_status tng_molecules_block_len_calculate
2989 (const tng_trajectory_t tng_data,
2993 tng_molecule_t molecule;
2995 tng_residue_t residue;
3001 for(i = 0; i < tng_data->n_molecules; i++)
3003 molecule = &tng_data->molecules[i];
3006 molecule->name = malloc(1);
3009 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3010 __FILE__, __LINE__);
3011 return(TNG_CRITICAL);
3013 molecule->name[0] = 0;
3015 *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3017 chain = molecule->chains;
3018 for(j = 0; j < molecule->n_chains; j++)
3020 *len += sizeof(chain->id);
3024 chain->name = malloc(1);
3027 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3028 __FILE__, __LINE__);
3029 return(TNG_CRITICAL);
3033 *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
3035 *len += sizeof(chain->n_residues);
3040 residue = molecule->residues;
3041 for(j = 0; j < molecule->n_residues; j++)
3043 *len += sizeof(residue->id);
3047 residue->name = malloc(1);
3050 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3051 __FILE__, __LINE__);
3052 return(TNG_CRITICAL);
3054 residue->name[0] = 0;
3056 *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
3058 *len += sizeof(residue->n_atoms);
3063 atom = molecule->atoms;
3064 for(j = 0; j < molecule->n_atoms; j++)
3066 *len += sizeof(atom->id);
3069 atom->name = malloc(1);
3072 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3073 __FILE__, __LINE__);
3074 return(TNG_CRITICAL);
3078 *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
3080 if(!atom->atom_type)
3082 atom->atom_type = malloc(1);
3083 if(!atom->atom_type)
3085 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3086 __FILE__, __LINE__);
3087 return(TNG_CRITICAL);
3089 atom->atom_type[0] = 0;
3091 *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
3096 for(j = 0; j < molecule->n_bonds; j++)
3098 *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
3101 *len += sizeof(tng_data->n_molecules) +
3102 (sizeof(molecule->id) +
3103 sizeof(molecule->quaternary_str) +
3104 sizeof(molecule->n_chains) +
3105 sizeof(molecule->n_residues) +
3106 sizeof(molecule->n_atoms) +
3107 sizeof(molecule->n_bonds)) *
3108 tng_data->n_molecules;
3110 if(!tng_data->var_num_atoms_flag)
3112 *len += tng_data->n_molecules * sizeof(int64_t);
3115 return(TNG_SUCCESS);
3118 /** Read a molecules block. Contains chain, residue and atom data
3119 * @param tng_data is a trajectory data container.
3120 * @param block is a general block container.
3121 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3122 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3123 * compared to the md5 hash of the read contents to ensure valid data.
3124 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3125 * error has occured.
3127 static tng_function_status tng_molecules_block_read
3128 (tng_trajectory_t tng_data,
3129 tng_gen_block_t block,
3130 const char hash_mode)
3133 int len, offset = 0;
3134 tng_molecule_t molecule;
3136 tng_residue_t residue;
3141 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3143 return(TNG_CRITICAL);
3146 if(block->block_contents)
3148 free(block->block_contents);
3151 block->block_contents = malloc(block->block_contents_size);
3152 if(!block->block_contents)
3154 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3155 block->block_contents_size, __FILE__, __LINE__);
3156 return(TNG_CRITICAL);
3159 /* Read the whole block into block_contents to be able to write it to disk
3160 * even if it cannot be interpreted. */
3161 if(fread(block->block_contents, block->block_contents_size, 1,
3162 tng_data->input_file) == 0)
3164 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3167 /* FIXME: Does not check if the size of the contents matches the expected
3168 * size or if the contents can be read. */
3170 if(hash_mode == TNG_USE_HASH)
3172 tng_md5_hash_match_verify(block, &same_hash);
3173 if(same_hash != TNG_TRUE)
3175 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3177 __FILE__, __LINE__);
3181 if(tng_data->molecules)
3183 for(i=0; i<tng_data->n_molecules; i++)
3185 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
3187 free(tng_data->molecules);
3188 tng_data->molecules = 0;
3189 tng_data->n_molecules = 0;
3192 memcpy(&tng_data->n_molecules, block->block_contents,
3193 sizeof(tng_data->n_molecules));
3194 if(tng_data->input_endianness_swap_func_64)
3196 if(tng_data->input_endianness_swap_func_64(tng_data,
3197 &tng_data->n_molecules)
3200 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3201 __FILE__, __LINE__);
3204 offset += sizeof(tng_data->n_molecules);
3206 if(tng_data->molecules)
3208 free(tng_data->molecules);
3211 tng_data->n_particles = 0;
3213 tng_data->molecules = malloc(tng_data->n_molecules *
3214 sizeof(struct tng_molecule));
3215 if(!tng_data->molecules)
3217 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3218 tng_data->n_molecules * sizeof(struct tng_molecule),
3219 __FILE__, __LINE__);
3220 return(TNG_CRITICAL);
3223 if(!tng_data->var_num_atoms_flag)
3225 if(tng_data->molecule_cnt_list)
3227 free(tng_data->molecule_cnt_list);
3229 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
3230 tng_data->n_molecules);
3231 if(!tng_data->molecule_cnt_list)
3233 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3234 tng_data->n_molecules * sizeof(struct tng_molecule),
3235 __FILE__, __LINE__);
3236 return(TNG_CRITICAL);
3240 /* Read each molecule from file */
3241 for(i=0; i < tng_data->n_molecules; i++)
3243 molecule = &tng_data->molecules[i];
3245 memcpy(&molecule->id, block->block_contents+offset,
3246 sizeof(molecule->id));
3247 if(tng_data->input_endianness_swap_func_64)
3249 if(tng_data->input_endianness_swap_func_64(tng_data,
3253 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3254 __FILE__, __LINE__);
3257 offset += sizeof(molecule->id);
3259 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
3260 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
3261 molecule->name = malloc(len);
3262 strncpy(molecule->name, block->block_contents+offset, len);
3265 memcpy(&molecule->quaternary_str, block->block_contents+offset,
3266 sizeof(molecule->quaternary_str));
3267 if(tng_data->input_endianness_swap_func_64)
3269 if(tng_data->input_endianness_swap_func_64(tng_data,
3270 &molecule->quaternary_str)
3273 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3274 __FILE__, __LINE__);
3277 offset += sizeof(molecule->quaternary_str);
3279 if(!tng_data->var_num_atoms_flag)
3281 memcpy(&tng_data->molecule_cnt_list[i],
3282 block->block_contents+offset,
3284 if(tng_data->input_endianness_swap_func_64)
3286 if(tng_data->input_endianness_swap_func_64(tng_data,
3287 &tng_data->molecule_cnt_list[i])
3290 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3291 __FILE__, __LINE__);
3294 offset += sizeof(int64_t);
3298 memcpy(&molecule->n_chains, block->block_contents+offset,
3299 sizeof(molecule->n_chains));
3300 if(tng_data->input_endianness_swap_func_64)
3302 if(tng_data->input_endianness_swap_func_64(tng_data,
3303 &molecule->n_chains)
3306 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3307 __FILE__, __LINE__);
3310 offset += sizeof(molecule->n_chains);
3312 memcpy(&molecule->n_residues, block->block_contents+offset,
3313 sizeof(molecule->n_residues));
3314 if(tng_data->input_endianness_swap_func_64)
3316 if(tng_data->input_endianness_swap_func_64(tng_data,
3317 &molecule->n_residues)
3320 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3321 __FILE__, __LINE__);
3324 offset += sizeof(molecule->n_residues);
3326 memcpy(&molecule->n_atoms, block->block_contents+offset,
3327 sizeof(molecule->n_atoms));
3328 if(tng_data->input_endianness_swap_func_64)
3330 if(tng_data->input_endianness_swap_func_64(tng_data,
3334 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3335 __FILE__, __LINE__);
3338 offset += sizeof(molecule->n_atoms);
3340 tng_data->n_particles += molecule->n_atoms *
3341 tng_data->molecule_cnt_list[i];
3343 if(molecule->n_chains > 0)
3345 molecule->chains = malloc(molecule->n_chains *
3346 sizeof(struct tng_chain));
3347 if(!molecule->chains)
3349 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3350 molecule->n_chains * sizeof(struct tng_chain),
3351 __FILE__, __LINE__);
3352 return(TNG_CRITICAL);
3355 chain = molecule->chains;
3362 if(molecule->n_residues > 0)
3364 molecule->residues = malloc(molecule->n_residues *
3365 sizeof(struct tng_residue));
3366 if(!molecule->residues)
3368 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3369 molecule->n_residues * sizeof(struct tng_residue),
3370 __FILE__, __LINE__);
3371 if(molecule->chains)
3373 free(molecule->chains);
3374 molecule->chains = 0;
3376 return(TNG_CRITICAL);
3379 residue = molecule->residues;
3386 molecule->atoms = malloc(molecule->n_atoms *
3387 sizeof(struct tng_atom));
3388 if(!molecule->atoms)
3390 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3391 molecule->n_atoms * sizeof(struct tng_atom),
3392 __FILE__, __LINE__);
3393 if(molecule->chains)
3395 free(molecule->chains);
3396 molecule->chains = 0;
3398 if(molecule->residues)
3400 free(molecule->residues);
3401 molecule->residues = 0;
3403 return(TNG_CRITICAL);
3406 atom = molecule->atoms;
3408 if(molecule->n_chains > 0)
3410 /* Read the chains of the molecule */
3411 for(j=0; j<molecule->n_chains; j++)
3413 chain->molecule = molecule;
3415 tng_chain_data_read(tng_data, block, chain, &offset);
3417 chain->residues = molecule->residues;
3418 residue = chain->residues;
3420 /* Read the residues of the chain */
3421 for(k=0; k<chain->n_residues; k++)
3423 residue->chain = chain;
3425 tng_residue_data_read(tng_data, block, residue, &offset);
3427 residue->atoms_offset = atom - molecule->atoms;
3428 /* Read the atoms of the residue */
3429 for(l=0; l<residue->n_atoms; l++)
3431 atom->residue = residue;
3433 tng_atom_data_read(tng_data, block, atom, &offset);
3444 if(molecule->n_residues > 0)
3446 for(k=0; k<molecule->n_residues; k++)
3450 tng_residue_data_read(tng_data, block, residue, &offset);
3452 residue->atoms_offset = atom - molecule->atoms;
3453 /* Read the atoms of the residue */
3454 for(l=0; l<residue->n_atoms; l++)
3456 atom->residue = residue;
3458 tng_atom_data_read(tng_data, block, atom, &offset);
3467 for(l=0; l<molecule->n_atoms; l++)
3471 tng_atom_data_read(tng_data, block, atom, &offset);
3478 memcpy(&molecule->n_bonds, block->block_contents+offset,
3479 sizeof(molecule->n_bonds));
3480 if(tng_data->input_endianness_swap_func_64)
3482 if(tng_data->input_endianness_swap_func_64(tng_data,
3486 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3487 __FILE__, __LINE__);
3490 offset += sizeof(molecule->n_bonds);
3492 if(molecule->n_bonds > 0)
3494 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
3495 sizeof(struct tng_bond));
3496 if(!molecule->bonds)
3498 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3499 molecule->n_bonds * sizeof(struct tng_bond),
3500 __FILE__, __LINE__);
3501 if(molecule->chains)
3503 free(molecule->chains);
3504 molecule->chains = 0;
3506 if(molecule->residues)
3508 free(molecule->residues);
3509 molecule->residues = 0;
3513 free(molecule->atoms);
3514 molecule->atoms = 0;
3516 return(TNG_CRITICAL);
3519 bond = molecule->bonds;
3521 for(j=0; j<molecule->n_bonds; j++)
3523 memcpy(&bond->from_atom_id, block->block_contents+offset,
3524 sizeof(bond->from_atom_id));
3525 if(tng_data->input_endianness_swap_func_64)
3527 if(tng_data->input_endianness_swap_func_64(tng_data,
3528 &bond->from_atom_id)
3531 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3532 __FILE__, __LINE__);
3535 offset += sizeof(bond->from_atom_id);
3537 memcpy(&bond->to_atom_id, block->block_contents+offset,
3538 sizeof(bond->to_atom_id));
3539 if(tng_data->input_endianness_swap_func_64)
3541 if(tng_data->input_endianness_swap_func_64(tng_data,
3545 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3546 __FILE__, __LINE__);
3549 offset += sizeof(bond->to_atom_id);
3556 molecule->bonds = 0;
3560 return(TNG_SUCCESS);
3563 /** Write a molecules block.
3564 * @param tng_data is a trajectory data container.
3565 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3566 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3567 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3568 * error has occured.
3570 static tng_function_status tng_molecules_block_write
3571 (tng_trajectory_t tng_data,
3572 const char hash_mode)
3574 int len = 0, name_len, offset = 0;
3576 tng_molecule_t molecule;
3578 tng_residue_t residue;
3581 tng_gen_block_t block;
3583 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3585 return(TNG_CRITICAL);
3588 tng_block_init(&block);
3590 name_len = (int)strlen("MOLECULES");
3592 block->name = malloc(name_len + 1);
3595 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3596 name_len+1, __FILE__, __LINE__);
3597 tng_block_destroy(&block);
3598 return(TNG_CRITICAL);
3601 strcpy(block->name, "MOLECULES");
3602 block->id = TNG_MOLECULES;
3604 if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
3607 fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3608 __FILE__, __LINE__);
3609 tng_block_destroy(&block);
3610 return(TNG_CRITICAL);
3613 block->block_contents = malloc(block->block_contents_size);
3614 if(!block->block_contents)
3616 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3617 block->block_contents_size, __FILE__, __LINE__);
3618 tng_block_destroy(&block);
3619 return(TNG_CRITICAL);
3622 memcpy(block->block_contents+offset, &tng_data->n_molecules,
3623 sizeof(tng_data->n_molecules));
3624 if(tng_data->output_endianness_swap_func_64)
3626 if(tng_data->output_endianness_swap_func_64(tng_data,
3627 (int64_t *)block->header_contents+offset)
3630 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3631 __FILE__, __LINE__);
3634 offset += sizeof(tng_data->n_molecules);
3636 for(i = 0; i < tng_data->n_molecules; i++)
3638 molecule = &tng_data->molecules[i];
3639 memcpy(block->block_contents+offset, &molecule->id,
3640 sizeof(molecule->id));
3641 if(tng_data->output_endianness_swap_func_64)
3643 if(tng_data->output_endianness_swap_func_64(tng_data,
3644 (int64_t *)block->header_contents+offset)
3647 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3648 __FILE__, __LINE__);
3651 offset += sizeof(molecule->id);
3653 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
3654 len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3655 strncpy(block->block_contents + offset, molecule->name, len);
3658 memcpy(block->block_contents+offset, &molecule->quaternary_str,
3659 sizeof(molecule->quaternary_str));
3660 if(tng_data->output_endianness_swap_func_64)
3662 if(tng_data->output_endianness_swap_func_64(tng_data,
3663 (int64_t *)block->header_contents+offset)
3666 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3667 __FILE__, __LINE__);
3670 offset += sizeof(molecule->quaternary_str);
3672 if(!tng_data->var_num_atoms_flag)
3674 memcpy(block->block_contents+offset,
3675 &tng_data->molecule_cnt_list[i], sizeof(int64_t));
3676 if(tng_data->output_endianness_swap_func_64)
3678 if(tng_data->output_endianness_swap_func_64(tng_data,
3679 (int64_t *)block->header_contents+offset)
3682 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3683 __FILE__, __LINE__);
3686 offset += sizeof(int64_t);
3689 memcpy(block->block_contents+offset, &molecule->n_chains,
3690 sizeof(molecule->n_chains));
3691 if(tng_data->output_endianness_swap_func_64)
3693 if(tng_data->output_endianness_swap_func_64(tng_data,
3694 (int64_t *)block->header_contents+offset)
3697 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3698 __FILE__, __LINE__);
3701 offset += sizeof(molecule->n_chains);
3703 memcpy(block->block_contents+offset, &molecule->n_residues,
3704 sizeof(molecule->n_residues));
3705 if(tng_data->output_endianness_swap_func_64)
3707 if(tng_data->output_endianness_swap_func_64(tng_data,
3708 (int64_t *)block->header_contents+offset)
3711 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3712 __FILE__, __LINE__);
3715 offset += sizeof(molecule->n_residues);
3717 memcpy(block->block_contents+offset, &molecule->n_atoms,
3718 sizeof(molecule->n_atoms));
3719 if(tng_data->output_endianness_swap_func_64)
3721 if(tng_data->output_endianness_swap_func_64(tng_data,
3722 (int64_t *)block->header_contents+offset)
3725 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3726 __FILE__, __LINE__);
3729 offset += sizeof(molecule->n_atoms);
3731 if(molecule->n_chains > 0)
3733 chain = molecule->chains;
3734 for(j = 0; j < molecule->n_chains; j++)
3736 tng_chain_data_write(tng_data, block, chain, &offset);
3738 residue = chain->residues;
3739 for(k = 0; k < chain->n_residues; k++)
3741 tng_residue_data_write(tng_data, block, residue, &offset);
3743 atom = molecule->atoms + residue->atoms_offset;
3744 for(l = 0; l < residue->n_atoms; l++)
3746 tng_atom_data_write(tng_data, block, atom, &offset);
3757 if(molecule->n_residues > 0)
3759 residue = molecule->residues;
3760 for(k = 0; k < molecule->n_residues; k++)
3762 tng_residue_data_write(tng_data, block, residue, &offset);
3764 atom = molecule->atoms + residue->atoms_offset;
3765 for(l = 0; l < residue->n_atoms; l++)
3767 tng_atom_data_write(tng_data, block, atom, &offset);
3776 atom = molecule->atoms;
3777 for(l = 0; l < molecule->n_atoms; l++)
3779 tng_atom_data_write(tng_data, block, atom, &offset);
3786 memcpy(block->block_contents+offset, &molecule->n_bonds,
3787 sizeof(molecule->n_bonds));
3788 if(tng_data->output_endianness_swap_func_64)
3790 if(tng_data->output_endianness_swap_func_64(tng_data,
3791 (int64_t *)block->header_contents+offset)
3794 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3795 __FILE__, __LINE__);
3798 offset += sizeof(molecule->n_bonds);
3800 bond = molecule->bonds;
3801 for(j = 0; j < molecule->n_bonds; j++)
3803 memcpy(block->block_contents+offset, &bond->from_atom_id,
3804 sizeof(bond->from_atom_id));
3805 if(tng_data->output_endianness_swap_func_64)
3807 if(tng_data->output_endianness_swap_func_64(tng_data,
3808 (int64_t *)block->header_contents+offset)
3811 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3812 __FILE__, __LINE__);
3815 offset += sizeof(bond->from_atom_id);
3817 memcpy(block->block_contents+offset, &bond->to_atom_id,
3818 sizeof(bond->to_atom_id));
3819 if(tng_data->output_endianness_swap_func_64)
3821 if(tng_data->output_endianness_swap_func_64(tng_data,
3822 (int64_t *)block->header_contents+offset)
3825 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3826 __FILE__, __LINE__);
3829 offset += sizeof(bond->to_atom_id);
3835 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3837 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3838 tng_data->output_file_path, __FILE__, __LINE__);
3839 tng_block_destroy(&block);
3840 return(TNG_CRITICAL);
3843 if(fwrite(block->block_contents, block->block_contents_size, 1,
3844 tng_data->output_file) != 1)
3846 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
3847 __FILE__, __LINE__);
3848 tng_block_destroy(&block);
3849 return(TNG_CRITICAL);
3852 tng_block_destroy(&block);
3854 return(TNG_SUCCESS);
3857 static tng_function_status tng_frame_set_block_len_calculate
3858 (const tng_trajectory_t tng_data,
3861 *len = sizeof(int64_t) * 8;
3862 *len += sizeof(double) * 2;
3864 if(tng_data->var_num_atoms_flag)
3866 *len += sizeof(int64_t) * tng_data->n_molecules;
3868 return(TNG_SUCCESS);
3871 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
3872 * @param tng_data is a trajectory data container.
3873 * @param block is a general block container.
3874 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3875 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3876 * compared to the md5 hash of the read contents to ensure valid data.
3877 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3878 * error has occured.
3880 static tng_function_status tng_frame_set_block_read
3881 (tng_trajectory_t tng_data,
3882 tng_gen_block_t block,
3883 const char hash_mode)
3886 int64_t file_pos, i, prev_n_particles;
3888 tng_trajectory_frame_set_t frame_set =
3889 &tng_data->current_trajectory_frame_set;
3891 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3893 return(TNG_CRITICAL);
3896 if(block->block_contents)
3898 free(block->block_contents);
3901 block->block_contents = malloc(block->block_contents_size);
3902 if(!block->block_contents)
3904 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3905 block->block_contents_size, __FILE__, __LINE__);
3906 return(TNG_CRITICAL);
3909 /* Read the whole block into block_contents to be able to write it to
3910 * disk even if it cannot be interpreted. */
3911 if(fread(block->block_contents, block->block_contents_size, 1,
3912 tng_data->input_file) == 0)
3914 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3915 return(TNG_CRITICAL);
3918 /* FIXME: Does not check if the size of the contents matches the expected
3919 * size or if the contents can be read. */
3921 file_pos = (int64_t)ftello(tng_data->input_file) -
3922 (block->block_contents_size + block->header_contents_size);
3924 if(hash_mode == TNG_USE_HASH)
3926 tng_md5_hash_match_verify(block, &same_hash);
3927 if(same_hash != TNG_TRUE)
3929 fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %"PRId64" Hashes do not match. "
3931 file_pos, __FILE__, __LINE__);
3932 /* return(TNG_FAILURE); */
3936 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3938 tng_frame_set_particle_mapping_free(tng_data);
3940 if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
3942 tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
3944 /* FIXME: Should check the frame number instead of the file_pos, in case
3945 * frame sets are not in order */
3946 if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
3948 tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
3951 memcpy(&frame_set->first_frame, block->block_contents,
3952 sizeof(frame_set->first_frame));
3953 if(tng_data->input_endianness_swap_func_64)
3955 if(tng_data->input_endianness_swap_func_64(tng_data,
3956 &frame_set->first_frame)
3959 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3960 __FILE__, __LINE__);
3963 offset += sizeof(frame_set->first_frame);
3965 memcpy(&frame_set->n_frames, block->block_contents + offset,
3966 sizeof(frame_set->n_frames));
3967 if(tng_data->input_endianness_swap_func_64)
3969 if(tng_data->input_endianness_swap_func_64(tng_data,
3970 &frame_set->n_frames)
3973 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3974 __FILE__, __LINE__);
3977 offset += sizeof(frame_set->n_frames);
3979 if(tng_data->var_num_atoms_flag)
3981 prev_n_particles = frame_set->n_particles;
3982 frame_set->n_particles = 0;
3983 /* If the list of molecule counts has already been created assume that
3984 * it is of correct size. */
3985 if(!frame_set->molecule_cnt_list)
3987 frame_set->molecule_cnt_list =
3988 malloc(sizeof(int64_t) * tng_data->n_molecules);
3990 if(!frame_set->molecule_cnt_list)
3992 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3993 sizeof(int64_t) * tng_data->n_molecules,
3994 __FILE__, __LINE__);
3995 return(TNG_CRITICAL);
3998 for(i = 0; i < tng_data->n_molecules; i++)
4000 memcpy(&frame_set->molecule_cnt_list[i],
4001 block->block_contents + offset,
4003 if(tng_data->input_endianness_swap_func_64)
4005 if(tng_data->input_endianness_swap_func_64(tng_data,
4006 &frame_set->molecule_cnt_list[i])
4009 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4010 __FILE__, __LINE__);
4013 offset += sizeof(int64_t);
4014 frame_set->n_particles += tng_data->molecules[i].n_atoms *
4015 frame_set->molecule_cnt_list[i];
4017 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
4019 /* FIXME: Particle dependent data memory management */
4023 memcpy(&frame_set->next_frame_set_file_pos,
4024 block->block_contents + offset,
4025 sizeof(frame_set->next_frame_set_file_pos));
4026 if(tng_data->input_endianness_swap_func_64)
4028 if(tng_data->input_endianness_swap_func_64(tng_data,
4029 &frame_set->next_frame_set_file_pos)
4032 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4033 __FILE__, __LINE__);
4036 offset += sizeof(frame_set->next_frame_set_file_pos);
4038 memcpy(&frame_set->prev_frame_set_file_pos,
4039 block->block_contents + offset,
4040 sizeof(frame_set->prev_frame_set_file_pos));
4041 if(tng_data->input_endianness_swap_func_64)
4043 if(tng_data->input_endianness_swap_func_64(tng_data,
4044 &frame_set->prev_frame_set_file_pos)
4047 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4048 __FILE__, __LINE__);
4051 offset += sizeof(frame_set->prev_frame_set_file_pos);
4053 memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
4054 block->block_contents + offset,
4055 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4056 if(tng_data->input_endianness_swap_func_64)
4058 if(tng_data->input_endianness_swap_func_64(tng_data,
4059 &frame_set->medium_stride_next_frame_set_file_pos)
4062 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4063 __FILE__, __LINE__);
4066 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4068 memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
4069 block->block_contents + offset,
4070 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4071 if(tng_data->input_endianness_swap_func_64)
4073 if(tng_data->input_endianness_swap_func_64(tng_data,
4074 &frame_set->medium_stride_prev_frame_set_file_pos)
4077 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4078 __FILE__, __LINE__);
4081 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4083 memcpy(&frame_set->long_stride_next_frame_set_file_pos,
4084 block->block_contents + offset,
4085 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4086 if(tng_data->input_endianness_swap_func_64)
4088 if(tng_data->input_endianness_swap_func_64(tng_data,
4089 &frame_set->long_stride_next_frame_set_file_pos)
4092 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4093 __FILE__, __LINE__);
4096 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4098 memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
4099 block->block_contents + offset,
4100 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4101 if(tng_data->input_endianness_swap_func_64)
4103 if(tng_data->input_endianness_swap_func_64(tng_data,
4104 &frame_set->long_stride_prev_frame_set_file_pos)
4107 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4108 __FILE__, __LINE__);
4111 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4113 if(block->block_version >= 3)
4115 memcpy(&frame_set->first_frame_time,
4116 block->block_contents + offset,
4117 sizeof(frame_set->first_frame_time));
4118 if(tng_data->input_endianness_swap_func_64)
4120 if(tng_data->input_endianness_swap_func_64(tng_data,
4121 (int64_t *)&frame_set->first_frame_time)
4124 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4125 __FILE__, __LINE__);
4128 offset += sizeof(frame_set->first_frame_time);
4130 memcpy(&tng_data->time_per_frame,
4131 block->block_contents + offset,
4132 sizeof(tng_data->time_per_frame));
4133 if(tng_data->input_endianness_swap_func_64)
4135 if(tng_data->input_endianness_swap_func_64(tng_data,
4136 (int64_t *)&tng_data->time_per_frame)
4139 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4140 __FILE__, __LINE__);
4146 frame_set->first_frame_time = -1;
4147 tng_data->time_per_frame = -1;
4150 /* If the output file and the input files are the same the number of
4151 * frames in the file are the same number as has just been read.
4152 * This is updated here to later on see if there have been new frames
4153 * added and thereby the frame set needs to be rewritten. */
4154 if(tng_data->output_file == tng_data->input_file)
4156 frame_set->n_written_frames = frame_set->n_frames;
4159 return(TNG_SUCCESS);
4162 /** Write tng_data->current_trajectory_frame_set to file
4163 * @param tng_data is a trajectory data container.
4164 * @param block is a general block container.
4165 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4166 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4167 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4168 * error has occured.
4170 static tng_function_status tng_frame_set_block_write
4171 (tng_trajectory_t tng_data,
4172 tng_gen_block_t block,
4173 const char hash_mode)
4178 unsigned int name_len;
4179 tng_trajectory_frame_set_t frame_set =
4180 &tng_data->current_trajectory_frame_set;
4182 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4184 return(TNG_CRITICAL);
4187 name_len = (int)strlen("TRAJECTORY FRAME SET");
4189 if(!block->name || strlen(block->name) < name_len)
4191 temp_name = realloc(block->name, name_len + 1);
4194 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4195 name_len+1, __FILE__, __LINE__);
4198 return(TNG_CRITICAL);
4200 block->name = temp_name;
4202 strcpy(block->name, "TRAJECTORY FRAME SET");
4203 block->id = TNG_TRAJECTORY_FRAME_SET;
4205 if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
4208 fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
4209 __FILE__, __LINE__);
4210 return(TNG_CRITICAL);
4213 if(block->block_contents)
4215 free(block->block_contents);
4217 block->block_contents = malloc(block->block_contents_size);
4218 if(!block->block_contents)
4220 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4221 block->block_contents_size, __FILE__, __LINE__);
4222 return(TNG_CRITICAL);
4225 memcpy(block->block_contents, &frame_set->first_frame,
4226 sizeof(frame_set->first_frame));
4227 if(tng_data->output_endianness_swap_func_64)
4229 if(tng_data->output_endianness_swap_func_64(tng_data,
4230 (int64_t *)block->header_contents+offset)
4233 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4234 __FILE__, __LINE__);
4237 offset += sizeof(frame_set->first_frame);
4239 memcpy(block->block_contents+offset, &frame_set->n_frames,
4240 sizeof(frame_set->n_frames));
4241 if(tng_data->output_endianness_swap_func_64)
4243 if(tng_data->output_endianness_swap_func_64(tng_data,
4244 (int64_t *)block->header_contents+offset)
4247 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4248 __FILE__, __LINE__);
4251 offset += sizeof(frame_set->n_frames);
4253 if(tng_data->var_num_atoms_flag)
4255 for(i = 0; i < tng_data->n_molecules; i++)
4257 memcpy(block->block_contents+offset,
4258 &frame_set->molecule_cnt_list[i],
4260 if(tng_data->output_endianness_swap_func_64)
4262 if(tng_data->output_endianness_swap_func_64(tng_data,
4263 (int64_t *)block->header_contents+offset)
4266 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4267 __FILE__, __LINE__);
4270 offset += sizeof(int64_t);
4275 memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
4276 sizeof(frame_set->next_frame_set_file_pos));
4277 if(tng_data->output_endianness_swap_func_64)
4279 if(tng_data->output_endianness_swap_func_64(tng_data,
4280 (int64_t *)block->header_contents+offset)
4283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4284 __FILE__, __LINE__);
4287 offset += sizeof(frame_set->next_frame_set_file_pos);
4289 memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
4290 sizeof(frame_set->prev_frame_set_file_pos));
4291 if(tng_data->output_endianness_swap_func_64)
4293 if(tng_data->output_endianness_swap_func_64(tng_data,
4294 (int64_t *)block->header_contents+offset)
4297 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4298 __FILE__, __LINE__);
4301 offset += sizeof(frame_set->prev_frame_set_file_pos);
4303 memcpy(block->block_contents+offset,
4304 &frame_set->medium_stride_next_frame_set_file_pos,
4305 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4306 if(tng_data->output_endianness_swap_func_64)
4308 if(tng_data->output_endianness_swap_func_64(tng_data,
4309 (int64_t *)block->header_contents+offset)
4312 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4313 __FILE__, __LINE__);
4316 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4318 memcpy(block->block_contents+offset,
4319 &frame_set->medium_stride_prev_frame_set_file_pos,
4320 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4321 if(tng_data->output_endianness_swap_func_64)
4323 if(tng_data->output_endianness_swap_func_64(tng_data,
4324 (int64_t *)block->header_contents+offset)
4327 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4328 __FILE__, __LINE__);
4331 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4333 memcpy(block->block_contents+offset,
4334 &frame_set->long_stride_next_frame_set_file_pos,
4335 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4336 if(tng_data->output_endianness_swap_func_64)
4338 if(tng_data->output_endianness_swap_func_64(tng_data,
4339 (int64_t *)block->header_contents+offset)
4342 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4343 __FILE__, __LINE__);
4346 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4348 memcpy(block->block_contents+offset,
4349 &frame_set->long_stride_prev_frame_set_file_pos,
4350 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4351 if(tng_data->output_endianness_swap_func_64)
4353 if(tng_data->output_endianness_swap_func_64(tng_data,
4354 (int64_t *)block->header_contents+offset)
4357 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4358 __FILE__, __LINE__);
4361 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4363 memcpy(block->block_contents+offset,
4364 &frame_set->first_frame_time,
4365 sizeof(frame_set->first_frame_time));
4366 if(tng_data->output_endianness_swap_func_64)
4368 if(tng_data->output_endianness_swap_func_64(tng_data,
4369 (int64_t *)block->header_contents+offset)
4372 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4373 __FILE__, __LINE__);
4376 offset += sizeof(frame_set->first_frame_time);
4378 memcpy(block->block_contents+offset,
4379 &tng_data->time_per_frame,
4380 sizeof(tng_data->time_per_frame));
4381 if(tng_data->output_endianness_swap_func_64)
4383 if(tng_data->output_endianness_swap_func_64(tng_data,
4384 (int64_t *)block->header_contents+offset)
4387 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4388 __FILE__, __LINE__);
4392 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4394 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4395 tng_data->output_file_path, __FILE__, __LINE__);
4396 return(TNG_CRITICAL);
4399 if(fwrite(block->block_contents, block->block_contents_size, 1,
4400 tng_data->output_file) != 1)
4402 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4403 return(TNG_CRITICAL);
4406 return(TNG_SUCCESS);
4409 static tng_function_status tng_trajectory_mapping_block_len_calculate
4410 (const tng_trajectory_t tng_data,
4411 const int64_t n_particles,
4415 *len = sizeof(int64_t) * (2 + n_particles);
4417 return(TNG_SUCCESS);
4420 /** Read an atom mappings block (translating between real atom indexes and how
4421 * the atom info is written in this frame set).
4422 * @param tng_data is a trajectory data container.
4423 * @param block is a general block container.
4424 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4425 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
4426 * compared to the md5 hash of the read contents to ensure valid data.
4427 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4428 * error has occured.
4430 static tng_function_status tng_trajectory_mapping_block_read
4431 (tng_trajectory_t tng_data,
4432 tng_gen_block_t block,
4433 const char hash_mode)
4438 tng_trajectory_frame_set_t frame_set =
4439 &tng_data->current_trajectory_frame_set;
4441 tng_particle_mapping_t mapping, mappings;
4443 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
4445 return(TNG_CRITICAL);
4448 if(block->block_contents)
4450 free(block->block_contents);
4453 block->block_contents = malloc(block->block_contents_size);
4454 if(!block->block_contents)
4456 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4457 block->block_contents_size, __FILE__, __LINE__);
4458 return(TNG_CRITICAL);
4461 /* Read the whole block into block_contents to be able to write it to disk
4462 * even if it cannot be interpreted. */
4463 if(fread(block->block_contents, block->block_contents_size, 1,
4464 tng_data->input_file) == 0)
4466 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
4467 return(TNG_CRITICAL);
4470 /* FIXME: Does not check if the size of the contents matches the expected
4471 * size or if the contents can be read. */
4473 if(hash_mode == TNG_USE_HASH)
4475 tng_md5_hash_match_verify(block, &same_hash);
4476 if(same_hash != TNG_TRUE)
4478 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4480 __FILE__, __LINE__);
4481 /* return(TNG_FAILURE); */
4485 frame_set->n_mapping_blocks++;
4486 mappings = realloc(frame_set->mappings,
4487 sizeof(struct tng_particle_mapping) *
4488 frame_set->n_mapping_blocks);
4491 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4492 block->block_contents_size, __FILE__, __LINE__);
4493 free(frame_set->mappings);
4494 frame_set->mappings = 0;
4495 return(TNG_CRITICAL);
4497 frame_set->mappings = mappings;
4498 mapping = &mappings[frame_set->n_mapping_blocks - 1];
4501 memcpy(&mapping->num_first_particle, block->block_contents+offset,
4502 sizeof(mapping->num_first_particle));
4503 if(tng_data->input_endianness_swap_func_64)
4505 if(tng_data->input_endianness_swap_func_64(tng_data,
4506 &mapping->num_first_particle)
4509 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4510 __FILE__, __LINE__);
4513 offset += sizeof(mapping->num_first_particle);
4515 memcpy(&mapping->n_particles, block->block_contents+offset,
4516 sizeof(mapping->n_particles));
4517 if(tng_data->input_endianness_swap_func_64)
4519 if(tng_data->input_endianness_swap_func_64(tng_data,
4520 &mapping->n_particles)
4523 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4524 __FILE__, __LINE__);
4527 offset += sizeof(mapping->n_particles);
4529 mapping->real_particle_numbers = malloc(mapping->n_particles *
4531 if(!mapping->real_particle_numbers)
4533 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4534 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
4535 return(TNG_CRITICAL);
4538 /* If the byte order needs to be swapped the data must be read one value at
4539 * a time and swapped */
4540 if(tng_data->input_endianness_swap_func_64)
4542 for(i = 0; i < mapping->n_particles; i++)
4544 memcpy(&mapping->real_particle_numbers[i],
4545 block->block_contents + offset,
4547 if(tng_data->input_endianness_swap_func_64(tng_data,
4548 &mapping->real_particle_numbers[i])
4551 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4552 __FILE__, __LINE__);
4554 offset += sizeof(int64_t);
4557 /* Otherwise the data can be read all at once */
4560 memcpy(mapping->real_particle_numbers, block->block_contents + offset,
4561 mapping->n_particles * sizeof(int64_t));
4565 return(TNG_SUCCESS);
4568 /** Write the atom mappings of the current trajectory frame set
4569 * @param tng_data is a trajectory data container.
4570 * @param block is a general block container.
4571 * @param mapping_block_nr is the index of the mapping block to write.
4572 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4573 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4574 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4575 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4577 static tng_function_status tng_trajectory_mapping_block_write
4578 (tng_trajectory_t tng_data,
4579 tng_gen_block_t block,
4580 int mapping_block_nr,
4581 const char hash_mode)
4585 unsigned int name_len;
4586 tng_particle_mapping_t mapping =
4587 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
4589 if(mapping_block_nr >=
4590 tng_data->current_trajectory_frame_set.n_mapping_blocks)
4592 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
4593 __FILE__, __LINE__);
4594 return(TNG_FAILURE);
4597 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4599 return(TNG_CRITICAL);
4602 name_len = (int)strlen("PARTICLE MAPPING");
4604 if(!block->name || strlen(block->name) < name_len)
4606 temp_name = realloc(block->name, name_len + 1);
4609 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4610 name_len+1, __FILE__, __LINE__);
4613 return(TNG_CRITICAL);
4615 block->name = temp_name;
4617 strcpy(block->name, "PARTICLE MAPPING");
4618 block->id = TNG_PARTICLE_MAPPING;
4620 if(tng_trajectory_mapping_block_len_calculate(tng_data,
4621 mapping->n_particles,
4622 &block->block_contents_size) !=
4625 fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4626 __FILE__, __LINE__);
4627 return(TNG_CRITICAL);
4630 if(block->block_contents)
4632 free(block->block_contents);
4634 block->block_contents = malloc(block->block_contents_size);
4635 if(!block->block_contents)
4637 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4638 block->block_contents_size, __FILE__, __LINE__);
4639 return(TNG_CRITICAL);
4642 memcpy(block->block_contents, &mapping->num_first_particle,
4643 sizeof(mapping->num_first_particle));
4644 if(tng_data->output_endianness_swap_func_64)
4646 if(tng_data->output_endianness_swap_func_64(tng_data,
4647 (int64_t *)block->header_contents+offset)
4650 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4651 __FILE__, __LINE__);
4654 offset += sizeof(mapping->num_first_particle);
4656 memcpy(block->block_contents+offset, &mapping->n_particles,
4657 sizeof(mapping->n_particles));
4658 if(tng_data->output_endianness_swap_func_64)
4660 if(tng_data->output_endianness_swap_func_64(tng_data,
4661 (int64_t *)block->header_contents+offset)
4664 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4665 __FILE__, __LINE__);
4668 offset += sizeof(mapping->n_particles);
4670 if(tng_data->output_endianness_swap_func_64)
4672 for(i = 0; i < mapping->n_particles; i++)
4674 memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
4676 if(tng_data->output_endianness_swap_func_64(tng_data,
4677 (int64_t *)block->header_contents+offset)
4680 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4681 __FILE__, __LINE__);
4683 offset += sizeof(int64_t);
4688 memcpy(block->block_contents+offset, mapping->real_particle_numbers,
4689 mapping->n_particles * sizeof(int64_t));
4693 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4695 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4696 tng_data->output_file_path, __FILE__, __LINE__);
4697 return(TNG_CRITICAL);
4700 if(fwrite(block->block_contents, block->block_contents_size, 1,
4701 tng_data->output_file) != 1)
4703 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4704 return(TNG_CRITICAL);
4707 return(TNG_SUCCESS);
4710 /** Prepare a block for storing particle data
4711 * @param tng_data is a trajectory data container.
4712 * @param block_type_flag specifies if this is a trajectory block or a
4713 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4714 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4715 * error has occured.
4717 static tng_function_status tng_particle_data_block_create
4718 (tng_trajectory_t tng_data,
4719 const char block_type_flag)
4721 tng_trajectory_frame_set_t frame_set =
4722 &tng_data->current_trajectory_frame_set;
4724 tng_particle_data_t data;
4726 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4728 frame_set->n_particle_data_blocks++;
4729 data = realloc(frame_set->tr_particle_data,
4730 sizeof(struct tng_particle_data) *
4731 frame_set->n_particle_data_blocks);
4734 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4735 sizeof(struct tng_particle_data) *
4736 frame_set->n_particle_data_blocks,
4737 __FILE__, __LINE__);
4738 free(frame_set->tr_particle_data);
4739 frame_set->tr_particle_data = 0;
4740 return(TNG_CRITICAL);
4742 frame_set->tr_particle_data = data;
4746 tng_data->n_particle_data_blocks++;
4747 data = realloc(tng_data->non_tr_particle_data,
4748 sizeof(struct tng_particle_data) *
4749 tng_data->n_particle_data_blocks);
4752 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4753 sizeof(struct tng_particle_data) *
4754 tng_data->n_particle_data_blocks,
4755 __FILE__, __LINE__);
4756 free(tng_data->non_tr_particle_data);
4757 tng_data->non_tr_particle_data = 0;
4758 return(TNG_CRITICAL);
4760 tng_data->non_tr_particle_data = data;
4763 return(TNG_SUCCESS);
4766 static tng_function_status tng_compress(tng_trajectory_t tng_data,
4767 tng_gen_block_t block,
4768 const int64_t n_frames,
4769 const int64_t n_particles,
4776 char *dest, *temp, *temp_data_contents;
4777 int64_t algo_find_n_frames, compressed_len, offset;
4781 if(block->id != TNG_TRAJ_POSITIONS &&
4782 block->id != TNG_TRAJ_VELOCITIES)
4784 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
4785 "TNG method. %s: %d\n", __FILE__, __LINE__);
4786 return(TNG_FAILURE);
4788 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4790 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
4791 return(TNG_FAILURE);
4794 if(n_frames <= 0 || n_particles <= 0)
4796 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
4797 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
4798 return(TNG_FAILURE);
4801 f_precision = 1/(float)tng_data->compression_precision;
4802 d_precision = 1/tng_data->compression_precision;
4804 compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
4805 temp_data_contents = malloc(compressed_len);
4806 if(!temp_data_contents)
4808 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4809 compressed_len, __FILE__, __LINE__);
4810 return(TNG_CRITICAL);
4813 memcpy(temp_data_contents, (char *)start_pos, compressed_len);
4815 if(block->id == TNG_TRAJ_POSITIONS)
4817 /* If there is only one frame in this frame set and there might be more
4818 * do not store the algorithm as the compression algorithm, but find
4819 * the best one without storing it */
4820 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4822 nalgo = tng_compress_nalgo();
4823 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4824 if(type == TNG_FLOAT_DATA)
4826 dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
4835 dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
4842 else if(!tng_data->compress_algo_pos)
4846 algo_find_n_frames = 5;
4850 algo_find_n_frames = n_frames;
4853 nalgo = tng_compress_nalgo();
4854 tng_data->compress_algo_pos=malloc(nalgo *
4855 sizeof *tng_data->compress_algo_pos);
4856 if(type == TNG_FLOAT_DATA)
4858 dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
4859 (int)algo_find_n_frames,
4865 if(algo_find_n_frames < n_frames)
4867 dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
4870 0, tng_data->compress_algo_pos,
4876 dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
4877 (int)algo_find_n_frames,
4883 if(algo_find_n_frames < n_frames)
4885 dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
4888 tng_data->compress_algo_pos,
4895 if(type == TNG_FLOAT_DATA)
4897 dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
4900 tng_data->compress_algo_pos, &new_len);
4904 dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
4907 tng_data->compress_algo_pos,
4912 else if(block->id == TNG_TRAJ_VELOCITIES)
4914 /* If there is only one frame in this frame set and there might be more
4915 * do not store the algorithm as the compression algorithm, but find
4916 * the best one without storing it */
4917 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4919 nalgo = tng_compress_nalgo();
4920 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4921 if(type == TNG_FLOAT_DATA)
4923 dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
4932 dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
4939 else if(!tng_data->compress_algo_vel)
4943 algo_find_n_frames = 5;
4947 algo_find_n_frames = n_frames;
4950 nalgo = tng_compress_nalgo();
4951 tng_data->compress_algo_vel=malloc(nalgo *
4952 sizeof *tng_data->compress_algo_vel);
4954 if(type == TNG_FLOAT_DATA)
4956 dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
4957 (int)algo_find_n_frames,
4962 if(algo_find_n_frames < n_frames)
4964 dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
4967 0, tng_data->compress_algo_vel,
4973 dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
4974 (int)algo_find_n_frames,
4979 if(algo_find_n_frames < n_frames)
4981 dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
4984 0, tng_data->compress_algo_vel,
4991 if(type == TNG_FLOAT_DATA)
4993 dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
5002 dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
5013 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
5014 free(temp_data_contents);
5015 return(TNG_FAILURE);
5018 offset = (unsigned long)((char *)start_pos - block->block_contents);
5025 block->block_contents_size = new_len + offset;
5027 free(temp_data_contents);
5029 temp = realloc(block->block_contents, block->block_contents_size);
5032 free(block->block_contents);
5033 block->block_contents = 0;
5034 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5035 block->block_contents_size, __FILE__, __LINE__);
5036 return(TNG_CRITICAL);
5038 block->block_contents = temp;
5041 memcpy(temp + offset, dest, new_len);
5046 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
5047 return(TNG_FAILURE);
5050 return(TNG_SUCCESS);
5053 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
5054 tng_gen_block_t block,
5057 const int64_t uncompressed_len)
5059 char *temp, *temp_data_contents;
5066 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
5068 if(block->id != TNG_TRAJ_POSITIONS &&
5069 block->id != TNG_TRAJ_VELOCITIES)
5071 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
5073 return(TNG_FAILURE);
5075 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
5077 fprintf(stderr, "TNG library: Data type not supported.\n");
5078 return(TNG_FAILURE);
5081 temp_data_contents = malloc(uncompressed_len);
5082 if(!temp_data_contents)
5084 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5085 uncompressed_len, __FILE__, __LINE__);
5086 return(TNG_CRITICAL);
5089 memcpy(temp_data_contents, (char *)start_pos, uncompressed_len);
5091 if(type == TNG_FLOAT_DATA)
5093 f_dest = malloc(uncompressed_len);
5096 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5097 uncompressed_len, __FILE__, __LINE__);
5098 free(temp_data_contents);
5099 return(TNG_CRITICAL);
5101 result = tng_compress_uncompress_float(temp_data_contents, f_dest);
5105 d_dest = malloc(uncompressed_len);
5108 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5109 uncompressed_len, __FILE__, __LINE__);
5110 free(temp_data_contents);
5111 return(TNG_CRITICAL);
5113 result = tng_compress_uncompress(temp_data_contents, d_dest);
5118 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
5119 free(temp_data_contents);
5120 return(TNG_FAILURE);
5123 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
5125 block->block_contents_size = (int64_t)(uncompressed_len + offset);
5127 temp = realloc(block->block_contents, uncompressed_len + offset);
5130 free(block->block_contents);
5131 block->block_contents = 0;
5140 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5141 block->block_contents_size, __FILE__, __LINE__);
5142 free(temp_data_contents);
5143 return(TNG_CRITICAL);
5146 if(type == TNG_FLOAT_DATA)
5148 memcpy(temp + offset, f_dest, uncompressed_len);
5152 memcpy(temp + offset, d_dest, uncompressed_len);
5155 block->block_contents = temp;
5157 free(temp_data_contents);
5166 return(TNG_SUCCESS);
5170 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
5171 tng_gen_block_t block,
5172 void *start_pos, const int len)
5176 unsigned long max_len, stat, offset;
5179 max_len = compressBound(len);
5180 dest = malloc(max_len);
5183 fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
5184 max_len, __FILE__, __LINE__);
5185 return(TNG_CRITICAL);
5188 stat = compress(dest, &max_len, start_pos, len);
5189 if(stat != (unsigned long)Z_OK)
5192 if(stat == (unsigned long)Z_MEM_ERROR)
5194 fprintf(stderr, "TNG library: Not enough memory. ");
5196 else if(stat == (unsigned long)Z_BUF_ERROR)
5198 fprintf(stderr, "TNG library: Destination buffer too small. ");
5200 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
5201 return(TNG_FAILURE);
5204 offset = (char *)start_pos - block->block_contents;
5206 block->block_contents_size = max_len + offset;
5208 temp = realloc(block->block_contents, block->block_contents_size);
5211 free(block->block_contents);
5213 block->block_contents = 0;
5214 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5215 block->block_contents_size, __FILE__, __LINE__);
5216 return(TNG_CRITICAL);
5219 block->block_contents = temp;
5221 memcpy(temp + offset, dest, max_len);
5225 return(TNG_SUCCESS);
5228 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5229 tng_gen_block_t block,
5231 unsigned long uncompressed_len)
5239 offset = (char *)start_pos - (char *)block->block_contents;
5241 dest = malloc(uncompressed_len);
5244 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5245 uncompressed_len, __FILE__, __LINE__);
5246 return(TNG_CRITICAL);
5249 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
5250 block->block_contents_size - offset);
5255 if(stat == (unsigned long)Z_MEM_ERROR)
5257 fprintf(stderr, "TNG library: Not enough memory. ");
5259 else if(stat == (unsigned long)Z_BUF_ERROR)
5261 fprintf(stderr, "TNG library: Destination buffer too small. ");
5263 else if(stat == (unsigned long)Z_DATA_ERROR)
5265 fprintf(stderr, "TNG library: Data corrupt. ");
5267 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
5269 return(TNG_FAILURE);
5273 block->block_contents_size = uncompressed_len + offset;
5275 temp = realloc(block->block_contents, uncompressed_len + offset);
5278 free(block->block_contents);
5279 block->block_contents = 0;
5281 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5282 block->block_contents_size, __FILE__, __LINE__);
5283 return(TNG_CRITICAL);
5286 memcpy(temp + offset, dest, uncompressed_len);
5288 block->block_contents = temp;
5291 return(TNG_SUCCESS);
5295 /** Allocate memory for storing particle data.
5296 * The allocated block will be refered to by data->values.
5297 * @param tng_data is a trajectory data container.
5298 * @param data is the data struct, which will contain the allocated memory in
5300 * @param n_frames is the number of frames of data to store.
5301 * @param n_particles is the number of particles with data.
5302 * @param n_values_per_frame is the number of data values per particle and
5304 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5305 * error has occured.
5307 static tng_function_status tng_allocate_particle_data_mem
5308 (tng_trajectory_t tng_data,
5309 tng_particle_data_t data,
5311 int64_t stride_length,
5312 const int64_t n_particles,
5313 const int64_t n_values_per_frame)
5316 int64_t i, j, k, size, frame_alloc;
5319 if(n_particles == 0 || n_values_per_frame == 0)
5321 return(TNG_FAILURE);
5324 if(data->strings && data->datatype == TNG_CHAR_DATA)
5326 for(i = 0; i < data->n_frames; i++)
5328 for(j = 0; j < n_particles; j++)
5330 for(k = 0; k < data->n_values_per_frame; k++)
5332 if(data->strings[i][j][k])
5334 free(data->strings[i][j][k]);
5337 free(data->strings[i][j]);
5339 free(data->strings[i]);
5341 free(data->strings);
5343 data->n_frames = n_frames;
5344 n_frames = tng_max_i64(1, n_frames);
5345 data->stride_length = tng_max_i64(1, stride_length);
5346 data->n_values_per_frame = n_values_per_frame;
5347 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5349 if(data->datatype == TNG_CHAR_DATA)
5351 data->strings = malloc(sizeof(char ***) * frame_alloc);
5352 for(i = 0; i < frame_alloc; i++)
5354 data->strings[i] = malloc(sizeof(char **) *
5356 if(!data->strings[i])
5358 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5359 sizeof(union data_values *) * n_particles,
5360 __FILE__, __LINE__);
5361 return(TNG_CRITICAL);
5363 for(j = 0; j < n_particles; j++)
5365 data->strings[i][j] = malloc(sizeof(char *) *
5366 n_values_per_frame);
5367 if(!data->strings[i][j])
5369 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5370 sizeof(union data_values) * n_values_per_frame,
5371 __FILE__, __LINE__);
5372 return(TNG_CRITICAL);
5374 for(k = 0; k < n_values_per_frame; k++)
5376 data->strings[i][j][k] = 0;
5383 switch(data->datatype)
5386 size = sizeof(int64_t);
5388 case TNG_FLOAT_DATA:
5389 size = sizeof(float);
5391 case TNG_DOUBLE_DATA:
5393 size = sizeof(double);
5396 values = realloc(data->values,
5397 size * frame_alloc *
5398 n_particles * n_values_per_frame);
5401 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5402 size * frame_alloc *
5403 n_particles * n_values_per_frame,
5404 __FILE__, __LINE__);
5407 return(TNG_CRITICAL);
5409 data->values = values;
5411 return(TNG_SUCCESS);
5414 static tng_function_status tng_particle_data_find
5415 (tng_trajectory_t tng_data,
5417 tng_particle_data_t *data)
5419 int64_t block_index, i;
5420 tng_trajectory_frame_set_t frame_set = &tng_data->
5421 current_trajectory_frame_set;
5422 char block_type_flag;
5424 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5425 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5427 block_type_flag = TNG_TRAJECTORY_BLOCK;
5431 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5435 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5437 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
5439 *data = &frame_set->tr_particle_data[i];
5440 if((*data)->block_id == id)
5449 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
5451 *data = &tng_data->non_tr_particle_data[i];
5452 if((*data)->block_id == id)
5459 if(block_index == -1)
5461 return(TNG_FAILURE);
5463 return(TNG_SUCCESS);
5466 static tng_function_status tng_data_find
5467 (tng_trajectory_t tng_data,
5469 tng_non_particle_data_t *data)
5471 int64_t block_index, i;
5472 tng_trajectory_frame_set_t frame_set = &tng_data->
5473 current_trajectory_frame_set;
5474 char block_type_flag;
5476 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5477 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5479 block_type_flag = TNG_TRAJECTORY_BLOCK;
5483 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5487 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5489 for(i = 0; i < frame_set->n_data_blocks; i++)
5491 *data = &frame_set->tr_data[i];
5492 if((*data)->block_id == id)
5498 if(block_index == -1)
5500 for(i = 0; i < tng_data->n_data_blocks; i++)
5502 *data = &tng_data->non_tr_data[i];
5503 if((*data)->block_id == id)
5513 for(i = 0; i < tng_data->n_data_blocks; i++)
5515 *data = &tng_data->non_tr_data[i];
5516 if((*data)->block_id == id)
5523 if(block_index == -1)
5525 return(TNG_FAILURE);
5527 return(TNG_SUCCESS);
5530 static tng_function_status tng_data_block_len_calculate
5531 (const tng_trajectory_t tng_data,
5532 const tng_particle_data_t data,
5533 const tng_bool is_particle_data,
5534 const int64_t n_frames,
5535 const int64_t frame_step,
5536 const int64_t stride_length,
5537 const int64_t num_first_particle,
5538 const int64_t n_particles,
5539 const char dependency,
5540 int64_t *data_start_pos,
5545 char ***first_dim_values, **second_dim_values;
5550 return(TNG_SUCCESS);
5553 switch(data->datatype)
5559 size = sizeof(int64_t);
5561 case TNG_FLOAT_DATA:
5562 size = sizeof(float);
5564 case TNG_DOUBLE_DATA:
5566 size = sizeof(double);
5569 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5570 sizeof(data->codec_id);
5571 if(is_particle_data)
5573 *len += sizeof(num_first_particle) + sizeof(n_particles);
5576 if(stride_length > 1)
5578 *len += sizeof(data->first_frame_with_data) +
5579 sizeof(data->stride_length);
5582 if(data->codec_id != TNG_UNCOMPRESSED)
5584 *len += sizeof(data->compression_multiplier);
5587 if(dependency & TNG_FRAME_DEPENDENT)
5589 *len += sizeof(char);
5592 *data_start_pos = *len;
5594 if(data->datatype == TNG_CHAR_DATA)
5596 if(is_particle_data)
5598 for(i = 0; i < n_frames; i++)
5600 first_dim_values = data->strings[i];
5601 for(j = num_first_particle; j < num_first_particle + n_particles;
5604 second_dim_values = first_dim_values[j];
5605 for(k = 0; k < data->n_values_per_frame; k++)
5607 *len += strlen(second_dim_values[k]) + 1;
5614 for(i = 0; i < n_frames; i++)
5616 second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
5617 for(j = 0; j < data->n_values_per_frame; j++)
5619 *len += strlen(second_dim_values[j]) + 1;
5626 *len += size * frame_step * n_particles * data->n_values_per_frame;
5629 return(TNG_SUCCESS);
5632 /** Read the values of a particle data block
5633 * @param tng_data is a trajectory data container.
5634 * @param block is the block to store the data (should already contain
5635 * the block headers and the block contents).
5636 * @param offset is the reading offset to point at the place where the actual
5637 * values are stored, starting from the beginning of the block_contents. The
5638 * offset is changed during the reading.
5639 * @param datatype is the type of data of the data block (char, int, float or
5641 * @param num_first_particle is the number of the first particle in the data
5642 * block. This should be the same as in the corresponding particle mapping
5644 * @param n_particles is the number of particles in the data block. This should
5645 * be the same as in the corresponding particle mapping block.
5646 * @param first_frame_with_data is the frame number of the first frame with data
5647 * in this data block.
5648 * @param stride_length is the number of frames between each data entry.
5649 * @param n_frames is the number of frames in this data block.
5650 * @param n_values is the number of values per particle and frame stored in this
5652 * @param codec_id is the ID of the codec to compress the data.
5653 * @param multiplier is the multiplication factor applied to each data value
5654 * before compression. This factor is applied since some compression algorithms
5655 * work only on integers.
5656 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5657 * error has occured.
5659 static tng_function_status tng_particle_data_read
5660 (tng_trajectory_t tng_data,
5661 tng_gen_block_t block,
5663 const char datatype,
5664 const int64_t num_first_particle,
5665 const int64_t n_particles,
5666 const int64_t first_frame_with_data,
5667 const int64_t stride_length,
5669 const int64_t n_values,
5670 const int64_t codec_id,
5671 const double multiplier)
5673 int64_t i, j, k, tot_n_particles, n_frames_div;
5676 char ***first_dim_values, **second_dim_values;
5677 tng_particle_data_t data;
5678 tng_trajectory_frame_set_t frame_set =
5679 &tng_data->current_trajectory_frame_set;
5680 char block_type_flag;
5682 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5690 size = sizeof(int64_t);
5692 case TNG_FLOAT_DATA:
5693 size = sizeof(float);
5695 case TNG_DOUBLE_DATA:
5697 size = sizeof(double);
5700 /* If the block does not exist, create it */
5701 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5703 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5705 block_type_flag = TNG_TRAJECTORY_BLOCK;
5709 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5712 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5715 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5716 __FILE__, __LINE__);
5717 return(TNG_CRITICAL);
5719 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5721 data = &frame_set->tr_particle_data[frame_set->
5722 n_particle_data_blocks - 1];
5726 data = &tng_data->non_tr_particle_data[tng_data->
5727 n_particle_data_blocks - 1];
5729 data->block_id = block->id;
5731 data->block_name = malloc(strlen(block->name) + 1);
5732 if(!data->block_name)
5734 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5735 (int)strlen(block->name)+1, __FILE__, __LINE__);
5736 return(TNG_CRITICAL);
5738 strcpy(data->block_name, block->name);
5740 data->datatype = datatype;
5743 /* FIXME: Memory leak from strings. */
5746 data->codec_id = codec_id;
5747 data->compression_multiplier = multiplier;
5748 data->last_retrieved_frame = -1;
5751 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5752 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5753 tng_data->var_num_atoms_flag)
5755 tot_n_particles = frame_set->n_particles;
5759 tot_n_particles = tng_data->n_particles;
5762 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5764 if(codec_id != TNG_UNCOMPRESSED)
5766 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5769 case TNG_XTC_COMPRESSION:
5770 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5772 case TNG_TNG_COMPRESSION:
5773 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5774 if(tng_uncompress(tng_data, block, datatype,
5775 block->block_contents + *offset,
5776 data_size) != TNG_SUCCESS)
5778 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5779 __FILE__, __LINE__);
5780 return(TNG_CRITICAL);
5782 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5785 case TNG_GZIP_COMPRESSION:
5786 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5787 if(tng_gzip_uncompress(tng_data, block,
5788 block->block_contents + *offset,
5789 data_size) != TNG_SUCCESS)
5791 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5793 return(TNG_CRITICAL);
5795 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5800 /* Allocate memory */
5801 if(!data->values || data->n_frames != n_frames ||
5802 data->n_values_per_frame != n_values)
5804 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5806 tot_n_particles, n_values) !=
5809 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5810 __FILE__, __LINE__);
5811 return(TNG_CRITICAL);
5815 data->first_frame_with_data = first_frame_with_data;
5817 if(datatype == TNG_CHAR_DATA)
5819 for(i = 0; i < n_frames_div; i++)
5821 first_dim_values = data->strings[i];
5822 for(j = num_first_particle; j < num_first_particle + n_particles;
5825 second_dim_values = first_dim_values[j];
5826 for(k = 0; k < n_values; k++)
5828 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5830 if(second_dim_values[k])
5832 free(second_dim_values[k]);
5834 second_dim_values[k] = malloc(len);
5835 if(!second_dim_values[k])
5837 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5838 len, __FILE__, __LINE__);
5839 return(TNG_CRITICAL);
5841 strncpy(second_dim_values[k],
5842 block->block_contents+*offset, len);
5850 memcpy((char *)data->values + n_frames_div * size * n_values *
5852 block->block_contents + *offset,
5853 block->block_contents_size - *offset);
5856 case TNG_FLOAT_DATA:
5857 if(tng_data->input_endianness_swap_func_32)
5859 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5861 if(tng_data->input_endianness_swap_func_32(tng_data,
5862 (int32_t *)((char *)data->values + i))
5865 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5866 __FILE__, __LINE__);
5872 case TNG_DOUBLE_DATA:
5873 if(tng_data->input_endianness_swap_func_64)
5875 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5877 if(tng_data->input_endianness_swap_func_64(tng_data,
5878 (int64_t *)((char *)data->values + i))
5881 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5882 __FILE__, __LINE__);
5891 return(TNG_SUCCESS);
5894 /** Write a particle data block
5895 * @param tng_data is a trajectory data container.
5896 * @param block is the block to store the data (should already contain
5897 * the block headers and the block contents).
5898 * @param block_index is the index number of the data block in the frame set.
5899 * @param mapping is the particle mapping that is relevant for the data block.
5900 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5901 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5902 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5903 * error has occured.
5905 static tng_function_status tng_particle_data_block_write
5906 (tng_trajectory_t tng_data,
5907 tng_gen_block_t block,
5908 const int64_t block_index,
5909 const tng_particle_mapping_t mapping,
5910 const char hash_mode)
5912 int64_t n_particles, num_first_particle, n_frames, stride_length;
5913 int64_t frame_step, data_start_pos;
5916 size_t len, offset = 0;
5917 char dependency, temp, *temp_name;
5919 char ***first_dim_values, **second_dim_values;
5920 tng_trajectory_frame_set_t frame_set;
5921 tng_function_status stat;
5923 tng_particle_data_t data;
5924 char block_type_flag;
5926 frame_set = &tng_data->current_trajectory_frame_set;
5928 /* If we have already started writing frame sets it is too late to write
5929 * non-trajectory data blocks */
5930 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5932 block_type_flag = TNG_TRAJECTORY_BLOCK;
5936 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5939 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5941 return(TNG_CRITICAL);
5944 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5946 data = &frame_set->tr_particle_data[block_index];
5948 /* If this data block has not had any data added in this frame set
5949 * do not write it. */
5950 if(data->first_frame_with_data < frame_set->first_frame)
5952 return(TNG_SUCCESS);
5955 stride_length = tng_max_i64(1, data->stride_length);
5959 data = &tng_data->non_tr_particle_data[block_index];
5963 switch(data->datatype)
5969 size = sizeof(int64_t);
5971 case TNG_FLOAT_DATA:
5972 size = sizeof(float);
5974 case TNG_DOUBLE_DATA:
5976 size = sizeof(double);
5979 len = strlen(data->block_name) + 1;
5981 if(!block->name || strlen(block->name) < len)
5983 temp_name = realloc(block->name, len);
5986 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5987 __FILE__, __LINE__);
5990 return(TNG_CRITICAL);
5992 block->name = temp_name;
5994 strncpy(block->name, data->block_name, len);
5995 block->id = data->block_id;
5997 /* If writing frame independent data data->n_frames is 0, but n_frames
5998 is used for the loop writing the data (and reserving memory) and needs
6000 n_frames = tng_max_i64(1, data->n_frames);
6002 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6004 /* If the frame set is finished before writing the full number of frames
6005 make sure the data block is not longer than the frame set. */
6006 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6008 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6011 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6012 n_frames / stride_length;
6014 /* TNG compression will use compression precision to get integers from
6015 * floating point data. The compression multiplier stores that information
6016 * to be able to return the precision of the compressed data. */
6017 if(data->codec_id == TNG_TNG_COMPRESSION)
6019 data->compression_multiplier = tng_data->compression_precision;
6021 /* Uncompressed data blocks do not use compression multipliers at all.
6022 * GZip compression does not need it either. */
6023 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6025 data->compression_multiplier = 1.0;
6028 if(mapping && mapping->n_particles != 0)
6030 n_particles = mapping->n_particles;
6031 num_first_particle = mapping->num_first_particle;
6035 num_first_particle = 0;
6036 if(tng_data->var_num_atoms_flag)
6038 n_particles = frame_set->n_particles;
6042 n_particles = tng_data->n_particles;
6046 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6048 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6052 dependency = TNG_PARTICLE_DEPENDENT;
6055 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6056 frame_step, stride_length, num_first_particle,
6057 n_particles, dependency, &data_start_pos,
6058 &block->block_contents_size) != TNG_SUCCESS)
6060 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6061 __FILE__, __LINE__);
6062 return(TNG_CRITICAL);
6065 if(block->block_contents)
6067 free(block->block_contents);
6069 block->block_contents = malloc(block->block_contents_size);
6070 if(!block->block_contents)
6072 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6073 block->block_contents_size, __FILE__, __LINE__);
6074 return(TNG_CRITICAL);
6078 memcpy(block->block_contents, &data->datatype, sizeof(char));
6079 offset += sizeof(char);
6081 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6082 offset += sizeof(char);
6084 if(dependency & TNG_FRAME_DEPENDENT)
6086 if(stride_length > 1)
6094 memcpy(block->block_contents+offset, &temp, sizeof(char));
6095 offset += sizeof(char);
6098 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6099 sizeof(data->n_values_per_frame));
6100 if(tng_data->output_endianness_swap_func_64)
6102 if(tng_data->output_endianness_swap_func_64(tng_data,
6103 (int64_t *)block->header_contents+offset)
6106 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6107 __FILE__, __LINE__);
6110 offset += sizeof(data->n_values_per_frame);
6112 memcpy(block->block_contents+offset, &data->codec_id,
6113 sizeof(data->codec_id));
6114 if(tng_data->output_endianness_swap_func_64)
6116 if(tng_data->output_endianness_swap_func_64(tng_data,
6117 (int64_t *)block->header_contents+offset)
6120 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6121 __FILE__, __LINE__);
6124 offset += sizeof(data->codec_id);
6126 if(data->codec_id != TNG_UNCOMPRESSED)
6128 memcpy(block->block_contents+offset, &data->compression_multiplier,
6129 sizeof(data->compression_multiplier));
6130 if(tng_data->output_endianness_swap_func_64)
6132 if(tng_data->output_endianness_swap_func_64(tng_data,
6133 (int64_t *)block->header_contents+offset)
6136 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6137 __FILE__, __LINE__);
6140 offset += sizeof(data->compression_multiplier);
6143 if(data->n_frames > 0 && stride_length > 1)
6145 /* FIXME: first_frame_with_data is not reliably set */
6146 if(data->first_frame_with_data == 0)
6148 data->first_frame_with_data = frame_set->first_frame;
6150 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6151 sizeof(data->first_frame_with_data));
6152 if(tng_data->output_endianness_swap_func_64)
6154 if(tng_data->output_endianness_swap_func_64(tng_data,
6155 (int64_t *)block->header_contents+offset)
6158 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6159 __FILE__, __LINE__);
6162 offset += sizeof(data->first_frame_with_data);
6164 memcpy(block->block_contents+offset, &stride_length,
6165 sizeof(stride_length));
6166 if(tng_data->output_endianness_swap_func_64)
6168 if(tng_data->output_endianness_swap_func_64(tng_data,
6169 (int64_t *)block->header_contents+offset)
6172 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6173 __FILE__, __LINE__);
6176 offset += sizeof(stride_length);
6180 memcpy(block->block_contents+offset, &num_first_particle,
6181 sizeof(num_first_particle));
6182 if(tng_data->output_endianness_swap_func_64)
6184 if(tng_data->output_endianness_swap_func_64(tng_data,
6185 (int64_t *)block->header_contents+offset)
6188 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6189 __FILE__, __LINE__);
6192 offset += sizeof(num_first_particle);
6194 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
6195 if(tng_data->output_endianness_swap_func_64)
6197 if(tng_data->output_endianness_swap_func_64(tng_data,
6198 (int64_t *)block->header_contents+offset)
6201 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6202 __FILE__, __LINE__);
6205 offset += sizeof(n_particles);
6207 if(data->datatype == TNG_CHAR_DATA)
6211 for(i = 0; i < frame_step; i++)
6213 first_dim_values = data->strings[i];
6214 for(j = num_first_particle; j < num_first_particle + n_particles;
6217 second_dim_values = first_dim_values[j];
6218 for(k = 0; k < data->n_values_per_frame; k++)
6220 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6221 strncpy(block->block_contents+offset,
6222 second_dim_values[k], len);
6229 else if(data->values)
6231 memcpy(block->block_contents + offset, data->values,
6232 block->block_contents_size - offset);
6234 switch(data->datatype)
6236 case TNG_FLOAT_DATA:
6237 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6238 data->codec_id == TNG_TNG_COMPRESSION)
6240 if(tng_data->input_endianness_swap_func_32)
6242 for(i = offset; i < block->block_contents_size; i+=size)
6244 if(tng_data->input_endianness_swap_func_32(tng_data,
6245 (int32_t *)(block->block_contents + i))
6248 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6249 __FILE__, __LINE__);
6256 multiplier = data->compression_multiplier;
6257 if(fabs(multiplier - 1.0) > 0.00001 ||
6258 tng_data->input_endianness_swap_func_32)
6260 for(i = offset; i < block->block_contents_size; i+=size)
6262 *(float *)(block->block_contents + i) *= (float)multiplier;
6263 if(tng_data->input_endianness_swap_func_32 &&
6264 tng_data->input_endianness_swap_func_32(tng_data,
6265 (int32_t *)(block->block_contents + i))
6268 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6269 __FILE__, __LINE__);
6276 if(tng_data->input_endianness_swap_func_64)
6278 for(i = offset; i < block->block_contents_size; i+=size)
6280 if(tng_data->input_endianness_swap_func_64(tng_data,
6281 (int64_t *)(block->block_contents + i))
6284 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6285 __FILE__, __LINE__);
6290 case TNG_DOUBLE_DATA:
6291 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6292 data->codec_id == TNG_TNG_COMPRESSION)
6294 if(tng_data->input_endianness_swap_func_64)
6296 for(i = offset; i < block->block_contents_size; i+=size)
6298 if(tng_data->input_endianness_swap_func_64(tng_data,
6299 (int64_t *)(block->block_contents + i))
6302 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6303 __FILE__, __LINE__);
6310 multiplier = data->compression_multiplier;
6311 if(fabs(multiplier - 1.0) > 0.00001 ||
6312 tng_data->input_endianness_swap_func_64)
6314 for(i = offset; i < block->block_contents_size; i+=size)
6316 *(double *)(block->block_contents + i) *= multiplier;
6317 if(tng_data->input_endianness_swap_func_64 &&
6318 tng_data->input_endianness_swap_func_64(tng_data,
6319 (int64_t *)(block->block_contents + i))
6322 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6323 __FILE__, __LINE__);
6335 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6338 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6339 frame_set->n_unwritten_frames = 0;
6341 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6343 switch(data->codec_id)
6345 case TNG_XTC_COMPRESSION:
6346 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6347 data->codec_id = TNG_UNCOMPRESSED;
6349 case TNG_TNG_COMPRESSION:
6350 stat = tng_compress(tng_data, block, frame_step,
6351 n_particles, data->datatype,
6352 block->block_contents + data_start_pos);
6353 if(stat != TNG_SUCCESS)
6355 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6356 __FILE__, __LINE__);
6357 if(stat == TNG_CRITICAL)
6359 return(TNG_CRITICAL);
6361 /* Set the data again, but with no compression (to write only
6362 * the relevant data) */
6363 data->codec_id = TNG_UNCOMPRESSED;
6364 stat = tng_particle_data_block_write(tng_data, block,
6365 block_index, mapping,
6371 case TNG_GZIP_COMPRESSION:
6372 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6373 stat = tng_gzip_compress(tng_data, block,
6374 block->block_contents + data_start_pos,
6375 block->block_contents_size - data_start_pos);
6376 if(stat != TNG_SUCCESS)
6378 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6380 if(stat == TNG_CRITICAL)
6382 return(TNG_CRITICAL);
6384 /* Set the data again, but with no compression (to write only
6385 * the relevant data) */
6386 data->codec_id = TNG_UNCOMPRESSED;
6387 stat = tng_particle_data_block_write(tng_data, block,
6388 block_index, mapping,
6392 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6398 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6400 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6401 tng_data->output_file_path, __FILE__, __LINE__);
6402 return(TNG_CRITICAL);
6405 if(fwrite(block->block_contents, block->block_contents_size, 1,
6406 tng_data->output_file) != 1)
6408 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6410 return(TNG_CRITICAL);
6413 return(TNG_SUCCESS);
6417 /** Create a non-particle data block
6418 * @param tng_data is a trajectory data container.
6419 * @param block_type_flag specifies if this is a trajectory block or a
6420 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6421 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6422 * error has occured.
6424 static tng_function_status tng_data_block_create
6425 (tng_trajectory_t tng_data,
6426 const char block_type_flag)
6428 tng_trajectory_frame_set_t frame_set =
6429 &tng_data->current_trajectory_frame_set;
6431 tng_non_particle_data_t data;
6433 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6435 frame_set->n_data_blocks++;
6436 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6437 frame_set->n_data_blocks);
6440 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6441 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6442 __FILE__, __LINE__);
6443 free(frame_set->tr_data);
6444 frame_set->tr_data = 0;
6445 return(TNG_CRITICAL);
6447 frame_set->tr_data = data;
6451 tng_data->n_data_blocks++;
6452 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6453 tng_data->n_data_blocks);
6456 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6457 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6458 __FILE__, __LINE__);
6459 free(tng_data->non_tr_data);
6460 tng_data->non_tr_data = 0;
6461 return(TNG_CRITICAL);
6463 tng_data->non_tr_data = data;
6466 return(TNG_SUCCESS);
6470 /** Allocate memory for storing non-particle data.
6471 * The allocated block will be refered to by data->values.
6472 * @param tng_data is a trajectory data container.
6473 * @param data is the data struct, which will contain the allocated memory in
6475 * @param n_frames is the number of frames of data to store.
6476 * @param n_values_per_frame is the number of data values per frame.
6477 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6478 * error has occured.
6480 static tng_function_status tng_allocate_data_mem
6481 (tng_trajectory_t tng_data,
6482 tng_non_particle_data_t data,
6484 int64_t stride_length,
6485 const int64_t n_values_per_frame)
6488 int64_t i, j, size, frame_alloc;
6491 if(n_values_per_frame == 0)
6493 return(TNG_FAILURE);
6496 if(data->strings && data->datatype == TNG_CHAR_DATA)
6498 for(i = 0; i < data->n_frames; i++)
6500 for(j = 0; j < data->n_values_per_frame; j++)
6502 if(data->strings[i][j])
6504 free(data->strings[i][j]);
6505 data->strings[i][j] = 0;
6508 free(data->strings[i]);
6509 data->strings[i] = 0;
6511 free(data->strings);
6513 data->n_frames = n_frames;
6514 data->stride_length = tng_max_i64(1, stride_length);
6515 n_frames = tng_max_i64(1, n_frames);
6516 data->n_values_per_frame = n_values_per_frame;
6517 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6519 if(data->datatype == TNG_CHAR_DATA)
6521 data->strings = malloc(sizeof(char **) * frame_alloc);
6522 for(i = 0; i < frame_alloc; i++)
6524 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6525 if(!data->strings[i])
6527 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6529 __FILE__, __LINE__);
6530 return(TNG_CRITICAL);
6532 for(j = 0; j < n_values_per_frame; j++)
6534 data->strings[i][j] = 0;
6540 switch(data->datatype)
6543 size = sizeof(int64_t);
6545 case TNG_FLOAT_DATA:
6546 size = sizeof(float);
6548 case TNG_DOUBLE_DATA:
6550 size = sizeof(double);
6553 values = realloc(data->values,
6554 size * frame_alloc *
6555 n_values_per_frame);
6558 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6559 size * frame_alloc *
6561 __FILE__, __LINE__);
6564 return(TNG_CRITICAL);
6566 data->values = values;
6569 return(TNG_SUCCESS);
6572 /** Read the values of a non-particle data block
6573 * @param tng_data is a trajectory data container.
6574 * @param block is the block to store the data (should already contain
6575 * the block headers and the block contents).
6576 * @param offset is the reading offset to point at the place where the actual
6577 * values are stored, starting from the beginning of the block_contents. The
6578 * offset is changed during the reading.
6579 * @param datatype is the type of data of the data block (char, int, float or
6581 * @param first_frame_with_data is the frame number of the first frame with data
6582 * in this data block.
6583 * @param stride_length is the number of frames between each data entry.
6584 * @param n_frames is the number of frames in this data block.
6585 * @param n_values is the number of values per frame stored in this data block.
6586 * @param codec_id is the ID of the codec to compress the data.
6587 * @param multiplier is the multiplication factor applied to each data value
6588 * before compression. This factor is applied since some compression algorithms
6589 * work only on integers.
6590 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6591 * error has occured.
6593 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6594 tng_gen_block_t block,
6596 const char datatype,
6597 const int64_t first_frame_with_data,
6598 const int64_t stride_length,
6600 const int64_t n_values,
6601 const int64_t codec_id,
6602 const double multiplier)
6604 int64_t i, j, n_frames_div;
6609 tng_non_particle_data_t data;
6610 tng_trajectory_frame_set_t frame_set =
6611 &tng_data->current_trajectory_frame_set;
6612 char block_type_flag;
6614 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6616 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6624 size = sizeof(int64_t);
6626 case TNG_FLOAT_DATA:
6627 size = sizeof(float);
6629 case TNG_DOUBLE_DATA:
6631 size = sizeof(double);
6634 /* If the block does not exist, create it */
6635 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6637 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6639 block_type_flag = TNG_TRAJECTORY_BLOCK;
6643 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6646 if(tng_data_block_create(tng_data, block_type_flag) !=
6649 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6650 __FILE__, __LINE__);
6651 return(TNG_CRITICAL);
6653 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6655 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6659 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6661 data->block_id = block->id;
6663 data->block_name = malloc(strlen(block->name) + 1);
6664 if(!data->block_name)
6666 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6667 (int)strlen(block->name)+1, __FILE__, __LINE__);
6668 return(TNG_CRITICAL);
6670 strcpy(data->block_name, block->name);
6672 data->datatype = datatype;
6675 /* FIXME: Memory leak from strings. */
6678 data->codec_id = codec_id;
6679 data->compression_multiplier = multiplier;
6680 data->last_retrieved_frame = -1;
6683 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6685 if(codec_id != TNG_UNCOMPRESSED)
6690 case TNG_GZIP_COMPRESSION:
6691 data_size = n_frames_div * size * n_values;
6692 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6693 if(tng_gzip_uncompress(tng_data, block,
6694 block->block_contents + *offset,
6695 data_size) != TNG_SUCCESS)
6697 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6699 return(TNG_CRITICAL);
6701 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6707 /* Allocate memory */
6708 if(!data->values || data->n_frames != n_frames ||
6709 data->n_values_per_frame != n_values)
6711 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6715 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6716 __FILE__, __LINE__);
6717 return(TNG_CRITICAL);
6721 data->first_frame_with_data = first_frame_with_data;
6723 if(datatype == TNG_CHAR_DATA)
6725 for(i = 0; i < n_frames_div; i++)
6727 for(j = 0; j < n_values; j++)
6729 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6731 if(data->strings[i][j])
6733 free(data->strings[i][j]);
6735 data->strings[i][j] = malloc(len);
6736 if(!data->strings[i][j])
6738 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6739 len, __FILE__, __LINE__);
6740 return(TNG_CRITICAL);
6742 strncpy(data->strings[i][j], block->block_contents+*offset,
6750 memcpy(data->values, block->block_contents + *offset,
6751 block->block_contents_size - *offset);
6754 case TNG_FLOAT_DATA:
6755 if(tng_data->input_endianness_swap_func_32)
6757 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6759 if(tng_data->input_endianness_swap_func_32(tng_data,
6760 (int32_t *)((char *)data->values + i))
6763 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6764 __FILE__, __LINE__);
6770 case TNG_DOUBLE_DATA:
6771 if(tng_data->input_endianness_swap_func_64)
6773 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6775 if(tng_data->input_endianness_swap_func_64(tng_data,
6776 (int64_t *)((char *)data->values + i))
6779 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6780 __FILE__, __LINE__);
6789 return(TNG_SUCCESS);
6792 /** Write a non-particle data block
6793 * @param tng_data is a trajectory data container.
6794 * @param block is the block to store the data (should already contain
6795 * the block headers and the block contents).
6796 * @param block_index is the index number of the data block in the frame set.
6797 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6798 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6799 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6800 * error has occured.
6802 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6803 tng_gen_block_t block,
6804 const int64_t block_index,
6805 const char hash_mode)
6807 int64_t n_frames, stride_length, frame_step, data_start_pos;
6809 int offset = 0, size;
6812 tng_function_status stat;
6814 char temp, dependency, *temp_name;
6816 tng_trajectory_frame_set_t frame_set =
6817 &tng_data->current_trajectory_frame_set;
6819 tng_non_particle_data_t data;
6820 char block_type_flag;
6822 /* If we have already started writing frame sets it is too late to write
6823 * non-trajectory data blocks */
6824 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6826 block_type_flag = TNG_TRAJECTORY_BLOCK;
6830 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6833 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6835 return(TNG_CRITICAL);
6838 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6840 data = &frame_set->tr_data[block_index];
6842 /* If this data block has not had any data added in this frame set
6843 * do not write it. */
6844 if(data->first_frame_with_data < frame_set->first_frame)
6846 return(TNG_SUCCESS);
6849 stride_length = tng_max_i64(1, data->stride_length);
6853 data = &tng_data->non_tr_data[block_index];
6857 switch(data->datatype)
6863 size = sizeof(int64_t);
6865 case TNG_FLOAT_DATA:
6866 size = sizeof(float);
6868 case TNG_DOUBLE_DATA:
6870 size = sizeof(double);
6873 len = (unsigned int)strlen(data->block_name) + 1;
6875 if(!block->name || strlen(block->name) < len)
6877 temp_name = realloc(block->name, len);
6880 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6881 __FILE__, __LINE__);
6884 return(TNG_CRITICAL);
6886 block->name = temp_name;
6888 strncpy(block->name, data->block_name, len);
6889 block->id = data->block_id;
6891 /* If writing frame independent data data->n_frames is 0, but n_frames
6892 is used for the loop writing the data (and reserving memory) and needs
6894 n_frames = tng_max_i64(1, data->n_frames);
6896 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6898 /* If the frame set is finished before writing the full number of frames
6899 make sure the data block is not longer than the frame set. */
6900 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6902 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6905 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6906 n_frames / stride_length;
6908 /* TNG compression will use compression precision to get integers from
6909 * floating point data. The compression multiplier stores that information
6910 * to be able to return the precision of the compressed data. */
6911 if(data->codec_id == TNG_TNG_COMPRESSION)
6913 data->compression_multiplier = tng_data->compression_precision;
6915 /* Uncompressed data blocks do not use compression multipliers at all.
6916 * GZip compression does not need it either. */
6917 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6919 data->compression_multiplier = 1.0;
6922 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6924 dependency = TNG_FRAME_DEPENDENT;
6931 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6932 frame_step, stride_length, 0,
6933 1, dependency, &data_start_pos,
6934 &block->block_contents_size) != TNG_SUCCESS)
6936 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6937 __FILE__, __LINE__);
6938 return(TNG_CRITICAL);
6941 if(block->block_contents)
6943 free(block->block_contents);
6945 block->block_contents = malloc(block->block_contents_size);
6946 if(!block->block_contents)
6948 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6949 block->block_contents_size, __FILE__, __LINE__);
6950 return(TNG_CRITICAL);
6954 memcpy(block->block_contents, &data->datatype, sizeof(char));
6955 offset += sizeof(char);
6957 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6958 offset += sizeof(char);
6960 if(dependency & TNG_FRAME_DEPENDENT)
6962 if(stride_length > 1)
6970 memcpy(block->block_contents+offset, &temp, sizeof(char));
6971 offset += sizeof(char);
6974 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6975 sizeof(data->n_values_per_frame));
6976 if(tng_data->output_endianness_swap_func_64)
6978 if(tng_data->output_endianness_swap_func_64(tng_data,
6979 (int64_t *)block->header_contents+offset)
6982 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6983 __FILE__, __LINE__);
6986 offset += sizeof(data->n_values_per_frame);
6988 memcpy(block->block_contents+offset, &data->codec_id,
6989 sizeof(data->codec_id));
6990 if(tng_data->output_endianness_swap_func_64)
6992 if(tng_data->output_endianness_swap_func_64(tng_data,
6993 (int64_t *)block->header_contents+offset)
6996 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6997 __FILE__, __LINE__);
7000 offset += sizeof(data->codec_id);
7002 if(data->codec_id != TNG_UNCOMPRESSED)
7004 memcpy(block->block_contents+offset, &data->compression_multiplier,
7005 sizeof(data->compression_multiplier));
7006 if(tng_data->output_endianness_swap_func_64)
7008 if(tng_data->output_endianness_swap_func_64(tng_data,
7009 (int64_t *)block->header_contents+offset)
7012 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7013 __FILE__, __LINE__);
7016 offset += sizeof(data->compression_multiplier);
7019 if(data->n_frames > 0 && stride_length > 1)
7021 /* FIXME: first_frame_with_data is not reliably set */
7022 if(data->first_frame_with_data == 0)
7024 data->first_frame_with_data = frame_set->first_frame;
7026 memcpy(block->block_contents+offset, &data->first_frame_with_data,
7027 sizeof(data->first_frame_with_data));
7028 if(tng_data->output_endianness_swap_func_64)
7030 if(tng_data->output_endianness_swap_func_64(tng_data,
7031 (int64_t *)block->header_contents+offset)
7034 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7035 __FILE__, __LINE__);
7038 offset += sizeof(data->first_frame_with_data);
7040 memcpy(block->block_contents+offset, &stride_length,
7041 sizeof(data->stride_length));
7042 if(tng_data->output_endianness_swap_func_64)
7044 if(tng_data->output_endianness_swap_func_64(tng_data,
7045 (int64_t *)block->header_contents+offset)
7048 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7049 __FILE__, __LINE__);
7052 offset += sizeof(data->stride_length);
7055 if(data->datatype == TNG_CHAR_DATA)
7059 for(i = 0; i < frame_step; i++)
7061 for(j = 0; j < data->n_values_per_frame; j++)
7063 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7064 strncpy(block->block_contents+offset, data->strings[i][j],
7071 else if(data->values)
7073 memcpy(block->block_contents + offset, data->values,
7074 block->block_contents_size - offset);
7075 switch(data->datatype)
7077 case TNG_FLOAT_DATA:
7078 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7079 data->codec_id == TNG_TNG_COMPRESSION)
7081 if(tng_data->input_endianness_swap_func_32)
7083 for(i = offset; i < block->block_contents_size; i+=size)
7085 if(tng_data->input_endianness_swap_func_32(tng_data,
7086 (int32_t *)(block->block_contents + i))
7089 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7090 __FILE__, __LINE__);
7097 multiplier = data->compression_multiplier;
7098 if(fabs(multiplier - 1.0) > 0.00001 ||
7099 tng_data->input_endianness_swap_func_32)
7101 for(i = offset; block->block_contents_size; i+=size)
7103 *(float *)(block->block_contents + i) *= (float)multiplier;
7104 if(tng_data->input_endianness_swap_func_32 &&
7105 tng_data->input_endianness_swap_func_32(tng_data,
7106 (int32_t *)(block->block_contents + i))
7109 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7110 __FILE__, __LINE__);
7117 if(tng_data->input_endianness_swap_func_64)
7119 for(i = offset; i < block->block_contents_size; i+=size)
7121 if(tng_data->input_endianness_swap_func_64(tng_data,
7122 (int64_t *)(block->block_contents + i))
7125 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7126 __FILE__, __LINE__);
7131 case TNG_DOUBLE_DATA:
7132 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7133 data->codec_id == TNG_TNG_COMPRESSION)
7135 if(tng_data->input_endianness_swap_func_64)
7137 for(i = offset; i < block->block_contents_size; i+=size)
7139 if(tng_data->input_endianness_swap_func_64(tng_data,
7140 (int64_t *)(block->block_contents + i))
7143 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7144 __FILE__, __LINE__);
7151 multiplier = data->compression_multiplier;
7152 if(fabs(multiplier - 1.0) > 0.00001 ||
7153 tng_data->input_endianness_swap_func_64)
7155 for(i = offset; i < block->block_contents_size; i+=size)
7157 *(double *)(block->block_contents + i) *= multiplier;
7158 if(tng_data->input_endianness_swap_func_64 &&
7159 tng_data->input_endianness_swap_func_64(tng_data,
7160 (int64_t *)(block->block_contents + i))
7163 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7164 __FILE__, __LINE__);
7176 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7179 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7180 frame_set->n_unwritten_frames = 0;
7182 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7184 switch(data->codec_id)
7187 case TNG_GZIP_COMPRESSION:
7188 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7189 stat = tng_gzip_compress(tng_data, block,
7190 block->block_contents + data_start_pos,
7191 block->block_contents_size - data_start_pos);
7192 if(stat != TNG_SUCCESS)
7194 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7196 if(stat == TNG_CRITICAL)
7198 return(TNG_CRITICAL);
7200 data->codec_id = TNG_UNCOMPRESSED;
7202 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7208 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7210 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7211 tng_data->output_file_path, __FILE__, __LINE__);
7212 return(TNG_CRITICAL);
7215 if(fwrite(block->block_contents, block->block_contents_size, 1,
7216 tng_data->output_file) != 1)
7218 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7219 __FILE__, __LINE__);
7220 return(TNG_CRITICAL);
7223 return(TNG_SUCCESS);
7226 /** Read the meta information of a data block (particle or non-particle data).
7227 * @param tng_data is a trajectory data container.
7228 * @param block is the block to store the data (should already contain
7229 * the block headers).
7230 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7231 * error has occured.
7233 static tng_function_status tng_data_block_meta_information_read
7234 (tng_trajectory_t tng_data,
7235 tng_gen_block_t block,
7242 int64_t *first_frame_with_data,
7243 int64_t *stride_length,
7245 int64_t *num_first_particle,
7246 int64_t *block_n_particles,
7252 if(block->block_contents)
7254 contents = block->block_contents;
7258 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7259 contents = malloc(meta_size);
7262 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7263 meta_size, __FILE__, __LINE__);
7266 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7268 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7270 return(TNG_CRITICAL);
7274 memcpy(datatype, contents+*offset,
7276 *offset += sizeof(*datatype);
7278 memcpy(dependency, contents+*offset,
7279 sizeof(*dependency));
7280 *offset += sizeof(*dependency);
7282 if(*dependency & TNG_FRAME_DEPENDENT)
7284 memcpy(sparse_data, contents+*offset,
7285 sizeof(*sparse_data));
7286 *offset += sizeof(*sparse_data);
7289 memcpy(n_values, contents+*offset,
7291 if(tng_data->input_endianness_swap_func_64)
7293 if(tng_data->input_endianness_swap_func_64(tng_data,
7297 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7298 __FILE__, __LINE__);
7301 *offset += sizeof(*n_values);
7303 memcpy(codec_id, contents+*offset,
7305 if(tng_data->input_endianness_swap_func_64)
7307 if(tng_data->input_endianness_swap_func_64(tng_data,
7311 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7312 __FILE__, __LINE__);
7315 *offset += sizeof(*codec_id);
7317 if(*codec_id != TNG_UNCOMPRESSED)
7319 memcpy(multiplier, contents+*offset,
7320 sizeof(*multiplier));
7321 if(tng_data->input_endianness_swap_func_64)
7323 if(tng_data->input_endianness_swap_func_64(tng_data,
7324 (int64_t *) multiplier)
7327 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7328 __FILE__, __LINE__);
7331 *offset += sizeof(*multiplier);
7338 if(*dependency & TNG_FRAME_DEPENDENT)
7342 memcpy(first_frame_with_data, contents+*offset,
7343 sizeof(*first_frame_with_data));
7344 if(tng_data->input_endianness_swap_func_64)
7346 if(tng_data->input_endianness_swap_func_64(tng_data,
7347 first_frame_with_data)
7350 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7351 __FILE__, __LINE__);
7354 *offset += sizeof(*first_frame_with_data);
7356 memcpy(stride_length, contents+*offset,
7357 sizeof(*stride_length));
7358 if(tng_data->input_endianness_swap_func_64)
7360 if(tng_data->input_endianness_swap_func_64(tng_data,
7364 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7365 __FILE__, __LINE__);
7368 *offset += sizeof(*stride_length);
7369 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7370 (*first_frame_with_data -
7371 tng_data->current_trajectory_frame_set.first_frame);
7375 *first_frame_with_data = 0;
7377 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7382 *first_frame_with_data = 0;
7387 if (*dependency & TNG_PARTICLE_DEPENDENT)
7389 memcpy(num_first_particle, contents+*offset,
7390 sizeof(*num_first_particle));
7391 if(tng_data->input_endianness_swap_func_64)
7393 if(tng_data->input_endianness_swap_func_64(tng_data,
7397 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7398 __FILE__, __LINE__);
7401 *offset += sizeof(*num_first_particle);
7403 memcpy(block_n_particles, contents+*offset,
7404 sizeof(*block_n_particles));
7405 if(tng_data->input_endianness_swap_func_64)
7407 if(tng_data->input_endianness_swap_func_64(tng_data,
7411 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7412 __FILE__, __LINE__);
7415 *offset += sizeof(*block_n_particles);
7418 if(!block->block_contents)
7422 return(TNG_SUCCESS);
7425 /** Read the contents of a data block (particle or non-particle data).
7426 * @param tng_data is a trajectory data container.
7427 * @param block is the block to store the data (should already contain
7428 * the block headers).
7429 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7430 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7431 * compared to the md5 hash of the read contents to ensure valid data.
7432 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7433 * error has occured.
7435 static tng_function_status tng_data_block_contents_read
7436 (tng_trajectory_t tng_data,
7437 tng_gen_block_t block,
7438 const char hash_mode)
7440 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7441 int64_t stride_length, block_n_particles, num_first_particle;
7443 char datatype, dependency, sparse_data;
7447 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7449 return(TNG_CRITICAL);
7452 if(block->block_contents)
7454 free(block->block_contents);
7457 block->block_contents = malloc(block->block_contents_size);
7458 if(!block->block_contents)
7460 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7461 block->block_contents_size, __FILE__, __LINE__);
7462 return(TNG_CRITICAL);
7465 /* Read the whole block into block_contents to be able to write it to
7466 * disk even if it cannot be interpreted. */
7467 if(fread(block->block_contents, block->block_contents_size, 1,
7468 tng_data->input_file) == 0)
7470 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7471 return(TNG_CRITICAL);
7474 /* FIXME: Does not check if the size of the contents matches the expected
7475 * size or if the contents can be read. */
7477 if(hash_mode == TNG_USE_HASH)
7479 tng_md5_hash_match_verify(block, &same_hash);
7480 if(same_hash != TNG_TRUE)
7482 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7483 block->name, __FILE__, __LINE__);
7484 /* return(TNG_FAILURE); */
7488 if(tng_data_block_meta_information_read(tng_data, block,
7490 &dependency, &sparse_data,
7491 &n_values, &codec_id,
7492 &first_frame_with_data,
7493 &stride_length, &n_frames,
7494 &num_first_particle,
7496 &multiplier) == TNG_CRITICAL)
7498 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7499 block->name, __FILE__, __LINE__);
7500 return(TNG_CRITICAL);
7503 if (dependency & TNG_PARTICLE_DEPENDENT)
7505 return(tng_particle_data_read(tng_data, block,
7509 first_frame_with_data,
7512 codec_id, multiplier));
7516 return(tng_data_read(tng_data, block,
7518 first_frame_with_data,
7521 codec_id, multiplier));
7526 // ** Move the blocks in a frame set so that there is no unused space between
7527 // * them. This can only be done on the last frame set in the file and should
7528 // * be done e.g. if the last frame set in the file has fewer frames than
7529 // * default or after compressing data blocks in a frame set.
7530 // * @param tng_data is a trajectory data container.
7531 // * @details the current_trajectory_frame_set is the one that will be modified.
7532 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7533 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7534 // * FIXME: This function is not finished!!!
7536 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7538 // tng_gen_block_t block;
7539 // tng_trajectory_frame_set_t frame_set;
7540 // FILE *temp = tng_data->input_file;
7541 // int64_t pos, contents_start_pos, output_file_len;
7543 // frame_set = &tng_data->current_trajectory_frame_set;
7545 // if(frame_set->n_written_frames == frame_set->n_frames)
7547 // return(TNG_SUCCESS);
7550 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7551 // tng_data->last_trajectory_frame_set_output_file_pos)
7555 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7557 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7558 // __FILE__, __LINE__);
7559 // return(TNG_CRITICAL);
7562 // tng_block_init(&block);
7563 // // output_file_pos = ftello(tng_data->output_file);
7565 // tng_data->input_file = tng_data->output_file;
7567 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7569 // fseeko(tng_data->output_file, pos, SEEK_SET);
7570 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7572 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7573 // __FILE__, __LINE__);
7574 // tng_data->input_file = temp;
7575 // tng_block_destroy(&block);
7576 // return(TNG_CRITICAL);
7579 // contents_start_pos = ftello(tng_data->output_file);
7581 // fseeko(tng_data->output_file, 0, SEEK_END);
7582 // output_file_len = ftello(tng_data->output_file);
7583 // pos = contents_start_pos + block->block_contents_size;
7584 // fseeko(tng_data->output_file, pos,
7587 // while(pos < output_file_len)
7589 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7591 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7592 // __FILE__, __LINE__);
7593 // tng_data->input_file = temp;
7594 // tng_block_destroy(&block);
7595 // return(TNG_CRITICAL);
7597 // pos += block->header_contents_size + block->block_contents_size;
7598 // fseeko(tng_data->output_file, pos, SEEK_SET);
7601 // return(TNG_SUCCESS);
7604 /** Finish writing the current frame set. Update the number of frames
7605 * and the hashes of the frame set and all its data blocks (if hash_mode
7607 * @param tng_data is a trajectory data container.
7608 * @param hash_mode specifies whether to update the block md5 hash when
7609 * updating the pointers.
7610 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7611 * error has occured.
7613 static tng_function_status tng_frame_set_finalize
7614 (tng_trajectory_t tng_data, const char hash_mode)
7616 tng_gen_block_t block;
7617 tng_trajectory_frame_set_t frame_set;
7618 FILE *temp = tng_data->input_file;
7619 int64_t pos, contents_start_pos, output_file_len;
7621 frame_set = &tng_data->current_trajectory_frame_set;
7623 if(frame_set->n_written_frames == frame_set->n_frames)
7625 return(TNG_SUCCESS);
7628 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7630 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7631 __FILE__, __LINE__);
7632 return(TNG_CRITICAL);
7635 tng_block_init(&block);
7636 /* output_file_pos = ftello(tng_data->output_file); */
7638 tng_data->input_file = tng_data->output_file;
7640 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7642 fseeko(tng_data->output_file, pos, SEEK_SET);
7644 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7646 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7647 __FILE__, __LINE__);
7648 tng_data->input_file = temp;
7649 tng_block_destroy(&block);
7650 return(TNG_CRITICAL);
7653 contents_start_pos = ftello(tng_data->output_file);
7655 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7656 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7657 1, tng_data->output_file) != 1)
7659 tng_data->input_file = temp;
7660 tng_block_destroy(&block);
7661 return(TNG_CRITICAL);
7665 if(hash_mode == TNG_USE_HASH)
7667 tng_md5_hash_update(tng_data, block, pos,
7668 pos + block->header_contents_size);
7671 fseeko(tng_data->output_file, 0, SEEK_END);
7672 output_file_len = ftello(tng_data->output_file);
7673 pos = contents_start_pos + block->block_contents_size;
7674 fseeko(tng_data->output_file, pos, SEEK_SET);
7676 while(pos < output_file_len)
7678 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7680 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7681 __FILE__, __LINE__);
7682 tng_data->input_file = temp;
7683 tng_block_destroy(&block);
7684 return(TNG_CRITICAL);
7687 if(hash_mode == TNG_USE_HASH)
7689 tng_md5_hash_update(tng_data, block, pos,
7690 pos + block->header_contents_size);
7692 pos += block->header_contents_size + block->block_contents_size;
7693 fseeko(tng_data->output_file, pos, SEEK_SET);
7696 tng_data->input_file = temp;
7697 tng_block_destroy(&block);
7698 return(TNG_SUCCESS);
7702 // ** Sets the name of a file contents block
7703 // * @param tng_data is a trajectory data container.
7704 // * @param block is the block, of which to change names.
7705 // * @param new_name is the new name of the block.
7706 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7707 // * error has occured.
7709 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7710 // tng_gen_block_t block,
7711 // const char *new_name)
7715 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7717 // * If the currently stored string length is not enough to store the new
7718 // * string it is freed and reallocated. *
7719 // if(block->name && strlen(block->name) < len)
7721 // free(block->name);
7726 // block->name = malloc(len);
7729 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7730 // __FILE__, __LINE__);
7731 // return(TNG_CRITICAL);
7735 // strncpy(block->name, new_name, len);
7737 // return(TNG_SUCCESS);
7741 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7742 const tng_atom_t atom,
7743 tng_residue_t *residue)
7747 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7749 *residue = atom->residue;
7751 return(TNG_SUCCESS);
7754 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7755 const tng_atom_t atom,
7760 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7761 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7763 strncpy(name, atom->name, max_len - 1);
7764 name[max_len - 1] = 0;
7766 if(strlen(atom->name) > (unsigned int)max_len - 1)
7768 return(TNG_FAILURE);
7770 return(TNG_SUCCESS);
7773 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7775 const char *new_name)
7780 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7781 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7783 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7785 /* If the currently stored string length is not enough to store the new
7786 * string it is freed and reallocated. */
7787 if(atom->name && strlen(atom->name) < len)
7794 atom->name = malloc(len);
7797 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7798 __FILE__, __LINE__);
7799 return(TNG_CRITICAL);
7803 strncpy(atom->name, new_name, len);
7805 return(TNG_SUCCESS);
7808 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7809 const tng_atom_t atom,
7814 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7815 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7817 strncpy(type, atom->atom_type, max_len - 1);
7818 type[max_len - 1] = 0;
7820 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7822 return(TNG_FAILURE);
7824 return(TNG_SUCCESS);
7827 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7829 const char *new_type)
7834 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7835 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7837 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7839 /* If the currently stored string length is not enough to store the new
7840 * string it is freed and reallocated. */
7841 if(atom->atom_type && strlen(atom->atom_type) < len)
7843 free(atom->atom_type);
7844 atom->atom_type = 0;
7846 if(!atom->atom_type)
7848 atom->atom_type = malloc(len);
7849 if(!atom->atom_type)
7851 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7852 __FILE__, __LINE__);
7853 return(TNG_CRITICAL);
7857 strncpy(atom->atom_type, new_type, len);
7859 return(TNG_SUCCESS);
7862 /** Initialise an atom struct
7863 * @param atom is the atom to initialise.
7864 * @return TNG_SUCCESS (0) if successful.
7866 static tng_function_status tng_atom_init(tng_atom_t atom)
7869 atom->atom_type = 0;
7871 return(TNG_SUCCESS);
7874 /** Free the memory in an atom struct
7875 * @param atom is the atom to destroy.
7876 * @return TNG_SUCCESS (0) if successful.
7878 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7887 free(atom->atom_type);
7888 atom->atom_type = 0;
7891 return(TNG_SUCCESS);
7894 tng_function_status DECLSPECDLLEXPORT tng_version_major
7895 (const tng_trajectory_t tng_data,
7900 *version = TNG_VERSION_MAJOR;
7902 return(TNG_SUCCESS);
7905 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7906 (const tng_trajectory_t tng_data,
7911 *version = TNG_VERSION_MINOR;
7913 return(TNG_SUCCESS);
7916 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7917 (const tng_trajectory_t tng_data,
7922 *patch_level = TNG_VERSION_PATCHLEVEL;
7924 return(TNG_SUCCESS);
7927 tng_function_status DECLSPECDLLEXPORT tng_version
7928 (const tng_trajectory_t tng_data,
7933 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
7935 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
7937 return(TNG_SUCCESS);
7940 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7941 (tng_trajectory_t tng_data,
7943 tng_molecule_t *molecule)
7947 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7948 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7950 /* Set ID to the ID of the last molecule + 1 */
7951 if(tng_data->n_molecules)
7953 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7960 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7963 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7964 (tng_trajectory_t tng_data,
7967 tng_molecule_t *molecule)
7969 tng_molecule_t new_molecules;
7970 int64_t *new_molecule_cnt_list;
7971 tng_function_status stat = TNG_SUCCESS;
7973 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7974 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7976 new_molecules = realloc(tng_data->molecules,
7977 sizeof(struct tng_molecule) *
7978 (tng_data->n_molecules + 1));
7982 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7983 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7984 __FILE__, __LINE__);
7985 free(tng_data->molecules);
7986 tng_data->molecules = 0;
7987 return(TNG_CRITICAL);
7990 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7992 (tng_data->n_molecules + 1));
7994 if(!new_molecule_cnt_list)
7996 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7997 sizeof(int64_t) * (tng_data->n_molecules + 1),
7998 __FILE__, __LINE__);
7999 free(tng_data->molecule_cnt_list);
8000 tng_data->molecule_cnt_list = 0;
8001 free(new_molecules);
8002 return(TNG_CRITICAL);
8005 tng_data->molecules = new_molecules;
8006 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8008 *molecule = &new_molecules[tng_data->n_molecules];
8010 tng_molecule_init(tng_data, *molecule);
8011 tng_molecule_name_set(tng_data, *molecule, name);
8013 /* FIXME: Should this be a function argument instead? */
8014 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8016 (*molecule)->id = id;
8018 tng_data->n_molecules++;
8023 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
8024 (tng_trajectory_t tng_data,
8025 tng_molecule_t *molecule_p)
8027 int64_t *new_molecule_cnt_list, id;
8028 tng_molecule_t new_molecules, molecule;
8030 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8032 /* Set ID to the ID of the last molecule + 1 */
8033 if(tng_data->n_molecules)
8035 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
8042 new_molecules = realloc(tng_data->molecules,
8043 sizeof(struct tng_molecule) *
8044 (tng_data->n_molecules + 1));
8048 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8049 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8050 __FILE__, __LINE__);
8051 free(tng_data->molecules);
8052 tng_data->molecules = 0;
8053 return(TNG_CRITICAL);
8056 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8058 (tng_data->n_molecules + 1));
8060 if(!new_molecule_cnt_list)
8062 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8063 sizeof(int64_t) * (tng_data->n_molecules + 1),
8064 __FILE__, __LINE__);
8065 free(tng_data->molecule_cnt_list);
8066 tng_data->molecule_cnt_list = 0;
8067 free(new_molecules);
8068 return(TNG_CRITICAL);
8071 molecule = *molecule_p;
8073 tng_data->molecules = new_molecules;
8074 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8076 new_molecules[tng_data->n_molecules] = *molecule;
8078 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8082 molecule = &new_molecules[tng_data->n_molecules];
8084 *molecule_p = molecule;
8088 tng_data->n_molecules++;
8090 return(TNG_SUCCESS);
8093 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8094 const tng_molecule_t molecule,
8099 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8100 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8102 strncpy(name, molecule->name, max_len - 1);
8103 name[max_len - 1] = 0;
8105 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8107 return(TNG_FAILURE);
8109 return(TNG_SUCCESS);
8112 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8113 (tng_trajectory_t tng_data,
8114 tng_molecule_t molecule,
8115 const char *new_name)
8120 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8121 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8123 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8125 /* If the currently stored string length is not enough to store the new
8126 * string it is freed and reallocated. */
8127 if(molecule->name && strlen(molecule->name) < len)
8129 free(molecule->name);
8134 molecule->name = malloc(len);
8137 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8138 __FILE__, __LINE__);
8139 return(TNG_CRITICAL);
8143 strncpy(molecule->name, new_name, len);
8145 return(TNG_SUCCESS);
8148 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8149 (const tng_trajectory_t tng_data,
8150 const tng_molecule_t molecule,
8153 int64_t i, index = -1;
8155 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8156 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8158 for(i = 0; i < tng_data->n_molecules; i++)
8160 if(&tng_data->molecules[i] == molecule)
8168 return(TNG_FAILURE);
8170 *cnt = tng_data->molecule_cnt_list[index];
8172 return(TNG_SUCCESS);
8175 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8176 (tng_trajectory_t tng_data,
8177 tng_molecule_t molecule,
8180 int64_t i, old_cnt, index = -1;
8182 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8184 for(i = 0; i < tng_data->n_molecules; i++)
8186 if(&tng_data->molecules[i] == molecule)
8194 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8195 __FILE__, __LINE__);
8196 return(TNG_FAILURE);
8198 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8200 old_cnt = tng_data->molecule_cnt_list[index];
8201 tng_data->molecule_cnt_list[index] = cnt;
8203 tng_data->n_particles += (cnt-old_cnt) *
8204 tng_data->molecules[index].n_atoms;
8208 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8209 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8211 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8212 tng_data->molecules[index].n_atoms;
8215 return(TNG_SUCCESS);
8218 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8219 (tng_trajectory_t tng_data,
8222 tng_molecule_t *molecule)
8224 int64_t i, n_molecules;
8226 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8227 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8228 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8230 n_molecules = tng_data->n_molecules;
8232 for(i = n_molecules - 1; i >= 0; i--)
8234 *molecule = &tng_data->molecules[i];
8235 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8237 if(nr == -1 || nr == (*molecule)->id)
8239 return(TNG_SUCCESS);
8246 return(TNG_FAILURE);
8249 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8250 (tng_trajectory_t tng_data,
8252 tng_molecule_t *molecule)
8254 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8255 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8257 if(index >= tng_data->n_molecules)
8260 return(TNG_FAILURE);
8262 *molecule = &tng_data->molecules[index];
8263 return(TNG_SUCCESS);
8266 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8267 tng_trajectory_t tng_data_dest)
8269 tng_molecule_t molecule, molecule_temp;
8270 tng_chain_t chain, chain_temp;
8271 tng_residue_t residue, residue_temp;
8272 tng_atom_t atom, atom_temp;
8273 tng_bond_t bond_temp;
8274 tng_function_status stat;
8275 int64_t i, j, k, l, *list_temp;
8277 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8278 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8280 for(i = 0; i < tng_data_dest->n_molecules; i++)
8282 molecule = &tng_data_dest->molecules[i];
8283 tng_molecule_destroy(tng_data_dest, molecule);
8286 tng_data_dest->n_molecules = 0;
8287 tng_data_dest->n_particles = 0;
8289 molecule_temp = realloc(tng_data_dest->molecules,
8290 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8293 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8294 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8295 __FILE__, __LINE__);
8296 free(tng_data_dest->molecules);
8297 tng_data_dest->molecules = 0;
8298 return(TNG_CRITICAL);
8300 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8301 sizeof(int64_t) * tng_data_src->n_molecules);
8304 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8305 sizeof(int64_t) * tng_data_src->n_molecules,
8306 __FILE__, __LINE__);
8307 free(tng_data_dest->molecule_cnt_list);
8308 tng_data_dest->molecule_cnt_list = 0;
8309 free(molecule_temp);
8310 return(TNG_CRITICAL);
8313 tng_data_dest->molecules = molecule_temp;
8314 tng_data_dest->molecule_cnt_list = list_temp;
8316 for(i = 0; i < tng_data_src->n_molecules; i++)
8318 molecule = &tng_data_src->molecules[i];
8319 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8321 if(stat != TNG_SUCCESS)
8323 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8324 __FILE__, __LINE__);
8327 molecule_temp->quaternary_str = molecule->quaternary_str;
8328 for(j = 0; j < molecule->n_chains; j++)
8330 chain = &molecule->chains[j];
8331 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8332 chain->name, chain->id,
8334 if(stat != TNG_SUCCESS)
8336 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8337 __FILE__, __LINE__);
8340 for(k = 0; k < chain->n_residues; k++)
8342 residue = &chain->residues[k];
8343 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8344 residue->name, residue->id,
8346 if(stat != TNG_SUCCESS)
8348 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8349 __FILE__, __LINE__);
8352 for(l = 0; l < residue->n_atoms; l++)
8354 atom = &molecule->atoms[residue->atoms_offset + l];
8355 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8356 atom->name, atom->atom_type,
8357 atom->id, &atom_temp);
8358 if(stat != TNG_SUCCESS)
8360 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8361 __FILE__, __LINE__);
8367 molecule_temp->n_bonds = molecule->n_bonds;
8368 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8372 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8373 sizeof(struct tng_bond) * molecule->n_bonds,
8374 __FILE__, __LINE__);
8375 free(molecule_temp->bonds);
8376 molecule_temp->n_bonds = 0;
8377 return(TNG_CRITICAL);
8379 molecule_temp->bonds = bond_temp;
8380 for(j = 0; j < molecule->n_bonds; j++)
8382 molecule_temp->bonds[j] = molecule->bonds[j];
8384 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8385 tng_data_src->molecule_cnt_list[i]);
8386 if(stat != TNG_SUCCESS)
8388 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8389 __FILE__, __LINE__);
8393 return(TNG_SUCCESS);
8396 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8397 (const tng_trajectory_t tng_data,
8398 const tng_molecule_t molecule,
8402 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8403 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8405 *n = molecule->n_chains;
8407 return(TNG_SUCCESS);
8410 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8411 (tng_trajectory_t tng_data,
8412 tng_molecule_t molecule,
8417 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8418 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8420 if(index >= molecule->n_chains)
8423 return(TNG_FAILURE);
8425 *chain = &molecule->chains[index];
8426 return(TNG_SUCCESS);
8429 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8430 (const tng_trajectory_t tng_data,
8431 const tng_molecule_t molecule,
8435 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8436 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8438 *n = molecule->n_residues;
8440 return(TNG_SUCCESS);
8443 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8444 (const tng_trajectory_t tng_data,
8445 const tng_molecule_t molecule,
8446 const int64_t index,
8447 tng_residue_t *residue)
8450 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8451 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8453 if(index >= molecule->n_residues)
8456 return(TNG_FAILURE);
8458 *residue = &molecule->residues[index];
8459 return(TNG_SUCCESS);
8462 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8463 (const tng_trajectory_t tng_data,
8464 const tng_molecule_t molecule,
8468 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8469 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8471 *n = molecule->n_atoms;
8473 return(TNG_SUCCESS);
8476 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8477 (const tng_trajectory_t tng_data,
8478 const tng_molecule_t molecule,
8479 const int64_t index,
8483 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8484 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8486 if(index >= molecule->n_atoms)
8489 return(TNG_FAILURE);
8491 *atom = &molecule->atoms[index];
8492 return(TNG_SUCCESS);
8495 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8496 (tng_trajectory_t tng_data,
8497 tng_molecule_t molecule,
8502 int64_t i, n_chains;
8505 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8506 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8508 n_chains = molecule->n_chains;
8510 for(i = n_chains - 1; i >= 0; i--)
8512 *chain = &molecule->chains[i];
8513 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8515 if(nr == -1 || nr == (*chain)->id)
8517 return(TNG_SUCCESS);
8524 return(TNG_FAILURE);
8527 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8528 (tng_trajectory_t tng_data,
8529 tng_molecule_t molecule,
8535 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8536 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8538 /* Set ID to the ID of the last chain + 1 */
8539 if(molecule->n_chains)
8541 id = molecule->chains[molecule->n_chains-1].id + 1;
8548 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8552 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8553 (tng_trajectory_t tng_data,
8554 tng_molecule_t molecule,
8559 tng_chain_t new_chains;
8560 tng_function_status stat = TNG_SUCCESS;
8562 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8563 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8565 new_chains = realloc(molecule->chains,
8566 sizeof(struct tng_chain) *
8567 (molecule->n_chains + 1));
8571 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8572 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8573 __FILE__, __LINE__);
8574 free(molecule->chains);
8575 molecule->chains = 0;
8576 return(TNG_CRITICAL);
8579 molecule->chains = new_chains;
8581 *chain = &new_chains[molecule->n_chains];
8584 tng_chain_name_set(tng_data, *chain, name);
8586 (*chain)->molecule = molecule;
8587 (*chain)->n_residues = 0;
8589 molecule->n_chains++;
8596 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8597 (const tng_trajectory_t tng_data,
8598 tng_molecule_t molecule,
8599 const int64_t from_atom_id,
8600 const int64_t to_atom_id,
8603 tng_bond_t new_bonds;
8606 new_bonds = realloc(molecule->bonds,
8607 sizeof(struct tng_bond) *
8608 (molecule->n_bonds + 1));
8612 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8613 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8614 __FILE__, __LINE__);
8616 free(molecule->bonds);
8617 molecule->bonds = 0;
8618 return(TNG_CRITICAL);
8621 molecule->bonds = new_bonds;
8623 *bond = &new_bonds[molecule->n_bonds];
8625 (*bond)->from_atom_id = from_atom_id;
8626 (*bond)->to_atom_id = to_atom_id;
8628 molecule->n_bonds++;
8630 return(TNG_SUCCESS);
8633 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8634 (tng_trajectory_t tng_data,
8635 tng_molecule_t molecule,
8643 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8645 n_atoms = molecule->n_atoms;
8647 for(i = n_atoms - 1; i >= 0; i--)
8649 *atom = &molecule->atoms[i];
8650 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8652 if(id == -1 || id == (*atom)->id)
8654 return(TNG_SUCCESS);
8661 return(TNG_FAILURE);
8664 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8665 const tng_chain_t chain,
8670 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8671 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8673 strncpy(name, chain->name, max_len - 1);
8674 name[max_len - 1] = 0;
8676 if(strlen(chain->name) > (unsigned int)max_len - 1)
8678 return(TNG_FAILURE);
8680 return(TNG_SUCCESS);
8683 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8684 (tng_trajectory_t tng_data,
8686 const char *new_name)
8691 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8693 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8695 /* If the currently stored string length is not enough to store the new
8696 * string it is freed and reallocated. */
8697 if(chain->name && strlen(chain->name) < len)
8704 chain->name = malloc(len);
8707 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8708 __FILE__, __LINE__);
8709 return(TNG_CRITICAL);
8713 strncpy(chain->name, new_name, len);
8715 return(TNG_SUCCESS);
8718 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8719 (const tng_trajectory_t tng_data,
8720 const tng_chain_t chain,
8724 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8725 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8727 *n = chain->n_residues;
8729 return(TNG_SUCCESS);
8732 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8733 (const tng_trajectory_t tng_data,
8734 const tng_chain_t chain,
8735 const int64_t index,
8736 tng_residue_t *residue)
8739 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8740 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8742 if(index >= chain->n_residues)
8745 return(TNG_FAILURE);
8747 *residue = &chain->residues[index];
8748 return(TNG_SUCCESS);
8751 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8752 (tng_trajectory_t tng_data,
8756 tng_residue_t *residue)
8758 int64_t i, n_residues;
8761 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8763 n_residues = chain->n_residues;
8765 for(i = n_residues - 1; i >= 0; i--)
8767 *residue = &chain->residues[i];
8768 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8770 if(id == -1 || id == (*residue)->id)
8772 return(TNG_SUCCESS);
8779 return(TNG_FAILURE);
8782 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8783 (tng_trajectory_t tng_data,
8786 tng_residue_t *residue)
8790 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8791 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8793 /* Set ID to the ID of the last residue + 1 */
8794 if(chain->n_residues)
8796 id = chain->residues[chain->n_residues-1].id + 1;
8803 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8807 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8808 (tng_trajectory_t tng_data,
8812 tng_residue_t *residue)
8815 tng_residue_t new_residues, temp_residue, last_residue;
8816 tng_molecule_t molecule = chain->molecule;
8817 tng_function_status stat = TNG_SUCCESS;
8819 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8820 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8822 if(chain->n_residues)
8824 curr_index = chain->residues - molecule->residues;
8831 new_residues = realloc(molecule->residues,
8832 sizeof(struct tng_residue) *
8833 (molecule->n_residues + 1));
8837 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8838 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8839 __FILE__, __LINE__);
8840 free(molecule->residues);
8841 molecule->residues = 0;
8842 return(TNG_CRITICAL);
8845 molecule->residues = new_residues;
8847 if(curr_index != -1)
8849 chain->residues = new_residues + curr_index;
8850 if(molecule->n_residues)
8852 last_residue = &new_residues[molecule->n_residues - 1];
8854 temp_residue = chain->residues + (chain->n_residues - 1);
8855 /* Make space in list of residues to add the new residues together with the other
8856 * residues of this chain */
8857 if(temp_residue != last_residue)
8860 memmove(temp_residue + 1, temp_residue,
8861 last_residue - temp_residue);
8867 curr_index = molecule->n_residues;
8870 *residue = &molecule->residues[curr_index + chain->n_residues];
8872 if(!chain->n_residues)
8874 chain->residues = *residue;
8878 chain->residues = &molecule->residues[curr_index];
8881 (*residue)->name = 0;
8882 tng_residue_name_set(tng_data, *residue, name);
8884 (*residue)->chain = chain;
8885 (*residue)->n_atoms = 0;
8886 (*residue)->atoms_offset = 0;
8888 chain->n_residues++;
8889 molecule->n_residues++;
8891 (*residue)->id = id;
8896 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8897 const tng_residue_t residue,
8902 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8903 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8905 strncpy(name, residue->name, max_len - 1);
8906 name[max_len - 1] = 0;
8908 if(strlen(residue->name) > (unsigned int)max_len - 1)
8910 return(TNG_FAILURE);
8912 return(TNG_SUCCESS);
8915 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8916 tng_residue_t residue,
8917 const char *new_name)
8922 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8923 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8925 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8927 /* If the currently stored string length is not enough to store the new
8928 * string it is freed and reallocated. */
8929 if(residue->name && strlen(residue->name) < len)
8931 free(residue->name);
8936 residue->name = malloc(len);
8939 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8940 __FILE__, __LINE__);
8941 return(TNG_CRITICAL);
8945 strncpy(residue->name, new_name, len);
8947 return(TNG_SUCCESS);
8950 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8951 (const tng_trajectory_t tng_data,
8952 const tng_residue_t residue,
8956 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8957 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8959 *n = residue->n_atoms;
8961 return(TNG_SUCCESS);
8964 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8965 (const tng_trajectory_t tng_data,
8966 const tng_residue_t residue,
8967 const int64_t index,
8971 tng_molecule_t molecule;
8974 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8975 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8977 if(index >= residue->n_atoms)
8980 return(TNG_FAILURE);
8982 chain = residue->chain;
8983 molecule = chain->molecule;
8985 if(index + residue->atoms_offset >= molecule->n_atoms)
8988 return(TNG_FAILURE);
8991 *atom = &molecule->atoms[residue->atoms_offset + index];
8992 return(TNG_SUCCESS);
8995 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8996 (tng_trajectory_t tng_data,
8997 tng_residue_t residue,
8998 const char *atom_name,
8999 const char *atom_type,
9004 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9005 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9006 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9008 /* Set ID to the ID of the last atom + 1 */
9009 if(residue->chain->molecule->n_atoms)
9011 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
9018 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
9022 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
9023 (tng_trajectory_t tng_data,
9024 tng_residue_t residue,
9025 const char *atom_name,
9026 const char *atom_type,
9030 tng_atom_t new_atoms;
9031 tng_molecule_t molecule = residue->chain->molecule;
9032 tng_function_status stat = TNG_SUCCESS;
9034 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9035 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9036 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9038 if(!residue->n_atoms)
9040 residue->atoms_offset = molecule->n_atoms;
9043 new_atoms = realloc(molecule->atoms,
9044 sizeof(struct tng_atom) *
9045 (molecule->n_atoms + 1));
9049 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9050 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
9051 __FILE__, __LINE__);
9052 free(molecule->atoms);
9053 molecule->atoms = 0;
9054 return(TNG_CRITICAL);
9057 molecule->atoms = new_atoms;
9059 *atom = &new_atoms[molecule->n_atoms];
9061 tng_atom_init(*atom);
9062 tng_atom_name_set(tng_data, *atom, atom_name);
9063 tng_atom_type_set(tng_data, *atom, atom_type);
9065 (*atom)->residue = residue;
9068 molecule->n_atoms++;
9075 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
9076 tng_molecule_t *molecule_p)
9078 *molecule_p = malloc(sizeof(struct tng_molecule));
9081 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9082 sizeof(struct tng_molecule), __FILE__, __LINE__);
9083 return(TNG_CRITICAL);
9086 tng_molecule_init(tng_data, *molecule_p);
9088 return(TNG_SUCCESS);
9091 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9092 tng_molecule_t *molecule_p)
9096 return(TNG_SUCCESS);
9099 tng_molecule_destroy(tng_data, *molecule_p);
9104 return(TNG_SUCCESS);
9107 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9108 tng_molecule_t molecule)
9111 molecule->quaternary_str = 1;
9113 molecule->n_chains = 0;
9114 molecule->chains = 0;
9115 molecule->n_residues = 0;
9116 molecule->residues = 0;
9117 molecule->n_atoms = 0;
9118 molecule->atoms = 0;
9119 molecule->n_bonds = 0;
9120 molecule->bonds = 0;
9122 return(TNG_SUCCESS);
9125 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9126 tng_molecule_t molecule)
9133 free(molecule->name);
9137 if(molecule->chains)
9139 for(i = 0; i < molecule->n_chains; i++)
9141 if(molecule->chains[i].name)
9143 free(molecule->chains[i].name);
9144 molecule->chains[i].name = 0;
9147 free(molecule->chains);
9148 molecule->chains = 0;
9150 molecule->n_chains = 0;
9152 if(molecule->residues)
9154 for(i = 0; i < molecule->n_residues; i++)
9156 if(molecule->residues[i].name)
9158 free(molecule->residues[i].name);
9159 molecule->residues[i].name = 0;
9162 free(molecule->residues);
9163 molecule->residues = 0;
9165 molecule->n_residues = 0;
9169 for(i = 0; i < molecule->n_atoms; i++)
9171 tng_atom_destroy(&molecule->atoms[i]);
9173 free(molecule->atoms);
9174 molecule->atoms = 0;
9176 molecule->n_atoms = 0;
9180 free(molecule->bonds);
9181 molecule->bonds = 0;
9183 molecule->n_bonds = 0;
9185 return(TNG_SUCCESS);
9188 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9189 (const tng_trajectory_t tng_data,
9194 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9196 tng_bool found = TNG_FALSE;
9198 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9199 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9201 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9203 if(!molecule_cnt_list)
9205 return(TNG_FAILURE);
9208 for(i = 0; i < tng_data->n_molecules; i++)
9210 mol = &tng_data->molecules[i];
9211 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9213 cnt += mol->n_atoms * molecule_cnt_list[i];
9221 return(TNG_FAILURE);
9224 strncpy(name, mol->name, max_len - 1);
9225 name[max_len - 1] = 0;
9227 if(strlen(mol->name) > (unsigned int)max_len - 1)
9229 return(TNG_FAILURE);
9231 return(TNG_SUCCESS);
9234 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9235 (const tng_trajectory_t tng_data,
9239 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9241 tng_bool found = TNG_FALSE;
9243 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9244 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9246 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9248 if(!molecule_cnt_list)
9250 return(TNG_FAILURE);
9253 for(i = 0; i < tng_data->n_molecules; i++)
9255 mol = &tng_data->molecules[i];
9256 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9258 cnt += mol->n_atoms * molecule_cnt_list[i];
9266 return(TNG_FAILURE);
9271 return(TNG_SUCCESS);
9274 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9275 (const tng_trajectory_t tng_data,
9277 int64_t **from_atoms,
9280 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9281 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9285 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9286 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9287 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9288 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9290 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9292 if(!molecule_cnt_list)
9294 return(TNG_FAILURE);
9298 /* First count the total number of bonds to allocate memory */
9299 for(i = 0; i < tng_data->n_molecules; i++)
9301 mol = &tng_data->molecules[i];
9302 mol_cnt = molecule_cnt_list[i];
9303 *n_bonds += mol_cnt * mol->n_bonds;
9307 return(TNG_SUCCESS);
9310 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9313 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9314 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9315 return(TNG_CRITICAL);
9317 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9320 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9321 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9324 return(TNG_CRITICAL);
9328 for(i = 0; i < tng_data->n_molecules; i++)
9330 mol = &tng_data->molecules[i];
9331 mol_cnt = molecule_cnt_list[i];
9332 for(j = 0; j < mol_cnt; j++)
9334 for(k = 0; k < mol->n_bonds; k++)
9336 bond = &mol->bonds[k];
9337 from_atom = atom_cnt + bond->from_atom_id;
9338 to_atom = atom_cnt + bond->to_atom_id;
9339 (*from_atoms)[cnt] = from_atom;
9340 (*to_atoms)[cnt++] = to_atom;
9342 atom_cnt += mol->n_atoms;
9346 return(TNG_SUCCESS);
9349 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9350 (const tng_trajectory_t tng_data,
9355 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9358 tng_bool found = TNG_FALSE;
9360 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9361 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9363 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9365 if(!molecule_cnt_list)
9367 return(TNG_FAILURE);
9370 for(i = 0; i < tng_data->n_molecules; i++)
9372 mol = &tng_data->molecules[i];
9373 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9375 cnt += mol->n_atoms * molecule_cnt_list[i];
9378 atom = &mol->atoms[nr % mol->n_atoms];
9384 return(TNG_FAILURE);
9386 if(!atom->residue || !atom->residue->chain)
9388 return(TNG_FAILURE);
9391 strncpy(name, atom->residue->chain->name, max_len - 1);
9392 name[max_len - 1] = 0;
9394 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9396 return(TNG_FAILURE);
9398 return(TNG_SUCCESS);
9401 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9402 (const tng_trajectory_t tng_data,
9407 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9410 tng_bool found = TNG_FALSE;
9412 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9413 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9415 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9417 if(!molecule_cnt_list)
9419 return(TNG_FAILURE);
9422 for(i = 0; i < tng_data->n_molecules; i++)
9424 mol = &tng_data->molecules[i];
9425 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9427 cnt += mol->n_atoms * molecule_cnt_list[i];
9430 atom = &mol->atoms[nr % mol->n_atoms];
9436 return(TNG_FAILURE);
9440 return(TNG_FAILURE);
9443 strncpy(name, atom->residue->name, max_len - 1);
9444 name[max_len - 1] = 0;
9446 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9448 return(TNG_FAILURE);
9450 return(TNG_SUCCESS);
9453 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9454 (const tng_trajectory_t tng_data,
9458 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9461 tng_bool found = TNG_FALSE;
9463 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9464 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9466 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9468 if(!molecule_cnt_list)
9470 return(TNG_FAILURE);
9473 for(i = 0; i < tng_data->n_molecules; i++)
9475 mol = &tng_data->molecules[i];
9476 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9478 cnt += mol->n_atoms * molecule_cnt_list[i];
9481 atom = &mol->atoms[nr % mol->n_atoms];
9487 return(TNG_FAILURE);
9491 return(TNG_FAILURE);
9494 *id = atom->residue->id;
9496 return(TNG_SUCCESS);
9499 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9500 (const tng_trajectory_t tng_data,
9504 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9507 tng_bool found = TNG_FALSE;
9509 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9510 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9512 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9514 if(!molecule_cnt_list)
9516 return(TNG_FAILURE);
9519 for(i = 0; i < tng_data->n_molecules; i++)
9521 mol = &tng_data->molecules[i];
9522 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9524 cnt += mol->n_atoms * molecule_cnt_list[i];
9525 offset += mol->n_residues * molecule_cnt_list[i];
9528 atom = &mol->atoms[nr % mol->n_atoms];
9534 return(TNG_FAILURE);
9538 return(TNG_FAILURE);
9541 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9543 *id = atom->residue->id + offset;
9545 return(TNG_SUCCESS);
9548 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9549 (const tng_trajectory_t tng_data,
9554 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9557 tng_bool found = TNG_FALSE;
9559 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9560 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9562 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9564 if(!molecule_cnt_list)
9566 return(TNG_FAILURE);
9569 for(i = 0; i < tng_data->n_molecules; i++)
9571 mol = &tng_data->molecules[i];
9572 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9574 cnt += mol->n_atoms * molecule_cnt_list[i];
9577 atom = &mol->atoms[nr % mol->n_atoms];
9583 return(TNG_FAILURE);
9586 strncpy(name, atom->name, max_len - 1);
9587 name[max_len - 1] = 0;
9589 if(strlen(atom->name) > (unsigned int)max_len - 1)
9591 return(TNG_FAILURE);
9593 return(TNG_SUCCESS);
9596 tng_function_status tng_atom_type_of_particle_nr_get
9597 (const tng_trajectory_t tng_data,
9602 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9605 tng_bool found = TNG_FALSE;
9607 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9608 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9610 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9612 if(!molecule_cnt_list)
9614 return(TNG_FAILURE);
9617 for(i = 0; i < tng_data->n_molecules; i++)
9619 mol = &tng_data->molecules[i];
9620 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9622 cnt += mol->n_atoms * molecule_cnt_list[i];
9625 atom = &mol->atoms[nr % mol->n_atoms];
9631 return(TNG_FAILURE);
9634 strncpy(type, atom->atom_type, max_len - 1);
9635 type[max_len - 1] = 0;
9637 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9639 return(TNG_FAILURE);
9641 return(TNG_SUCCESS);
9644 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9645 (tng_trajectory_t tng_data,
9646 const int64_t num_first_particle,
9647 const int64_t n_particles,
9648 const int64_t *mapping_table)
9651 tng_particle_mapping_t mapping;
9652 tng_trajectory_frame_set_t frame_set;
9654 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9656 frame_set = &tng_data->current_trajectory_frame_set;
9658 /* Sanity check of the particle ranges. Split into multiple if
9659 * statements for improved readability */
9660 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9662 mapping = &frame_set->mappings[i];
9663 if(num_first_particle >= mapping->num_first_particle &&
9664 num_first_particle < mapping->num_first_particle +
9665 mapping->n_particles)
9667 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9668 return(TNG_FAILURE);
9670 if(num_first_particle + n_particles >=
9671 mapping->num_first_particle &&
9672 num_first_particle + n_particles <
9673 mapping->num_first_particle + mapping->n_particles)
9675 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9676 return(TNG_FAILURE);
9678 if(mapping->num_first_particle >= num_first_particle &&
9679 mapping->num_first_particle < num_first_particle +
9682 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9683 return(TNG_FAILURE);
9685 if(mapping->num_first_particle + mapping->n_particles >
9686 num_first_particle &&
9687 mapping->num_first_particle + mapping->n_particles <
9688 num_first_particle + n_particles)
9690 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9691 return(TNG_FAILURE);
9695 frame_set->n_mapping_blocks++;
9697 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9698 frame_set->n_mapping_blocks);
9702 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9703 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9704 __FILE__, __LINE__);
9705 free(frame_set->mappings);
9706 frame_set->mappings = 0;
9707 return(TNG_CRITICAL);
9709 frame_set->mappings = mapping;
9711 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9712 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9714 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9715 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9717 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9718 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9719 return(TNG_CRITICAL);
9722 for(i=0; i<n_particles; i++)
9724 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9727 return(TNG_SUCCESS);
9730 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9732 tng_trajectory_frame_set_t frame_set;
9733 tng_particle_mapping_t mapping;
9736 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9738 frame_set = &tng_data->current_trajectory_frame_set;
9740 if(frame_set->n_mapping_blocks && frame_set->mappings)
9742 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9744 mapping = &frame_set->mappings[i];
9745 if(mapping->real_particle_numbers)
9747 free(mapping->real_particle_numbers);
9748 mapping->real_particle_numbers = 0;
9751 free(frame_set->mappings);
9752 frame_set->mappings = 0;
9753 frame_set->n_mapping_blocks = 0;
9756 return(TNG_SUCCESS);
9759 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9762 tng_trajectory_frame_set_t frame_set;
9763 tng_trajectory_t tng_data;
9765 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9768 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9769 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9770 return(TNG_CRITICAL);
9773 tng_data = *tng_data_p;
9775 frame_set = &tng_data->current_trajectory_frame_set;
9777 tng_data->input_file_path = 0;
9778 tng_data->input_file = 0;
9779 tng_data->input_file_len = 0;
9780 tng_data->output_file_path = 0;
9781 tng_data->output_file = 0;
9783 tng_data->first_program_name = 0;
9784 tng_data->first_user_name = 0;
9785 tng_data->first_computer_name = 0;
9786 tng_data->first_pgp_signature = 0;
9787 tng_data->last_program_name = 0;
9788 tng_data->last_user_name = 0;
9789 tng_data->last_computer_name = 0;
9790 tng_data->last_pgp_signature = 0;
9791 tng_data->forcefield_name = 0;
9796 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9800 tng_data->time = seconds;
9803 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9804 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9805 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9806 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9807 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9808 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9809 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9810 tng_data->frame_set_n_frames = 100;
9811 tng_data->n_trajectory_frame_sets = 0;
9812 tng_data->medium_stride_length = 100;
9813 tng_data->long_stride_length = 10000;
9815 tng_data->time_per_frame = -1;
9817 tng_data->n_particle_data_blocks = 0;
9818 tng_data->n_data_blocks = 0;
9820 tng_data->non_tr_particle_data = 0;
9821 tng_data->non_tr_data = 0;
9823 tng_data->compress_algo_pos = 0;
9824 tng_data->compress_algo_vel = 0;
9825 tng_data->compression_precision = 1000;
9826 tng_data->distance_unit_exponential = -9;
9828 frame_set->first_frame = -1;
9829 frame_set->n_mapping_blocks = 0;
9830 frame_set->mappings = 0;
9831 frame_set->molecule_cnt_list = 0;
9833 frame_set->n_particle_data_blocks = 0;
9834 frame_set->n_data_blocks = 0;
9836 frame_set->tr_particle_data = 0;
9837 frame_set->tr_data = 0;
9839 frame_set->n_written_frames = 0;
9840 frame_set->n_unwritten_frames = 0;
9842 frame_set->next_frame_set_file_pos = -1;
9843 frame_set->prev_frame_set_file_pos = -1;
9844 frame_set->medium_stride_next_frame_set_file_pos = -1;
9845 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9846 frame_set->long_stride_next_frame_set_file_pos = -1;
9847 frame_set->long_stride_prev_frame_set_file_pos = -1;
9849 frame_set->first_frame_time = -1;
9851 tng_data->n_molecules = 0;
9852 tng_data->molecules = 0;
9853 tng_data->molecule_cnt_list = 0;
9854 tng_data->n_particles = 0;
9857 /* Check the endianness of the computer */
9858 static int32_t endianness_32 = 0x01234567;
9860 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9862 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9866 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9868 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9873 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9875 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9879 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9880 /* 0x0123456789ABCDEF */
9881 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9883 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9886 /* 0xEFCDAB8967452301 */
9887 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9889 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9892 /* 0x89ABCDEF01234567 */
9893 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9895 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9898 /* 0x45670123CDEF89AB */
9899 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9901 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9904 /* 0x23016745AB89EFCD */
9905 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9907 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9911 /* By default do not swap the byte order, i.e. keep the byte order of the
9912 * architecture. The input file endianness will be set when reading the
9913 * header. The output endianness can be changed - before the file is
9915 tng_data->input_endianness_swap_func_32 = 0;
9916 tng_data->input_endianness_swap_func_64 = 0;
9917 tng_data->output_endianness_swap_func_32 = 0;
9918 tng_data->output_endianness_swap_func_64 = 0;
9920 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9921 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9922 tng_data->current_trajectory_frame_set.n_frames = 0;
9924 return(TNG_SUCCESS);
9927 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9930 int64_t n_particles, n_values_per_frame;
9931 tng_trajectory_t tng_data = *tng_data_p;
9932 tng_trajectory_frame_set_t frame_set;
9936 return(TNG_SUCCESS);
9939 frame_set = &tng_data->current_trajectory_frame_set;
9941 if(tng_data->input_file_path)
9943 free(tng_data->input_file_path);
9944 tng_data->input_file_path = 0;
9947 if(tng_data->input_file)
9949 if(tng_data->output_file == tng_data->input_file)
9951 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9952 tng_data->output_file = 0;
9954 fclose(tng_data->input_file);
9955 tng_data->input_file = 0;
9958 if(tng_data->output_file_path)
9960 free(tng_data->output_file_path);
9961 tng_data->output_file_path = 0;
9964 if(tng_data->output_file)
9966 /* FIXME: Do not always write the hash */
9967 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9968 fclose(tng_data->output_file);
9969 tng_data->output_file = 0;
9972 if(tng_data->first_program_name)
9974 free(tng_data->first_program_name);
9975 tng_data->first_program_name = 0;
9978 if(tng_data->last_program_name)
9980 free(tng_data->last_program_name);
9981 tng_data->last_program_name = 0;
9984 if(tng_data->first_user_name)
9986 free(tng_data->first_user_name);
9987 tng_data->first_user_name = 0;
9990 if(tng_data->last_user_name)
9992 free(tng_data->last_user_name);
9993 tng_data->last_user_name = 0;
9996 if(tng_data->first_computer_name)
9998 free(tng_data->first_computer_name);
9999 tng_data->first_computer_name = 0;
10002 if(tng_data->last_computer_name)
10004 free(tng_data->last_computer_name);
10005 tng_data->last_computer_name = 0;
10008 if(tng_data->first_pgp_signature)
10010 free(tng_data->first_pgp_signature);
10011 tng_data->first_pgp_signature = 0;
10014 if(tng_data->last_pgp_signature)
10016 free(tng_data->last_pgp_signature);
10017 tng_data->last_pgp_signature = 0;
10020 if(tng_data->forcefield_name)
10022 free(tng_data->forcefield_name);
10023 tng_data->forcefield_name = 0;
10026 tng_frame_set_particle_mapping_free(tng_data);
10028 if(frame_set->molecule_cnt_list)
10030 free(frame_set->molecule_cnt_list);
10031 frame_set->molecule_cnt_list = 0;
10034 if(tng_data->var_num_atoms_flag)
10036 n_particles = frame_set->n_particles;
10040 n_particles = tng_data->n_particles;
10043 if(tng_data->non_tr_particle_data)
10045 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
10047 if(tng_data->non_tr_particle_data[i].values)
10049 free(tng_data->non_tr_particle_data[i].values);
10050 tng_data->non_tr_particle_data[i].values = 0;
10053 if(tng_data->non_tr_particle_data[i].strings)
10055 n_values_per_frame = tng_data->non_tr_particle_data[i].
10056 n_values_per_frame;
10057 if(tng_data->non_tr_particle_data[i].strings[0])
10059 for(j = 0; j < n_particles; j++)
10061 if(tng_data->non_tr_particle_data[i].strings[0][j])
10063 for(k = 0; k < n_values_per_frame; k++)
10065 if(tng_data->non_tr_particle_data[i].
10068 free(tng_data->non_tr_particle_data[i].
10070 tng_data->non_tr_particle_data[i].
10071 strings[0][j][k] = 0;
10074 free(tng_data->non_tr_particle_data[i].
10076 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
10079 free(tng_data->non_tr_particle_data[i].strings[0]);
10080 tng_data->non_tr_particle_data[i].strings[0] = 0;
10082 free(tng_data->non_tr_particle_data[i].strings);
10083 tng_data->non_tr_particle_data[i].strings = 0;
10086 if(tng_data->non_tr_particle_data[i].block_name)
10088 free(tng_data->non_tr_particle_data[i].block_name);
10089 tng_data->non_tr_particle_data[i].block_name = 0;
10092 free(tng_data->non_tr_particle_data);
10093 tng_data->non_tr_particle_data = 0;
10096 if(tng_data->non_tr_data)
10098 for(i = 0; i < tng_data->n_data_blocks; i++)
10100 if(tng_data->non_tr_data[i].values)
10102 free(tng_data->non_tr_data[i].values);
10103 tng_data->non_tr_data[i].values = 0;
10106 if(tng_data->non_tr_data[i].strings)
10108 n_values_per_frame = tng_data->non_tr_data[i].
10109 n_values_per_frame;
10110 if(tng_data->non_tr_data[i].strings[0])
10112 for(j = 0; j < n_values_per_frame; j++)
10114 if(tng_data->non_tr_data[i].strings[0][j])
10116 free(tng_data->non_tr_data[i].strings[0][j]);
10117 tng_data->non_tr_data[i].strings[0][j] = 0;
10120 free(tng_data->non_tr_data[i].strings[0]);
10121 tng_data->non_tr_data[i].strings[0] = 0;
10123 free(tng_data->non_tr_data[i].strings);
10124 tng_data->non_tr_data[i].strings = 0;
10127 if(tng_data->non_tr_data[i].block_name)
10129 free(tng_data->non_tr_data[i].block_name);
10130 tng_data->non_tr_data[i].block_name = 0;
10133 free(tng_data->non_tr_data);
10134 tng_data->non_tr_data = 0;
10137 tng_data->n_particle_data_blocks = 0;
10138 tng_data->n_data_blocks = 0;
10140 if(tng_data->compress_algo_pos)
10142 free(tng_data->compress_algo_pos);
10143 tng_data->compress_algo_pos = 0;
10145 if(tng_data->compress_algo_vel)
10147 free(tng_data->compress_algo_vel);
10148 tng_data->compress_algo_vel = 0;
10151 if(frame_set->tr_particle_data)
10153 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10155 if(frame_set->tr_particle_data[i].values)
10157 free(frame_set->tr_particle_data[i].values);
10158 frame_set->tr_particle_data[i].values = 0;
10161 if(frame_set->tr_particle_data[i].strings)
10163 n_values_per_frame = frame_set->tr_particle_data[i].
10164 n_values_per_frame;
10165 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10167 if(frame_set->tr_particle_data[i].strings[j])
10169 for(k = 0; k < n_particles; k++)
10171 if(frame_set->tr_particle_data[i].
10174 for(l = 0; l < n_values_per_frame; l++)
10176 if(frame_set->tr_particle_data[i].
10179 free(frame_set->tr_particle_data[i].
10181 frame_set->tr_particle_data[i].
10182 strings[j][k][l] = 0;
10185 free(frame_set->tr_particle_data[i].
10187 frame_set->tr_particle_data[i].
10191 free(frame_set->tr_particle_data[i].strings[j]);
10192 frame_set->tr_particle_data[i].strings[j] = 0;
10195 free(frame_set->tr_particle_data[i].strings);
10196 frame_set->tr_particle_data[i].strings = 0;
10199 if(frame_set->tr_particle_data[i].block_name)
10201 free(frame_set->tr_particle_data[i].block_name);
10202 frame_set->tr_particle_data[i].block_name = 0;
10205 free(frame_set->tr_particle_data);
10206 frame_set->tr_particle_data = 0;
10209 if(frame_set->tr_data)
10211 for(i = 0; i < frame_set->n_data_blocks; i++)
10213 if(frame_set->tr_data[i].values)
10215 free(frame_set->tr_data[i].values);
10216 frame_set->tr_data[i].values = 0;
10219 if(frame_set->tr_data[i].strings)
10221 n_values_per_frame = frame_set->tr_data[i].
10222 n_values_per_frame;
10223 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10225 if(frame_set->tr_data[i].strings[j])
10227 for(k = 0; k < n_values_per_frame; k++)
10229 if(frame_set->tr_data[i].strings[j][k])
10231 free(frame_set->tr_data[i].strings[j][k]);
10232 frame_set->tr_data[i].strings[j][k] = 0;
10235 free(frame_set->tr_data[i].strings[j]);
10236 frame_set->tr_data[i].strings[j] = 0;
10239 free(frame_set->tr_data[i].strings);
10240 frame_set->tr_data[i].strings = 0;
10243 if(frame_set->tr_data[i].block_name)
10245 free(frame_set->tr_data[i].block_name);
10246 frame_set->tr_data[i].block_name = 0;
10249 free(frame_set->tr_data);
10250 frame_set->tr_data = 0;
10253 frame_set->n_particle_data_blocks = 0;
10254 frame_set->n_data_blocks = 0;
10256 if(tng_data->molecules)
10258 for(i = 0; i < tng_data->n_molecules; i++)
10260 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10262 free(tng_data->molecules);
10263 tng_data->molecules = 0;
10264 tng_data->n_molecules = 0;
10266 if(tng_data->molecule_cnt_list)
10268 free(tng_data->molecule_cnt_list);
10269 tng_data->molecule_cnt_list = 0;
10275 return(TNG_SUCCESS);
10278 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10279 tng_trajectory_t *dest_p)
10281 tng_trajectory_frame_set_t frame_set;
10282 tng_trajectory_t dest;
10284 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10286 *dest_p = malloc(sizeof(struct tng_trajectory));
10289 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10290 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10291 return(TNG_CRITICAL);
10296 frame_set = &dest->current_trajectory_frame_set;
10298 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10299 if(!dest->input_file_path)
10301 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10302 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10303 return(TNG_CRITICAL);
10305 strcpy(dest->input_file_path, src->input_file_path);
10306 dest->input_file = 0;
10307 dest->input_file_len = src->input_file_len;
10308 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10309 if(!dest->output_file_path)
10311 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10312 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10313 return(TNG_CRITICAL);
10315 strcpy(dest->output_file_path, src->output_file_path);
10316 dest->output_file = 0;
10318 dest->first_program_name = 0;
10319 dest->first_user_name = 0;
10320 dest->first_computer_name = 0;
10321 dest->first_pgp_signature = 0;
10322 dest->last_program_name = 0;
10323 dest->last_user_name = 0;
10324 dest->last_computer_name = 0;
10325 dest->last_pgp_signature = 0;
10326 dest->forcefield_name = 0;
10328 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10329 dest->first_trajectory_frame_set_input_file_pos =
10330 src->first_trajectory_frame_set_input_file_pos;
10331 dest->last_trajectory_frame_set_input_file_pos =
10332 src->last_trajectory_frame_set_input_file_pos;
10333 dest->current_trajectory_frame_set_input_file_pos =
10334 src->current_trajectory_frame_set_input_file_pos;
10335 dest->first_trajectory_frame_set_output_file_pos =
10336 src->first_trajectory_frame_set_output_file_pos;
10337 dest->last_trajectory_frame_set_output_file_pos =
10338 src->last_trajectory_frame_set_output_file_pos;
10339 dest->current_trajectory_frame_set_output_file_pos =
10340 src->current_trajectory_frame_set_output_file_pos;
10341 dest->frame_set_n_frames = src->frame_set_n_frames;
10342 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10343 dest->medium_stride_length = src->medium_stride_length;
10344 dest->long_stride_length = src->long_stride_length;
10346 dest->time_per_frame = src->time_per_frame;
10348 /* Currently the non trajectory data blocks are not copied since it
10349 * can lead to problems when freeing memory in a parallel block. */
10350 dest->n_particle_data_blocks = 0;
10351 dest->n_data_blocks = 0;
10352 dest->non_tr_particle_data = 0;
10353 dest->non_tr_data = 0;
10355 dest->compress_algo_pos = 0;
10356 dest->compress_algo_vel = 0;
10357 dest->distance_unit_exponential = -9;
10358 dest->compression_precision = 1000;
10360 frame_set->n_mapping_blocks = 0;
10361 frame_set->mappings = 0;
10362 frame_set->molecule_cnt_list = 0;
10364 frame_set->n_particle_data_blocks = 0;
10365 frame_set->n_data_blocks = 0;
10367 frame_set->tr_particle_data = 0;
10368 frame_set->tr_data = 0;
10370 frame_set->next_frame_set_file_pos = -1;
10371 frame_set->prev_frame_set_file_pos = -1;
10372 frame_set->medium_stride_next_frame_set_file_pos = -1;
10373 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10374 frame_set->long_stride_next_frame_set_file_pos = -1;
10375 frame_set->long_stride_prev_frame_set_file_pos = -1;
10376 frame_set->first_frame = -1;
10378 dest->n_molecules = 0;
10379 dest->molecules = 0;
10380 dest->molecule_cnt_list = 0;
10381 dest->n_particles = src->n_particles;
10383 dest->endianness_32 = src->endianness_32;
10384 dest->endianness_64 = src->endianness_64;
10385 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10386 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10387 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10388 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10390 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10391 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10392 dest->current_trajectory_frame_set.n_frames = 0;
10394 return(TNG_SUCCESS);
10397 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10398 char *file_name, const int max_len)
10400 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10401 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10403 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10404 file_name[max_len - 1] = 0;
10406 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10408 return(TNG_FAILURE);
10410 return(TNG_SUCCESS);
10413 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10414 const char *file_name)
10419 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10420 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10423 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10426 return(TNG_SUCCESS);
10429 if(tng_data->input_file)
10431 fclose(tng_data->input_file);
10434 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10435 temp = realloc(tng_data->input_file_path, len);
10438 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10439 __FILE__, __LINE__);
10440 free(tng_data->input_file_path);
10441 tng_data->input_file_path = 0;
10442 return(TNG_CRITICAL);
10444 tng_data->input_file_path = temp;
10446 strncpy(tng_data->input_file_path, file_name, len);
10448 return(tng_input_file_init(tng_data));
10451 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10452 char *file_name, const int max_len)
10454 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10455 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10457 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10458 file_name[max_len - 1] = 0;
10460 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10462 return(TNG_FAILURE);
10464 return(TNG_SUCCESS);
10467 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10468 const char *file_name)
10473 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10474 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10476 if(tng_data->output_file_path &&
10477 strcmp(tng_data->output_file_path, file_name) == 0)
10479 return(TNG_SUCCESS);
10482 if(tng_data->output_file)
10484 fclose(tng_data->output_file);
10487 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10488 temp = realloc(tng_data->output_file_path, len);
10491 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10492 __FILE__, __LINE__);
10493 free(tng_data->output_file_path);
10494 tng_data->output_file_path = 0;
10495 return(TNG_CRITICAL);
10497 tng_data->output_file_path = temp;
10499 strncpy(tng_data->output_file_path, file_name, len);
10501 return(tng_output_file_init(tng_data));
10504 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10505 (tng_trajectory_t tng_data,
10506 const char *file_name)
10511 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10512 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10514 if(tng_data->output_file_path &&
10515 strcmp(tng_data->output_file_path, file_name) == 0)
10517 return(TNG_SUCCESS);
10520 if(tng_data->output_file)
10522 fclose(tng_data->output_file);
10525 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10526 temp = realloc(tng_data->output_file_path, len);
10529 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10530 __FILE__, __LINE__);
10531 free(tng_data->output_file_path);
10532 tng_data->output_file_path = 0;
10533 return(TNG_CRITICAL);
10535 tng_data->output_file_path = temp;
10537 strncpy(tng_data->output_file_path, file_name, len);
10539 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10540 if(!tng_data->output_file)
10542 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10543 tng_data->output_file_path, __FILE__, __LINE__);
10544 return(TNG_CRITICAL);
10546 tng_data->input_file = tng_data->output_file;
10548 return(TNG_SUCCESS);
10551 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10552 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10554 tng_endianness_32 end_32;
10555 tng_endianness_64 end_64;
10557 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10558 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10560 if(tng_data->output_endianness_swap_func_32)
10562 /* If other endianness variants are added they must be added here as well */
10563 if(tng_data->output_endianness_swap_func_32 ==
10564 &tng_swap_byte_order_big_endian_32)
10566 end_32 = TNG_BIG_ENDIAN_32;
10568 else if(tng_data->output_endianness_swap_func_32 ==
10569 &tng_swap_byte_order_little_endian_32)
10571 end_32 = TNG_LITTLE_ENDIAN_32;
10575 return(TNG_FAILURE);
10580 end_32 = (tng_endianness_32)tng_data->endianness_32;
10583 if(tng_data->output_endianness_swap_func_64)
10585 /* If other endianness variants are added they must be added here as well */
10586 if(tng_data->output_endianness_swap_func_64 ==
10587 &tng_swap_byte_order_big_endian_64)
10589 end_64 = TNG_BIG_ENDIAN_64;
10591 else if(tng_data->output_endianness_swap_func_64 ==
10592 &tng_swap_byte_order_little_endian_64)
10594 end_64 = TNG_LITTLE_ENDIAN_64;
10598 return(TNG_FAILURE);
10603 end_64 = (tng_endianness_64)tng_data->endianness_64;
10606 if((int)end_32 != (int)end_64)
10608 return(TNG_FAILURE);
10611 if(end_32 == TNG_LITTLE_ENDIAN_32)
10613 *endianness = TNG_LITTLE_ENDIAN;
10616 else if(end_32 == TNG_BIG_ENDIAN_32)
10618 *endianness = TNG_BIG_ENDIAN;
10622 return(TNG_FAILURE);
10625 return(TNG_SUCCESS);
10628 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10629 (tng_trajectory_t tng_data,
10630 const tng_file_endianness endianness)
10632 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10634 /* Tne endianness cannot be changed if the data has already been written
10635 * to the output file. */
10636 if(ftello(tng_data->output_file) > 0)
10638 return(TNG_FAILURE);
10641 if(endianness == TNG_BIG_ENDIAN)
10643 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10645 tng_data->output_endianness_swap_func_32 = 0;
10649 tng_data->output_endianness_swap_func_32 =
10650 &tng_swap_byte_order_big_endian_32;
10652 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10654 tng_data->output_endianness_swap_func_64 = 0;
10658 tng_data->output_endianness_swap_func_64 =
10659 &tng_swap_byte_order_big_endian_64;
10661 return(TNG_SUCCESS);
10663 else if(endianness == TNG_LITTLE_ENDIAN)
10665 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10667 tng_data->output_endianness_swap_func_32 = 0;
10671 tng_data->output_endianness_swap_func_32 =
10672 &tng_swap_byte_order_little_endian_32;
10674 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10676 tng_data->output_endianness_swap_func_64 = 0;
10680 tng_data->output_endianness_swap_func_64 =
10681 &tng_swap_byte_order_little_endian_64;
10683 return(TNG_SUCCESS);
10686 /* If the specified endianness is neither big nor little endian return a
10688 return(TNG_FAILURE);
10691 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10692 (const tng_trajectory_t tng_data,
10693 char *name, const int max_len)
10695 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10696 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10698 strncpy(name, tng_data->first_program_name, max_len - 1);
10699 name[max_len - 1] = 0;
10701 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10703 return(TNG_FAILURE);
10705 return(TNG_SUCCESS);
10708 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10709 const char *new_name)
10713 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10714 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10716 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10718 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10720 free(tng_data->first_program_name);
10721 tng_data->first_program_name = 0;
10723 if(!tng_data->first_program_name)
10725 tng_data->first_program_name = malloc(len);
10726 if(!tng_data->first_program_name)
10728 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10729 __FILE__, __LINE__);
10730 return(TNG_CRITICAL);
10734 strncpy(tng_data->first_program_name, new_name, len);
10736 return(TNG_SUCCESS);
10739 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10740 (const tng_trajectory_t tng_data,
10741 char *name, const int max_len)
10743 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10744 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10746 strncpy(name, tng_data->last_program_name, max_len - 1);
10747 name[max_len - 1] = 0;
10749 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10751 return(TNG_FAILURE);
10753 return(TNG_SUCCESS);
10756 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10757 (tng_trajectory_t tng_data,
10758 const char *new_name)
10762 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10763 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10765 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10767 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10769 free(tng_data->last_program_name);
10770 tng_data->last_program_name = 0;
10772 if(!tng_data->last_program_name)
10774 tng_data->last_program_name = malloc(len);
10775 if(!tng_data->last_program_name)
10777 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10778 __FILE__, __LINE__);
10779 return(TNG_CRITICAL);
10783 strncpy(tng_data->last_program_name, new_name, len);
10785 return(TNG_SUCCESS);
10788 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10789 (const tng_trajectory_t tng_data,
10790 char *name, const int max_len)
10792 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10793 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10795 strncpy(name, tng_data->first_user_name, max_len - 1);
10796 name[max_len - 1] = 0;
10798 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10800 return(TNG_FAILURE);
10802 return(TNG_SUCCESS);
10805 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10806 (tng_trajectory_t tng_data,
10807 const char *new_name)
10811 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10812 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10814 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10816 /* If the currently stored string length is not enough to store the new
10817 * string it is freed and reallocated. */
10818 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10820 free(tng_data->first_user_name);
10821 tng_data->first_user_name = 0;
10823 if(!tng_data->first_user_name)
10825 tng_data->first_user_name = malloc(len);
10826 if(!tng_data->first_user_name)
10828 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10829 __FILE__, __LINE__);
10830 return(TNG_CRITICAL);
10834 strncpy(tng_data->first_user_name, new_name, len);
10836 return(TNG_SUCCESS);
10839 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10840 (const tng_trajectory_t tng_data,
10841 char *name, const int max_len)
10843 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10844 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10846 strncpy(name, tng_data->last_user_name, max_len - 1);
10847 name[max_len - 1] = 0;
10849 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10851 return(TNG_FAILURE);
10853 return(TNG_SUCCESS);
10856 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10857 (tng_trajectory_t tng_data,
10858 const char *new_name)
10862 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10863 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10865 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10867 /* If the currently stored string length is not enough to store the new
10868 * string it is freed and reallocated. */
10869 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10871 free(tng_data->last_user_name);
10872 tng_data->last_user_name = 0;
10874 if(!tng_data->last_user_name)
10876 tng_data->last_user_name = malloc(len);
10877 if(!tng_data->last_user_name)
10879 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10880 __FILE__, __LINE__);
10881 return(TNG_CRITICAL);
10885 strncpy(tng_data->last_user_name, new_name, len);
10887 return(TNG_SUCCESS);
10890 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10891 (const tng_trajectory_t tng_data,
10892 char *name, const int max_len)
10894 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10895 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10897 strncpy(name, tng_data->first_computer_name, max_len - 1);
10898 name[max_len - 1] = 0;
10900 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10902 return(TNG_FAILURE);
10904 return(TNG_SUCCESS);
10907 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10908 (tng_trajectory_t tng_data,
10909 const char *new_name)
10913 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10914 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10916 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10918 /* If the currently stored string length is not enough to store the new
10919 * string it is freed and reallocated. */
10920 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10922 free(tng_data->first_computer_name);
10923 tng_data->first_computer_name = 0;
10925 if(!tng_data->first_computer_name)
10927 tng_data->first_computer_name = malloc(len);
10928 if(!tng_data->first_computer_name)
10930 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10931 __FILE__, __LINE__);
10932 return(TNG_CRITICAL);
10936 strncpy(tng_data->first_computer_name, new_name, len);
10938 return(TNG_SUCCESS);
10941 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10942 (const tng_trajectory_t tng_data,
10943 char *name, const int max_len)
10945 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10946 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10948 strncpy(name, tng_data->last_computer_name, max_len - 1);
10949 name[max_len - 1] = 0;
10951 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10953 return(TNG_FAILURE);
10955 return(TNG_SUCCESS);
10958 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10959 (tng_trajectory_t tng_data,
10960 const char *new_name)
10964 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10965 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10967 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10969 /* If the currently stored string length is not enough to store the new
10970 * string it is freed and reallocated. */
10971 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10974 free(tng_data->last_computer_name);
10975 tng_data->last_computer_name = 0;
10977 if(!tng_data->last_computer_name)
10979 tng_data->last_computer_name = malloc(len);
10980 if(!tng_data->last_computer_name)
10982 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10983 __FILE__, __LINE__);
10984 return(TNG_CRITICAL);
10988 strncpy(tng_data->last_computer_name, new_name, len);
10990 return(TNG_SUCCESS);
10993 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10994 (const tng_trajectory_t tng_data,
10995 char *signature, const int max_len)
10997 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10998 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11000 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
11001 signature[max_len - 1] = 0;
11003 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
11005 return(TNG_FAILURE);
11007 return(TNG_SUCCESS);
11010 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
11011 (tng_trajectory_t tng_data,
11012 const char *signature)
11016 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11017 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11019 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11021 /* If the currently stored string length is not enough to store the new
11022 * string it is freed and reallocated. */
11023 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
11026 free(tng_data->first_pgp_signature);
11027 tng_data->first_pgp_signature = 0;
11029 if(!tng_data->first_pgp_signature)
11031 tng_data->first_pgp_signature = malloc(len);
11032 if(!tng_data->first_pgp_signature)
11034 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11035 __FILE__, __LINE__);
11036 return(TNG_CRITICAL);
11040 strncpy(tng_data->first_pgp_signature, signature, len);
11042 return(TNG_SUCCESS);
11045 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11046 (const tng_trajectory_t tng_data,
11047 char *signature, const int max_len)
11049 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11050 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11052 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
11053 signature[max_len - 1] = 0;
11055 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
11057 return(TNG_FAILURE);
11059 return(TNG_SUCCESS);
11062 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11063 (tng_trajectory_t tng_data,
11064 const char *signature)
11068 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11069 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11071 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11073 /* If the currently stored string length is not enough to store the new
11074 * string it is freed and reallocated. */
11075 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
11078 free(tng_data->last_pgp_signature);
11079 tng_data->last_pgp_signature = 0;
11081 if(!tng_data->last_pgp_signature)
11083 tng_data->last_pgp_signature = malloc(len);
11084 if(!tng_data->last_pgp_signature)
11086 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11087 __FILE__, __LINE__);
11088 return(TNG_CRITICAL);
11092 strncpy(tng_data->last_pgp_signature, signature, len);
11094 return(TNG_SUCCESS);
11097 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11098 (const tng_trajectory_t tng_data,
11099 char *name, const int max_len)
11101 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11102 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11104 strncpy(name, tng_data->forcefield_name, max_len - 1);
11105 name[max_len - 1] = 0;
11107 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11109 return(TNG_FAILURE);
11111 return(TNG_SUCCESS);
11114 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11115 (tng_trajectory_t tng_data,
11116 const char *new_name)
11120 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11121 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11123 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11125 /* If the currently stored string length is not enough to store the new
11126 * string it is freed and reallocated. */
11127 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11129 free(tng_data->forcefield_name);
11130 tng_data->forcefield_name = 0;
11132 if(!tng_data->forcefield_name)
11134 tng_data->forcefield_name = malloc(len);
11135 if(!tng_data->forcefield_name)
11137 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11138 __FILE__, __LINE__);
11139 return(TNG_CRITICAL);
11143 strncpy(tng_data->forcefield_name, new_name, len);
11145 return(TNG_SUCCESS);
11148 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11149 (const tng_trajectory_t tng_data,
11152 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11153 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11155 *len = tng_data->medium_stride_length;
11157 return(TNG_SUCCESS);
11160 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11161 (tng_trajectory_t tng_data,
11164 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11166 if(len >= tng_data->long_stride_length)
11168 return(TNG_FAILURE);
11170 tng_data->medium_stride_length = len;
11172 return(TNG_SUCCESS);
11175 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11176 (const tng_trajectory_t tng_data,
11179 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11180 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11182 *len = tng_data->long_stride_length;
11184 return(TNG_SUCCESS);
11187 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11188 (tng_trajectory_t tng_data,
11191 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11193 if(len <= tng_data->medium_stride_length)
11195 return(TNG_FAILURE);
11197 tng_data->long_stride_length = len;
11199 return(TNG_SUCCESS);
11202 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11203 (const tng_trajectory_t tng_data,
11206 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11207 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11209 *time = tng_data->time_per_frame;
11211 return(TNG_SUCCESS);
11214 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11215 (tng_trajectory_t tng_data,
11218 tng_trajectory_frame_set_t frame_set;
11220 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11221 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11223 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11225 return(TNG_SUCCESS);
11228 frame_set = &tng_data->current_trajectory_frame_set;
11230 /* If the current frame set is not finished write it to disk before
11231 changing time per frame. */
11232 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11234 frame_set->n_frames = frame_set->n_unwritten_frames;
11235 tng_frame_set_write(tng_data, TNG_USE_HASH);
11237 tng_data->time_per_frame = time;
11239 return(TNG_SUCCESS);
11242 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11243 (const tng_trajectory_t tng_data,
11246 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11247 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11249 *len = tng_data->input_file_len;
11251 return(TNG_SUCCESS);
11254 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11255 (const tng_trajectory_t tng_data,
11258 tng_gen_block_t block;
11259 tng_function_status stat;
11260 int64_t file_pos, last_file_pos, first_frame, n_frames;
11262 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11263 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11264 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11266 file_pos = ftello(tng_data->input_file);
11267 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11269 if(last_file_pos <= 0)
11271 return(TNG_FAILURE);
11274 tng_block_init(&block);
11275 fseeko(tng_data->input_file,
11278 /* Read block headers first to see that a frame set block is found. */
11279 stat = tng_block_header_read(tng_data, block);
11280 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11282 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11283 __FILE__, __LINE__);
11284 tng_block_destroy(&block);
11285 return(TNG_FAILURE);
11287 tng_block_destroy(&block);
11289 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11291 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11292 __FILE__, __LINE__);
11293 return(TNG_CRITICAL);
11295 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11297 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11298 __FILE__, __LINE__);
11299 return(TNG_CRITICAL);
11301 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11303 *n = first_frame + n_frames;
11305 return(TNG_SUCCESS);
11308 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11309 (const tng_trajectory_t tng_data,
11312 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11314 *precision = tng_data->compression_precision;
11316 return(TNG_SUCCESS);
11319 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11320 (tng_trajectory_t tng_data,
11321 const double precision)
11323 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11325 tng_data->compression_precision = precision;
11327 return(TNG_SUCCESS);
11330 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11331 (tng_trajectory_t tng_data,
11334 tng_molecule_t mol;
11338 tng_function_status stat;
11339 int64_t diff, n_mod, n_impl;
11341 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11343 diff = n - tng_data->n_particles;
11345 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11346 if(stat == TNG_SUCCESS)
11348 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11350 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11351 __FILE__, __LINE__);
11352 return(TNG_FAILURE);
11354 diff -= n_impl * mol->n_atoms;
11359 if(stat == TNG_SUCCESS)
11361 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11364 return(TNG_SUCCESS);
11368 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11369 fprintf(stderr, "particle count.\n");
11370 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11371 __FILE__, __LINE__);
11372 /* FIXME: Should we set the count of all other molecules to 0 and add
11373 * implicit molecules? */
11374 return(TNG_FAILURE);
11376 if(stat != TNG_SUCCESS)
11378 stat = tng_molecule_add(tng_data,
11379 "TNG_IMPLICIT_MOL",
11381 if(stat != TNG_SUCCESS)
11385 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11386 if(stat != TNG_SUCCESS)
11390 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11391 if(stat != TNG_SUCCESS)
11395 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11396 if(stat != TNG_SUCCESS)
11403 if(mol->n_atoms > 1)
11405 n_mod = diff % mol->n_atoms;
11408 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11409 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11410 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11411 __FILE__, __LINE__);
11412 return(TNG_FAILURE);
11414 diff /= mol->n_atoms;
11417 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11422 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11423 (const tng_trajectory_t tng_data,
11426 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11427 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11429 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11431 *n = tng_data->n_particles;
11435 *n = tng_data->current_trajectory_frame_set.n_particles;
11438 return(TNG_SUCCESS);
11441 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11442 (const tng_trajectory_t tng_data,
11445 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11446 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11448 *variable = tng_data->var_num_atoms_flag;
11450 return(TNG_SUCCESS);
11453 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11454 (const tng_trajectory_t tng_data,
11457 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11458 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11460 *n = tng_data->n_molecules;
11462 return(TNG_SUCCESS);
11465 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11466 (const tng_trajectory_t tng_data,
11469 int64_t *cnt_list = 0, cnt = 0, i;
11471 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11472 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11474 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11478 return(TNG_FAILURE);
11481 for(i = 0; i < tng_data->n_molecules; i++)
11483 cnt += cnt_list[i];
11488 return(TNG_SUCCESS);
11491 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11492 (const tng_trajectory_t tng_data,
11493 int64_t **mol_cnt_list)
11495 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11497 if(tng_data->var_num_atoms_flag)
11499 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11504 *mol_cnt_list = tng_data->molecule_cnt_list;
11506 if(*mol_cnt_list == 0)
11508 return(TNG_FAILURE);
11510 return(TNG_SUCCESS);
11513 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11514 (const tng_trajectory_t tng_data,
11517 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11518 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11520 *exp = tng_data->distance_unit_exponential;
11522 return(TNG_SUCCESS);
11525 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11526 (const tng_trajectory_t tng_data,
11529 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11531 tng_data->distance_unit_exponential = exp;
11533 return(TNG_SUCCESS);
11536 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11537 (const tng_trajectory_t tng_data,
11540 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11541 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11543 *n = tng_data->frame_set_n_frames;
11545 return(TNG_SUCCESS);
11548 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11549 (const tng_trajectory_t tng_data,
11552 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11554 tng_data->frame_set_n_frames = n;
11556 return(TNG_SUCCESS);
11559 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11560 (const tng_trajectory_t tng_data,
11563 int64_t long_stride_length, medium_stride_length;
11564 int64_t file_pos, orig_frame_set_file_pos;
11565 tng_trajectory_frame_set_t frame_set;
11566 struct tng_trajectory_frame_set orig_frame_set;
11567 tng_gen_block_t block;
11568 tng_function_status stat;
11571 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11572 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11574 orig_frame_set = tng_data->current_trajectory_frame_set;
11576 frame_set = &tng_data->current_trajectory_frame_set;
11578 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11579 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11583 *n = tng_data->n_trajectory_frame_sets = cnt;
11584 return(TNG_SUCCESS);
11587 tng_block_init(&block);
11588 fseeko(tng_data->input_file,
11591 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11592 /* Read block headers first to see what block is found. */
11593 stat = tng_block_header_read(tng_data, block);
11594 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11596 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11597 __FILE__, __LINE__);
11598 tng_block_destroy(&block);
11599 return(TNG_CRITICAL);
11602 if(tng_block_read_next(tng_data, block,
11603 TNG_SKIP_HASH) != TNG_SUCCESS)
11605 tng_block_destroy(&block);
11606 return(TNG_CRITICAL);
11611 long_stride_length = tng_data->long_stride_length;
11612 medium_stride_length = tng_data->medium_stride_length;
11614 /* Take long steps forward until a long step forward would be too long or
11615 * the last frame set is found */
11616 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11617 while(file_pos > 0)
11621 cnt += long_stride_length;
11622 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11623 /* Read block headers first to see what block is found. */
11624 stat = tng_block_header_read(tng_data, block);
11625 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11627 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11628 file_pos, __FILE__, __LINE__);
11629 tng_block_destroy(&block);
11630 return(TNG_CRITICAL);
11633 if(tng_block_read_next(tng_data, block,
11634 TNG_SKIP_HASH) != TNG_SUCCESS)
11636 tng_block_destroy(&block);
11637 return(TNG_CRITICAL);
11640 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11643 /* Take medium steps forward until a medium step forward would be too long
11644 * or the last frame set is found */
11645 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11646 while(file_pos > 0)
11650 cnt += medium_stride_length;
11651 fseeko(tng_data->input_file,
11654 /* Read block headers first to see what block is found. */
11655 stat = tng_block_header_read(tng_data, block);
11656 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11658 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11659 file_pos, __FILE__, __LINE__);
11660 tng_block_destroy(&block);
11661 return(TNG_CRITICAL);
11664 if(tng_block_read_next(tng_data, block,
11665 TNG_SKIP_HASH) != TNG_SUCCESS)
11667 tng_block_destroy(&block);
11668 return(TNG_CRITICAL);
11671 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11674 /* Take one step forward until the last frame set is found */
11675 file_pos = frame_set->next_frame_set_file_pos;
11676 while(file_pos > 0)
11681 fseeko(tng_data->input_file,
11684 /* Read block headers first to see what block is found. */
11685 stat = tng_block_header_read(tng_data, block);
11686 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11688 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11689 file_pos, __FILE__, __LINE__);
11690 tng_block_destroy(&block);
11691 return(TNG_CRITICAL);
11694 if(tng_block_read_next(tng_data, block,
11695 TNG_SKIP_HASH) != TNG_SUCCESS)
11697 tng_block_destroy(&block);
11698 return(TNG_CRITICAL);
11701 file_pos = frame_set->next_frame_set_file_pos;
11704 tng_block_destroy(&block);
11706 *n = tng_data->n_trajectory_frame_sets = cnt;
11708 *frame_set = orig_frame_set;
11709 /* The mapping block in the original frame set has been freed when reading
11710 * other frame sets. */
11711 frame_set->mappings = 0;
11712 frame_set->n_mapping_blocks = 0;
11714 fseeko(tng_data->input_file,
11715 tng_data->first_trajectory_frame_set_input_file_pos,
11718 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11720 return(TNG_SUCCESS);
11723 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11724 (const tng_trajectory_t tng_data,
11725 tng_trajectory_frame_set_t *frame_set_p)
11727 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11729 *frame_set_p = &tng_data->current_trajectory_frame_set;
11731 return(TNG_SUCCESS);
11734 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11735 (tng_trajectory_t tng_data,
11738 int64_t long_stride_length, medium_stride_length;
11739 int64_t file_pos, curr_nr = 0, n_frame_sets;
11740 tng_trajectory_frame_set_t frame_set;
11741 tng_gen_block_t block;
11742 tng_function_status stat;
11744 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11745 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11747 frame_set = &tng_data->current_trajectory_frame_set;
11749 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11751 if(stat != TNG_SUCCESS)
11756 if(nr >= n_frame_sets)
11758 return(TNG_FAILURE);
11761 long_stride_length = tng_data->long_stride_length;
11762 medium_stride_length = tng_data->medium_stride_length;
11764 /* FIXME: The frame set number of the current frame set is not stored */
11766 if(nr < n_frame_sets - 1 - nr)
11768 /* Start from the beginning */
11769 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11773 /* Start from the end */
11774 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11775 curr_nr = n_frame_sets - 1;
11779 return(TNG_FAILURE);
11782 tng_block_init(&block);
11783 fseeko(tng_data->input_file,
11786 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11787 /* Read block headers first to see what block is found. */
11788 stat = tng_block_header_read(tng_data, block);
11789 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11791 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11792 __FILE__, __LINE__);
11793 tng_block_destroy(&block);
11794 return(TNG_CRITICAL);
11797 if(tng_block_read_next(tng_data, block,
11798 TNG_SKIP_HASH) != TNG_SUCCESS)
11800 tng_block_destroy(&block);
11801 return(TNG_CRITICAL);
11806 tng_block_destroy(&block);
11807 return(TNG_SUCCESS);
11810 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11812 /* Take long steps forward until a long step forward would be too long or
11813 * the right frame set is found */
11814 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11816 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11819 curr_nr += long_stride_length;
11820 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11821 /* Read block headers first to see what block is found. */
11822 stat = tng_block_header_read(tng_data, block);
11823 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11825 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11826 file_pos, __FILE__, __LINE__);
11827 tng_block_destroy(&block);
11828 return(TNG_CRITICAL);
11831 if(tng_block_read_next(tng_data, block,
11832 TNG_SKIP_HASH) != TNG_SUCCESS)
11834 tng_block_destroy(&block);
11835 return(TNG_CRITICAL);
11839 tng_block_destroy(&block);
11840 return(TNG_SUCCESS);
11845 /* Take medium steps forward until a medium step forward would be too long
11846 * or the right frame set is found */
11847 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11849 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11852 curr_nr += medium_stride_length;
11853 fseeko(tng_data->input_file,
11856 /* Read block headers first to see what block is found. */
11857 stat = tng_block_header_read(tng_data, block);
11858 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11860 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11861 file_pos, __FILE__, __LINE__);
11862 tng_block_destroy(&block);
11863 return(TNG_CRITICAL);
11866 if(tng_block_read_next(tng_data, block,
11867 TNG_SKIP_HASH) != TNG_SUCCESS)
11869 tng_block_destroy(&block);
11870 return(TNG_CRITICAL);
11874 tng_block_destroy(&block);
11875 return(TNG_SUCCESS);
11880 /* Take one step forward until the right frame set is found */
11881 while(file_pos > 0 && curr_nr < nr)
11883 file_pos = frame_set->next_frame_set_file_pos;
11888 fseeko(tng_data->input_file,
11891 /* Read block headers first to see what block is found. */
11892 stat = tng_block_header_read(tng_data, block);
11893 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11895 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11896 file_pos, __FILE__, __LINE__);
11897 tng_block_destroy(&block);
11898 return(TNG_CRITICAL);
11901 if(tng_block_read_next(tng_data, block,
11902 TNG_SKIP_HASH) != TNG_SUCCESS)
11904 tng_block_destroy(&block);
11905 return(TNG_CRITICAL);
11909 tng_block_destroy(&block);
11910 return(TNG_SUCCESS);
11915 /* Take long steps backward until a long step backward would be too long
11916 * or the right frame set is found */
11917 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11919 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11922 curr_nr -= long_stride_length;
11923 fseeko(tng_data->input_file,
11926 /* Read block headers first to see what block is found. */
11927 stat = tng_block_header_read(tng_data, block);
11928 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11930 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11931 file_pos, __FILE__, __LINE__);
11932 tng_block_destroy(&block);
11933 return(TNG_CRITICAL);
11936 if(tng_block_read_next(tng_data, block,
11937 TNG_SKIP_HASH) != TNG_SUCCESS)
11939 tng_block_destroy(&block);
11940 return(TNG_CRITICAL);
11944 tng_block_destroy(&block);
11945 return(TNG_SUCCESS);
11950 /* Take medium steps backward until a medium step backward would be too long
11951 * or the right frame set is found */
11952 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11954 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11957 curr_nr -= medium_stride_length;
11958 fseeko(tng_data->input_file,
11961 /* Read block headers first to see what block is found. */
11962 stat = tng_block_header_read(tng_data, block);
11963 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11965 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11966 file_pos, __FILE__, __LINE__);
11967 tng_block_destroy(&block);
11968 return(TNG_CRITICAL);
11971 if(tng_block_read_next(tng_data, block,
11972 TNG_SKIP_HASH) != TNG_SUCCESS)
11974 tng_block_destroy(&block);
11975 return(TNG_CRITICAL);
11979 tng_block_destroy(&block);
11980 return(TNG_SUCCESS);
11985 /* Take one step backward until the right frame set is found */
11986 while(file_pos > 0 && curr_nr > nr)
11988 file_pos = frame_set->prev_frame_set_file_pos;
11992 fseeko(tng_data->input_file,
11995 /* Read block headers first to see what block is found. */
11996 stat = tng_block_header_read(tng_data, block);
11997 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11999 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12000 file_pos, __FILE__, __LINE__);
12001 tng_block_destroy(&block);
12002 return(TNG_CRITICAL);
12005 if(tng_block_read_next(tng_data, block,
12006 TNG_SKIP_HASH) != TNG_SUCCESS)
12008 tng_block_destroy(&block);
12009 return(TNG_CRITICAL);
12013 tng_block_destroy(&block);
12014 return(TNG_SUCCESS);
12019 /* If for some reason the current frame set is not yet found,
12020 * take one step forward until the right frame set is found */
12021 while(file_pos > 0 && curr_nr < nr)
12023 file_pos = frame_set->next_frame_set_file_pos;
12027 fseeko(tng_data->input_file,
12030 /* Read block headers first to see what block is found. */
12031 stat = tng_block_header_read(tng_data, block);
12032 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12034 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12035 file_pos, __FILE__, __LINE__);
12036 tng_block_destroy(&block);
12037 return(TNG_CRITICAL);
12040 if(tng_block_read_next(tng_data, block,
12041 TNG_SKIP_HASH) != TNG_SUCCESS)
12043 tng_block_destroy(&block);
12044 return(TNG_CRITICAL);
12048 tng_block_destroy(&block);
12049 return(TNG_SUCCESS);
12054 tng_block_destroy(&block);
12055 return(TNG_FAILURE);
12058 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12059 (tng_trajectory_t tng_data,
12060 const int64_t frame)
12062 int64_t first_frame, last_frame, n_frames_per_frame_set;
12063 int64_t long_stride_length, medium_stride_length;
12064 int64_t file_pos, temp_frame, n_frames;
12065 tng_trajectory_frame_set_t frame_set;
12066 tng_gen_block_t block;
12067 tng_function_status stat;
12069 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12070 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
12072 frame_set = &tng_data->current_trajectory_frame_set;
12074 tng_block_init(&block);
12076 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
12078 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12079 fseeko(tng_data->input_file,
12082 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12083 /* Read block headers first to see what block is found. */
12084 stat = tng_block_header_read(tng_data, block);
12085 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12087 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12088 file_pos, __FILE__, __LINE__);
12089 tng_block_destroy(&block);
12090 return(TNG_CRITICAL);
12093 if(tng_block_read_next(tng_data, block,
12094 TNG_SKIP_HASH) != TNG_SUCCESS)
12096 tng_block_destroy(&block);
12097 return(TNG_CRITICAL);
12101 first_frame = tng_max_i64(frame_set->first_frame, 0);
12102 last_frame = first_frame + frame_set->n_frames - 1;
12103 /* Is this the right frame set? */
12104 if(first_frame <= frame && frame <= last_frame)
12106 tng_block_destroy(&block);
12107 return(TNG_SUCCESS);
12110 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12111 long_stride_length = tng_data->long_stride_length;
12112 medium_stride_length = tng_data->medium_stride_length;
12114 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12117 if(temp_frame - first_frame > n_frames_per_frame_set)
12119 n_frames_per_frame_set = temp_frame - first_frame;
12123 tng_num_frames_get(tng_data, &n_frames);
12125 if(frame >= n_frames)
12127 tng_block_destroy(&block);
12128 return(TNG_FAILURE);
12131 if(first_frame - frame >= frame ||
12132 frame - last_frame >
12133 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12135 /* Start from the beginning */
12136 if(first_frame - frame >= frame)
12138 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12142 tng_block_destroy(&block);
12143 return(TNG_FAILURE);
12146 /* Start from the end */
12147 else if(frame - first_frame > (n_frames - 1) - frame)
12149 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12151 /* If the last frame set position is not set start from the current
12152 * frame set, since it will be closer than the first frame set. */
12154 /* Start from current */
12157 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12162 fseeko(tng_data->input_file,
12165 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12166 /* Read block headers first to see what block is found. */
12167 stat = tng_block_header_read(tng_data, block);
12168 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12170 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12171 file_pos, __FILE__, __LINE__);
12172 tng_block_destroy(&block);
12173 return(TNG_CRITICAL);
12176 if(tng_block_read_next(tng_data, block,
12177 TNG_SKIP_HASH) != TNG_SUCCESS)
12179 tng_block_destroy(&block);
12180 return(TNG_CRITICAL);
12185 first_frame = tng_max_i64(frame_set->first_frame, 0);
12186 last_frame = first_frame + frame_set->n_frames - 1;
12188 if(frame >= first_frame && frame <= last_frame)
12190 tng_block_destroy(&block);
12191 return(TNG_SUCCESS);
12194 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12196 /* Take long steps forward until a long step forward would be too long or
12197 * the right frame set is found */
12198 while(file_pos > 0 && first_frame + long_stride_length *
12199 n_frames_per_frame_set <= frame)
12201 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12204 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12205 /* Read block headers first to see what block is found. */
12206 stat = tng_block_header_read(tng_data, block);
12207 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12209 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12210 file_pos, __FILE__, __LINE__);
12211 tng_block_destroy(&block);
12212 return(TNG_CRITICAL);
12215 if(tng_block_read_next(tng_data, block,
12216 TNG_SKIP_HASH) != TNG_SUCCESS)
12218 tng_block_destroy(&block);
12219 return(TNG_CRITICAL);
12222 first_frame = tng_max_i64(frame_set->first_frame, 0);
12223 last_frame = first_frame + frame_set->n_frames - 1;
12224 if(frame >= first_frame && frame <= last_frame)
12226 tng_block_destroy(&block);
12227 return(TNG_SUCCESS);
12231 /* Take medium steps forward until a medium step forward would be too long
12232 * or the right frame set is found */
12233 while(file_pos > 0 && first_frame + medium_stride_length *
12234 n_frames_per_frame_set <= frame)
12236 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12239 fseeko(tng_data->input_file,
12242 /* Read block headers first to see what block is found. */
12243 stat = tng_block_header_read(tng_data, block);
12244 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12246 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12247 file_pos, __FILE__, __LINE__);
12248 tng_block_destroy(&block);
12249 return(TNG_CRITICAL);
12252 if(tng_block_read_next(tng_data, block,
12253 TNG_SKIP_HASH) != TNG_SUCCESS)
12255 tng_block_destroy(&block);
12256 return(TNG_CRITICAL);
12259 first_frame = tng_max_i64(frame_set->first_frame, 0);
12260 last_frame = first_frame + frame_set->n_frames - 1;
12261 if(frame >= first_frame && frame <= last_frame)
12263 tng_block_destroy(&block);
12264 return(TNG_SUCCESS);
12268 /* Take one step forward until the right frame set is found */
12269 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12271 file_pos = frame_set->next_frame_set_file_pos;
12274 fseeko(tng_data->input_file,
12277 /* Read block headers first to see what block is found. */
12278 stat = tng_block_header_read(tng_data, block);
12279 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12281 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12282 file_pos, __FILE__, __LINE__);
12283 tng_block_destroy(&block);
12284 return(TNG_CRITICAL);
12287 if(tng_block_read_next(tng_data, block,
12288 TNG_SKIP_HASH) != TNG_SUCCESS)
12290 tng_block_destroy(&block);
12291 return(TNG_CRITICAL);
12294 first_frame = tng_max_i64(frame_set->first_frame, 0);
12295 last_frame = first_frame + frame_set->n_frames - 1;
12296 if(frame >= first_frame && frame <= last_frame)
12298 tng_block_destroy(&block);
12299 return(TNG_SUCCESS);
12303 /* Take long steps backward until a long step backward would be too long
12304 * or the right frame set is found */
12305 while(file_pos > 0 && first_frame - long_stride_length *
12306 n_frames_per_frame_set >= frame)
12308 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12311 fseeko(tng_data->input_file,
12314 /* Read block headers first to see what block is found. */
12315 stat = tng_block_header_read(tng_data, block);
12316 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12318 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12319 file_pos, __FILE__, __LINE__);
12320 tng_block_destroy(&block);
12321 return(TNG_CRITICAL);
12324 if(tng_block_read_next(tng_data, block,
12325 TNG_SKIP_HASH) != TNG_SUCCESS)
12327 tng_block_destroy(&block);
12328 return(TNG_CRITICAL);
12331 first_frame = tng_max_i64(frame_set->first_frame, 0);
12332 last_frame = first_frame + frame_set->n_frames - 1;
12333 if(frame >= first_frame && frame <= last_frame)
12335 tng_block_destroy(&block);
12336 return(TNG_SUCCESS);
12340 /* Take medium steps backward until a medium step backward would be too long
12341 * or the right frame set is found */
12342 while(file_pos > 0 && first_frame - medium_stride_length *
12343 n_frames_per_frame_set >= frame)
12345 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12348 fseeko(tng_data->input_file,
12351 /* Read block headers first to see what block is found. */
12352 stat = tng_block_header_read(tng_data, block);
12353 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12355 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12356 file_pos, __FILE__, __LINE__);
12357 tng_block_destroy(&block);
12358 return(TNG_CRITICAL);
12361 if(tng_block_read_next(tng_data, block,
12362 TNG_SKIP_HASH) != TNG_SUCCESS)
12364 tng_block_destroy(&block);
12365 return(TNG_CRITICAL);
12368 first_frame = tng_max_i64(frame_set->first_frame, 0);
12369 last_frame = first_frame + frame_set->n_frames - 1;
12370 if(frame >= first_frame && frame <= last_frame)
12372 tng_block_destroy(&block);
12373 return(TNG_SUCCESS);
12377 /* Take one step backward until the right frame set is found */
12378 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12380 file_pos = frame_set->prev_frame_set_file_pos;
12383 fseeko(tng_data->input_file,
12386 /* Read block headers first to see what block is found. */
12387 stat = tng_block_header_read(tng_data, block);
12388 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12390 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12391 file_pos, __FILE__, __LINE__);
12392 tng_block_destroy(&block);
12393 return(TNG_CRITICAL);
12396 if(tng_block_read_next(tng_data, block,
12397 TNG_SKIP_HASH) != TNG_SUCCESS)
12399 tng_block_destroy(&block);
12400 return(TNG_CRITICAL);
12403 first_frame = tng_max_i64(frame_set->first_frame, 0);
12404 last_frame = first_frame + frame_set->n_frames - 1;
12405 if(frame >= first_frame && frame <= last_frame)
12407 tng_block_destroy(&block);
12408 return(TNG_SUCCESS);
12412 /* If for some reason the current frame set is not yet found,
12413 * take one step forward until the right frame set is found */
12414 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12416 file_pos = frame_set->next_frame_set_file_pos;
12419 fseeko(tng_data->input_file,
12422 /* Read block headers first to see what block is found. */
12423 stat = tng_block_header_read(tng_data, block);
12424 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12426 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12427 file_pos, __FILE__, __LINE__);
12428 tng_block_destroy(&block);
12429 return(TNG_CRITICAL);
12432 if(tng_block_read_next(tng_data, block,
12433 TNG_SKIP_HASH) != TNG_SUCCESS)
12435 tng_block_destroy(&block);
12436 return(TNG_CRITICAL);
12439 first_frame = tng_max_i64(frame_set->first_frame, 0);
12440 last_frame = first_frame + frame_set->n_frames - 1;
12441 if(frame >= first_frame && frame <= last_frame)
12443 tng_block_destroy(&block);
12444 return(TNG_SUCCESS);
12448 tng_block_destroy(&block);
12449 return(TNG_FAILURE);
12452 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12453 (const tng_trajectory_t tng_data,
12454 const tng_trajectory_frame_set_t frame_set,
12459 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12460 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12462 *pos = frame_set->next_frame_set_file_pos;
12464 return(TNG_SUCCESS);
12467 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12468 (const tng_trajectory_t tng_data,
12469 const tng_trajectory_frame_set_t frame_set,
12474 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12475 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12477 *pos = frame_set->prev_frame_set_file_pos;
12479 return(TNG_SUCCESS);
12482 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12483 (const tng_trajectory_t tng_data,
12484 const tng_trajectory_frame_set_t frame_set,
12485 int64_t *first_frame,
12486 int64_t *last_frame)
12490 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12491 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12492 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12494 *first_frame = frame_set->first_frame;
12495 *last_frame = *first_frame + frame_set->n_frames - 1;
12497 return(TNG_SUCCESS);
12500 /** Translate from the particle numbering used in a frame set to the real
12501 * particle numbering - used in the molecule description.
12502 * @param frame_set is the frame_set containing the mappings to use.
12503 * @param local is the index number of the atom in this frame set
12504 * @param real is set to the index of the atom in the molecular system.
12505 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12508 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12509 (const tng_trajectory_frame_set_t frame_set,
12510 const int64_t local,
12513 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12514 tng_particle_mapping_t mapping;
12518 return(TNG_SUCCESS);
12520 for(i = 0; i < n_blocks; i++)
12522 mapping = &frame_set->mappings[i];
12523 first = mapping->num_first_particle;
12524 if(local < first ||
12525 local >= first + mapping->n_particles)
12529 *real = mapping->real_particle_numbers[local-first];
12530 return(TNG_SUCCESS);
12533 return(TNG_FAILURE);
12536 /** Translate from the real particle numbering to the particle numbering
12537 * used in a frame set.
12538 * @param frame_set is the frame_set containing the mappings to use.
12539 * @param real is the index number of the atom in the molecular system.
12540 * @param local is set to the index of the atom in this frame set.
12541 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12544 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12545 (const tng_trajectory_frame_set_t frame_set,
12546 const int64_t real,
12549 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12550 tng_particle_mapping_t mapping;
12554 return(TNG_SUCCESS);
12556 for(i = 0; i < n_blocks; i++)
12558 mapping = &frame_set->mappings[i];
12559 for(j = mapping->n_particles; j--;)
12561 if(mapping->real_particle_numbers[j] == real)
12564 return(TNG_SUCCESS);
12568 return(TNG_FAILURE);
12572 static tng_function_status tng_file_headers_len_get
12573 (tng_trajectory_t tng_data,
12577 tng_gen_block_t block;
12579 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12581 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12583 return(TNG_CRITICAL);
12588 orig_pos = ftello(tng_data->input_file);
12590 if(!tng_data->input_file_len)
12592 fseeko(tng_data->input_file, 0, SEEK_END);
12593 tng_data->input_file_len = ftello(tng_data->input_file);
12595 fseeko(tng_data->input_file, 0, SEEK_SET);
12597 tng_block_init(&block);
12598 /* Read through the headers of non-trajectory blocks (they come before the
12599 * trajectory blocks in the file) */
12600 while (*len < tng_data->input_file_len &&
12601 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12603 block->id != TNG_TRAJECTORY_FRAME_SET)
12605 *len += block->header_contents_size + block->block_contents_size;
12606 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12609 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
12611 tng_block_destroy(&block);
12613 return(TNG_SUCCESS);
12616 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12617 (tng_trajectory_t tng_data,
12618 const char hash_mode)
12620 int64_t prev_pos = 0;
12621 tng_gen_block_t block;
12623 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12625 tng_data->n_trajectory_frame_sets = 0;
12627 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12629 return(TNG_CRITICAL);
12632 if(!tng_data->input_file_len)
12634 fseeko(tng_data->input_file, 0, SEEK_END);
12635 tng_data->input_file_len = ftello(tng_data->input_file);
12637 fseeko(tng_data->input_file, 0, SEEK_SET);
12639 tng_block_init(&block);
12640 /* Non trajectory blocks (they come before the trajectory
12641 * blocks in the file) */
12642 while (prev_pos < tng_data->input_file_len &&
12643 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12645 block->id != TNG_TRAJECTORY_FRAME_SET)
12647 tng_block_read_next(tng_data, block, hash_mode);
12648 prev_pos = ftello(tng_data->input_file);
12651 /* Go back if a trajectory block was encountered */
12652 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12654 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
12657 tng_block_destroy(&block);
12659 return(TNG_SUCCESS);
12662 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12663 (tng_trajectory_t tng_data,
12664 const char hash_mode)
12667 int64_t len, orig_len, tot_len = 0, data_start_pos;
12668 tng_function_status stat;
12669 tng_gen_block_t block;
12671 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12673 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12675 return(TNG_CRITICAL);
12678 if(tng_data->n_trajectory_frame_sets > 0)
12680 stat = tng_file_headers_len_get(tng_data, &orig_len);
12681 if(stat != TNG_SUCCESS)
12686 tng_block_init(&block);
12687 block->name = malloc(TNG_MAX_STR_LEN);
12690 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12691 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12692 tng_block_destroy(&block);
12693 return(TNG_CRITICAL);
12695 strcpy(block->name, "GENERAL INFO");
12696 tng_block_header_len_calculate(tng_data, block, &len);
12698 tng_general_info_block_len_calculate(tng_data, &len);
12700 strcpy(block->name, "MOLECULES");
12701 tng_block_header_len_calculate(tng_data, block, &len);
12703 tng_molecules_block_len_calculate(tng_data, &len);
12706 for(i = 0; i < tng_data->n_data_blocks; i++)
12708 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12709 tng_block_header_len_calculate(tng_data, block, &len);
12711 tng_data_block_len_calculate(tng_data,
12712 (tng_particle_data_t)&tng_data->non_tr_data[i],
12713 TNG_FALSE, 1, 1, 1, 0,
12714 1, 0, &data_start_pos,
12718 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12720 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12721 tng_block_header_len_calculate(tng_data, block, &len);
12723 tng_data_block_len_calculate(tng_data,
12724 &tng_data->non_tr_particle_data[i],
12725 TNG_TRUE, 1, 1, 1, 0,
12726 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12731 tng_block_destroy(&block);
12733 if(tot_len > orig_len)
12735 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12738 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12741 /* TODO: If there is already frame set data written to this file (e.g. when
12742 * appending to an already existing file we might need to move frame sets to
12743 * the end of the file. */
12745 if(tng_general_info_block_write(tng_data, hash_mode)
12748 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12749 tng_data->input_file_path, __FILE__, __LINE__);
12750 return(TNG_CRITICAL);
12753 if(tng_molecules_block_write(tng_data, hash_mode)
12756 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12757 tng_data->input_file_path, __FILE__, __LINE__);
12758 return(TNG_CRITICAL);
12761 /* FIXME: Currently writing non-trajectory data blocks here.
12762 * Should perhaps be moved. */
12763 tng_block_init(&block);
12764 for(i = 0; i < tng_data->n_data_blocks; i++)
12766 block->id = tng_data->non_tr_data[i].block_id;
12767 tng_data_block_write(tng_data, block,
12771 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12773 block->id = tng_data->non_tr_particle_data[i].block_id;
12774 tng_particle_data_block_write(tng_data, block,
12778 tng_block_destroy(&block);
12780 return(TNG_SUCCESS);
12783 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12784 tng_gen_block_t block,
12785 const char hash_mode)
12787 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12788 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12792 case TNG_TRAJECTORY_FRAME_SET:
12793 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12794 case TNG_PARTICLE_MAPPING:
12795 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12796 case TNG_GENERAL_INFO:
12797 return(tng_general_info_block_read(tng_data, block, hash_mode));
12798 case TNG_MOLECULES:
12799 return(tng_molecules_block_read(tng_data, block, hash_mode));
12801 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12803 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12807 /* Skip to the next block */
12808 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12809 return(TNG_FAILURE);
12814 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12815 (tng_trajectory_t tng_data,
12816 const char hash_mode)
12819 tng_gen_block_t block;
12820 tng_function_status stat;
12822 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12824 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12826 return(TNG_CRITICAL);
12829 file_pos = ftello(tng_data->input_file);
12831 tng_block_init(&block);
12833 if(!tng_data->input_file_len)
12835 fseeko(tng_data->input_file, 0, SEEK_END);
12836 tng_data->input_file_len = ftello(tng_data->input_file);
12837 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12840 /* Read block headers first to see what block is found. */
12841 stat = tng_block_header_read(tng_data, block);
12842 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12845 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12846 file_pos, __FILE__, __LINE__);
12847 tng_block_destroy(&block);
12848 return(TNG_CRITICAL);
12851 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12853 if(tng_block_read_next(tng_data, block,
12854 hash_mode) == TNG_SUCCESS)
12856 tng_data->n_trajectory_frame_sets++;
12857 file_pos = ftello(tng_data->input_file);
12858 /* Read all blocks until next frame set block */
12859 stat = tng_block_header_read(tng_data, block);
12860 while(file_pos < tng_data->input_file_len &&
12861 stat != TNG_CRITICAL &&
12862 block->id != TNG_TRAJECTORY_FRAME_SET &&
12865 stat = tng_block_read_next(tng_data, block,
12867 if(stat != TNG_CRITICAL)
12869 file_pos = ftello(tng_data->input_file);
12870 if(file_pos < tng_data->input_file_len)
12872 stat = tng_block_header_read(tng_data, block);
12876 if(stat == TNG_CRITICAL)
12878 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12879 file_pos, __FILE__, __LINE__);
12880 tng_block_destroy(&block);
12884 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12886 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12890 tng_block_destroy(&block);
12892 return(TNG_SUCCESS);
12896 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12897 (tng_trajectory_t tng_data,
12898 const char hash_mode,
12899 const int64_t block_id)
12902 tng_gen_block_t block;
12903 tng_function_status stat;
12904 int found_flag = 1;
12906 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12908 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12910 return(TNG_CRITICAL);
12913 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12917 /* No current frame set. This means that the first frame set must be
12920 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12925 fseeko(tng_data->input_file,
12931 return(TNG_FAILURE);
12934 tng_block_init(&block);
12936 if(!tng_data->input_file_len)
12938 fseeko(tng_data->input_file, 0, SEEK_END);
12939 tng_data->input_file_len = ftello(tng_data->input_file);
12940 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12943 /* Read block headers first to see what block is found. */
12944 stat = tng_block_header_read(tng_data, block);
12945 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12947 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12948 file_pos, __FILE__, __LINE__);
12949 tng_block_destroy(&block);
12950 return(TNG_CRITICAL);
12952 /* If the current frame set had already been read skip its block contents */
12955 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12957 /* Otherwiese read the frame set block */
12960 stat = tng_block_read_next(tng_data, block,
12962 if(stat != TNG_SUCCESS)
12964 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12965 tng_block_destroy(&block);
12969 file_pos = ftello(tng_data->input_file);
12973 /* Read only blocks of the requested ID
12974 * until next frame set block */
12975 stat = tng_block_header_read(tng_data, block);
12976 while(file_pos < tng_data->input_file_len &&
12977 stat != TNG_CRITICAL &&
12978 block->id != TNG_TRAJECTORY_FRAME_SET &&
12981 if(block->id == block_id)
12983 stat = tng_block_read_next(tng_data, block,
12985 if(stat != TNG_CRITICAL)
12987 file_pos = ftello(tng_data->input_file);
12989 if(file_pos < tng_data->input_file_len)
12991 stat = tng_block_header_read(tng_data, block);
12997 file_pos += (block->block_contents_size + block->header_contents_size);
12998 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12999 if(file_pos < tng_data->input_file_len)
13001 stat = tng_block_header_read(tng_data, block);
13005 if(stat == TNG_CRITICAL)
13007 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13008 file_pos, __FILE__, __LINE__);
13009 tng_block_destroy(&block);
13013 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13015 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13018 tng_block_destroy(&block);
13022 return(TNG_SUCCESS);
13026 return(TNG_FAILURE);
13030 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
13031 (tng_trajectory_t tng_data,
13032 const char hash_mode)
13036 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13038 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13040 return(TNG_CRITICAL);
13043 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13045 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13047 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13052 fseeko(tng_data->input_file,
13058 return(TNG_FAILURE);
13061 return(tng_frame_set_read(tng_data, hash_mode));
13064 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13065 (tng_trajectory_t tng_data,
13066 const char hash_mode,
13067 const int64_t block_id)
13070 tng_gen_block_t block;
13071 tng_function_status stat;
13073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13075 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13077 return(TNG_CRITICAL);
13080 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13082 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13084 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13089 fseeko(tng_data->input_file,
13095 return(TNG_FAILURE);
13098 tng_block_init(&block);
13100 if(!tng_data->input_file_len)
13102 fseeko(tng_data->input_file, 0, SEEK_END);
13103 tng_data->input_file_len = ftello(tng_data->input_file);
13104 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13107 /* Read block headers first to see what block is found. */
13108 stat = tng_block_header_read(tng_data, block);
13109 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13111 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13112 file_pos, __FILE__, __LINE__);
13113 tng_block_destroy(&block);
13114 return(TNG_CRITICAL);
13117 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13119 if(tng_block_read_next(tng_data, block,
13120 hash_mode) == TNG_SUCCESS)
13122 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13125 tng_block_destroy(&block);
13130 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13131 const char hash_mode)
13134 tng_gen_block_t block;
13135 tng_trajectory_frame_set_t frame_set;
13136 tng_function_status stat;
13138 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13140 frame_set = &tng_data->current_trajectory_frame_set;
13142 if(frame_set->n_written_frames == frame_set->n_frames)
13144 return(TNG_SUCCESS);
13147 tng_data->current_trajectory_frame_set_output_file_pos =
13148 ftello(tng_data->output_file);
13149 tng_data->last_trajectory_frame_set_output_file_pos =
13150 tng_data->current_trajectory_frame_set_output_file_pos;
13152 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13154 return(TNG_FAILURE);
13157 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13159 tng_data->first_trajectory_frame_set_output_file_pos =
13160 tng_data->current_trajectory_frame_set_output_file_pos;
13163 tng_block_init(&block);
13165 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13167 tng_block_destroy(&block);
13168 return(TNG_FAILURE);
13171 /* Write non-particle data blocks */
13172 for(i = 0; i<frame_set->n_data_blocks; i++)
13174 block->id = frame_set->tr_data[i].block_id;
13175 tng_data_block_write(tng_data, block, i, hash_mode);
13177 /* Write the mapping blocks and particle data blocks*/
13178 if(frame_set->n_mapping_blocks)
13180 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13182 block->id = TNG_PARTICLE_MAPPING;
13183 if(frame_set->mappings[i].n_particles > 0)
13185 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13186 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13188 block->id = frame_set->tr_particle_data[j].block_id;
13189 tng_particle_data_block_write(tng_data, block,
13190 j, &frame_set->mappings[i],
13198 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13200 block->id = frame_set->tr_particle_data[i].block_id;
13201 tng_particle_data_block_write(tng_data, block,
13207 /* Update pointers in the general info block */
13208 stat = tng_header_pointers_update(tng_data, hash_mode);
13210 if(stat == TNG_SUCCESS)
13212 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13215 tng_block_destroy(&block);
13217 frame_set->n_unwritten_frames = 0;
13219 fflush(tng_data->output_file);
13224 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13225 (tng_trajectory_t tng_data,
13226 const char hash_mode)
13228 tng_trajectory_frame_set_t frame_set;
13230 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13232 frame_set = &tng_data->current_trajectory_frame_set;
13234 if(frame_set->n_unwritten_frames == 0)
13236 return(TNG_SUCCESS);
13238 frame_set->n_frames = frame_set->n_unwritten_frames;
13240 return(tng_frame_set_write(tng_data, hash_mode));
13243 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13244 (tng_trajectory_t tng_data,
13245 const int64_t first_frame,
13246 const int64_t n_frames)
13248 tng_gen_block_t block;
13249 tng_trajectory_frame_set_t frame_set;
13250 FILE *temp = tng_data->input_file;
13253 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13254 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13255 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13257 frame_set = &tng_data->current_trajectory_frame_set;
13259 curr_pos = ftello(tng_data->output_file);
13263 tng_file_headers_write(tng_data, TNG_USE_HASH);
13266 /* Set pointer to previous frame set to the one that was loaded
13268 * FIXME: This is a bit risky. If they are not added in order
13269 * it will be wrong. */
13270 if(tng_data->n_trajectory_frame_sets)
13272 frame_set->prev_frame_set_file_pos =
13273 tng_data->current_trajectory_frame_set_output_file_pos;
13276 tng_data->current_trajectory_frame_set_output_file_pos =
13277 ftello(tng_data->output_file);
13279 tng_data->n_trajectory_frame_sets++;
13281 /* Set the medium range pointers */
13282 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13284 frame_set->medium_stride_prev_frame_set_file_pos =
13285 tng_data->first_trajectory_frame_set_output_file_pos;
13287 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13289 /* FIXME: Currently only working if the previous frame set has its
13290 * medium stride pointer already set. This might need some fixing. */
13291 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13292 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13294 tng_block_init(&block);
13295 tng_data->input_file = tng_data->output_file;
13297 curr_pos = ftello(tng_data->output_file);
13298 fseeko(tng_data->output_file,
13299 frame_set->medium_stride_prev_frame_set_file_pos,
13302 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13304 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13305 __FILE__, __LINE__);
13306 tng_data->input_file = temp;
13307 tng_block_destroy(&block);
13308 return(TNG_CRITICAL);
13311 /* Read the next frame set from the previous frame set and one
13312 * medium stride step back */
13313 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13314 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13315 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13316 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13317 1, tng_data->output_file) == 0)
13319 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13320 tng_data->input_file = temp;
13321 tng_block_destroy(&block);
13322 return(TNG_CRITICAL);
13325 if(tng_data->input_endianness_swap_func_64)
13327 if(tng_data->input_endianness_swap_func_64(tng_data,
13328 &frame_set->medium_stride_prev_frame_set_file_pos)
13331 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13332 __FILE__, __LINE__);
13336 tng_block_destroy(&block);
13338 /* Set the long range pointers */
13339 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13341 frame_set->long_stride_prev_frame_set_file_pos =
13342 tng_data->first_trajectory_frame_set_output_file_pos;
13344 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13346 /* FIXME: Currently only working if the previous frame set has its
13347 * long stride pointer already set. This might need some fixing. */
13348 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13349 frame_set->long_stride_prev_frame_set_file_pos != 0)
13351 tng_block_init(&block);
13352 tng_data->input_file = tng_data->output_file;
13354 fseeko(tng_data->output_file,
13355 frame_set->long_stride_prev_frame_set_file_pos,
13358 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13360 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13361 __FILE__, __LINE__);
13362 tng_data->input_file = temp;
13363 tng_block_destroy(&block);
13364 return(TNG_CRITICAL);
13367 /* Read the next frame set from the previous frame set and one
13368 * long stride step back */
13369 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13370 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13372 tng_block_destroy(&block);
13374 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13375 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13376 1, tng_data->output_file) == 0)
13378 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13379 tng_data->input_file = temp;
13380 return(TNG_CRITICAL);
13383 if(tng_data->input_endianness_swap_func_64)
13385 if(tng_data->input_endianness_swap_func_64(tng_data,
13386 &frame_set->long_stride_prev_frame_set_file_pos)
13389 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13390 __FILE__, __LINE__);
13397 tng_data->input_file = temp;
13398 fseeko(tng_data->output_file, curr_pos, SEEK_SET);
13402 frame_set->first_frame = first_frame;
13403 frame_set->n_frames = n_frames;
13404 frame_set->n_written_frames = 0;
13405 frame_set->n_unwritten_frames = 0;
13406 frame_set->first_frame_time = -1;
13408 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13409 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13411 tng_data->first_trajectory_frame_set_output_file_pos =
13412 tng_data->current_trajectory_frame_set_output_file_pos;
13414 /* FIXME: Should check the frame number instead of the file_pos,
13415 * in case frame sets are not in order */
13416 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13417 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13418 tng_data->last_trajectory_frame_set_output_file_pos <
13419 tng_data->current_trajectory_frame_set_output_file_pos)
13421 tng_data->last_trajectory_frame_set_output_file_pos =
13422 tng_data->current_trajectory_frame_set_output_file_pos;
13425 return(TNG_SUCCESS);
13428 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13429 (tng_trajectory_t tng_data,
13430 const int64_t first_frame,
13431 const int64_t n_frames,
13432 const double first_frame_time)
13434 tng_function_status stat;
13436 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13437 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13438 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13439 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13442 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13443 if(stat != TNG_SUCCESS)
13447 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13452 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13453 (tng_trajectory_t tng_data,
13454 const double first_frame_time)
13456 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13457 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13459 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13461 return(TNG_SUCCESS);
13464 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13465 (const tng_trajectory_t tng_data,
13468 int64_t file_pos, next_frame_set_file_pos;
13469 tng_gen_block_t block;
13470 tng_function_status stat;
13472 tng_trajectory_frame_set_t frame_set;
13474 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13475 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13476 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13478 file_pos = ftello(tng_data->input_file);
13480 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13482 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13486 frame_set = &tng_data->current_trajectory_frame_set;
13487 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
13490 if(next_frame_set_file_pos <= 0)
13492 return(TNG_FAILURE);
13495 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
13496 /* Read block headers first to see that a frame set block is found. */
13497 tng_block_init(&block);
13498 stat = tng_block_header_read(tng_data, block);
13499 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13501 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13502 file_pos, __FILE__, __LINE__);
13503 return(TNG_CRITICAL);
13505 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13507 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13509 tng_block_destroy(&block);
13511 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13513 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13514 __FILE__, __LINE__);
13515 return(TNG_CRITICAL);
13517 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13519 return(TNG_SUCCESS);
13522 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13523 (tng_trajectory_t tng_data,
13525 const char *block_name,
13526 const char datatype,
13527 const char block_type_flag,
13529 const int64_t n_values_per_frame,
13530 int64_t stride_length,
13531 const int64_t codec_id,
13534 int i, j, size, len;
13535 tng_trajectory_frame_set_t frame_set;
13536 tng_non_particle_data_t data;
13537 char **first_dim_values;
13538 char *new_data_c=new_data;
13539 int64_t n_frames_div;
13541 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13542 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13543 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13545 frame_set = &tng_data->current_trajectory_frame_set;
13547 if(stride_length <= 0)
13552 /* If the block does not exist, create it */
13553 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13555 if(tng_data_block_create(tng_data, block_type_flag) !=
13558 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13559 __FILE__, __LINE__);
13560 return(TNG_CRITICAL);
13562 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13564 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13568 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13570 data->block_id = id;
13572 data->block_name = malloc(strlen(block_name) + 1);
13573 if(!data->block_name)
13575 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13576 (int)strlen(block_name)+1, __FILE__, __LINE__);
13577 return(TNG_CRITICAL);
13579 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13582 /* FIXME: Memory leak from strings. */
13584 data->last_retrieved_frame = -1;
13587 data->datatype = datatype;
13588 data->stride_length = tng_max_i64(stride_length, 1);
13589 data->n_values_per_frame = n_values_per_frame;
13590 data->n_frames = n_frames;
13591 data->codec_id = codec_id;
13592 data->compression_multiplier = 1.0;
13593 /* FIXME: This can cause problems. */
13594 data->first_frame_with_data = frame_set->first_frame;
13598 case TNG_FLOAT_DATA:
13599 size = sizeof(float);
13602 size = sizeof(int64_t);
13604 case TNG_DOUBLE_DATA:
13606 size = sizeof(double);
13612 /* Allocate memory */
13613 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13614 n_values_per_frame) !=
13617 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13618 __FILE__, __LINE__);
13619 return(TNG_CRITICAL);
13622 if(n_frames > frame_set->n_unwritten_frames)
13624 frame_set->n_unwritten_frames = n_frames;
13627 n_frames_div = (n_frames % stride_length) ?
13628 n_frames / stride_length + 1:
13629 n_frames / stride_length;
13631 if(datatype == TNG_CHAR_DATA)
13633 for(i = 0; i < n_frames_div; i++)
13635 first_dim_values = data->strings[i];
13636 for(j = 0; j < n_values_per_frame; j++)
13638 len = tng_min_i((int)strlen(new_data_c) + 1,
13640 if(first_dim_values[j])
13642 free(first_dim_values[j]);
13644 first_dim_values[j] = malloc(len);
13645 if(!first_dim_values[j])
13647 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13648 len, __FILE__, __LINE__);
13649 return(TNG_CRITICAL);
13651 strncpy(first_dim_values[j],
13659 memcpy(data->values, new_data, size * n_frames_div *
13660 n_values_per_frame);
13664 return(TNG_SUCCESS);
13667 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13668 (tng_trajectory_t tng_data,
13670 const char *block_name,
13671 const char datatype,
13672 const char block_type_flag,
13674 const int64_t n_values_per_frame,
13675 int64_t stride_length,
13676 const int64_t num_first_particle,
13677 const int64_t n_particles,
13678 const int64_t codec_id,
13683 int64_t tot_n_particles, n_frames_div;
13684 char ***first_dim_values, **second_dim_values;
13685 tng_trajectory_frame_set_t frame_set;
13686 tng_particle_data_t data;
13687 char *new_data_c=new_data;
13689 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13690 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13691 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13692 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13693 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13696 frame_set = &tng_data->current_trajectory_frame_set;
13698 if(stride_length <= 0)
13703 /* If the block does not exist, create it */
13704 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13706 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13709 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13710 __FILE__, __LINE__);
13711 return(TNG_CRITICAL);
13713 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13715 data = &frame_set->tr_particle_data[frame_set->
13716 n_particle_data_blocks - 1];
13720 data = &tng_data->non_tr_particle_data[tng_data->
13721 n_particle_data_blocks - 1];
13723 data->block_id = id;
13725 data->block_name = malloc(strlen(block_name) + 1);
13726 if(!data->block_name)
13728 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13729 (int)strlen(block_name)+1, __FILE__, __LINE__);
13730 return(TNG_CRITICAL);
13732 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13734 data->datatype = datatype;
13737 /* FIXME: Memory leak from strings. */
13739 data->last_retrieved_frame = -1;
13742 data->stride_length = tng_max_i64(stride_length, 1);
13743 data->n_values_per_frame = n_values_per_frame;
13744 data->n_frames = n_frames;
13745 data->codec_id = codec_id;
13746 data->compression_multiplier = 1.0;
13747 /* FIXME: This can cause problems. */
13748 data->first_frame_with_data = frame_set->first_frame;
13750 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13752 tot_n_particles = frame_set->n_particles;
13756 tot_n_particles = tng_data->n_particles;
13759 /* If data values are supplied add that data to the data block. */
13762 /* Allocate memory */
13763 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13764 stride_length, tot_n_particles,
13765 n_values_per_frame) !=
13768 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13769 __FILE__, __LINE__);
13770 return(TNG_CRITICAL);
13773 if(n_frames > frame_set->n_unwritten_frames)
13775 frame_set->n_unwritten_frames = n_frames;
13778 n_frames_div = (n_frames % stride_length) ?
13779 n_frames / stride_length + 1:
13780 n_frames / stride_length;
13782 if(datatype == TNG_CHAR_DATA)
13784 for(i = 0; i < n_frames_div; i++)
13786 first_dim_values = data->strings[i];
13787 for(j = num_first_particle; j < num_first_particle + n_particles;
13790 second_dim_values = first_dim_values[j];
13791 for(k = 0; k < n_values_per_frame; k++)
13793 len = tng_min_i((int)strlen(new_data_c) + 1,
13795 if(second_dim_values[k])
13797 free(second_dim_values[k]);
13799 second_dim_values[k] = malloc(len);
13800 if(!second_dim_values[k])
13802 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13803 len, __FILE__, __LINE__);
13804 return(TNG_CRITICAL);
13806 strncpy(second_dim_values[k],
13818 size = sizeof(int64_t);
13820 case TNG_FLOAT_DATA:
13821 size = sizeof(float);
13823 case TNG_DOUBLE_DATA:
13825 size = sizeof(double);
13828 memcpy(data->values, new_data, size * n_frames_div *
13829 n_particles * n_values_per_frame);
13833 return(TNG_SUCCESS);
13836 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13837 (tng_trajectory_t tng_data,
13843 tng_trajectory_frame_set_t frame_set;
13844 tng_function_status stat;
13845 tng_particle_data_t p_data;
13846 tng_non_particle_data_t np_data;
13847 int block_type = -1;
13849 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13850 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13852 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13854 p_data = &tng_data->non_tr_particle_data[i];
13855 if(p_data->block_id == block_id)
13857 strncpy(name, p_data->block_name, max_len);
13858 name[max_len - 1] = '\0';
13859 return(TNG_SUCCESS);
13862 for(i = 0; i < tng_data->n_data_blocks; i++)
13864 np_data = &tng_data->non_tr_data[i];
13865 if(np_data->block_id == block_id)
13867 strncpy(name, np_data->block_name, max_len);
13868 name[max_len - 1] = '\0';
13869 return(TNG_SUCCESS);
13873 frame_set = &tng_data->current_trajectory_frame_set;
13875 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13876 if(stat == TNG_SUCCESS)
13878 block_type = TNG_PARTICLE_BLOCK_DATA;
13882 stat = tng_data_find(tng_data, block_id, &np_data);
13883 if(stat == TNG_SUCCESS)
13885 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13889 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13890 if(stat != TNG_SUCCESS)
13894 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13895 if(stat == TNG_SUCCESS)
13897 block_type = TNG_PARTICLE_BLOCK_DATA;
13901 stat = tng_data_find(tng_data, block_id, &np_data);
13902 if(stat == TNG_SUCCESS)
13904 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13909 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13911 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13913 p_data = &frame_set->tr_particle_data[i];
13914 if(p_data->block_id == block_id)
13916 strncpy(name, p_data->block_name, max_len);
13917 name[max_len - 1] = '\0';
13918 return(TNG_SUCCESS);
13922 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13924 for(i = 0; i < frame_set->n_data_blocks; i++)
13926 np_data = &frame_set->tr_data[i];
13927 if(np_data->block_id == block_id)
13929 strncpy(name, np_data->block_name, max_len);
13930 name[max_len - 1] = '\0';
13931 return(TNG_SUCCESS);
13936 return(TNG_FAILURE);
13939 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13940 (const tng_trajectory_t tng_data,
13942 int *block_dependency)
13945 tng_function_status stat;
13946 tng_particle_data_t p_data;
13947 tng_non_particle_data_t np_data;
13949 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13950 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13952 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13954 p_data = &tng_data->non_tr_particle_data[i];
13955 if(p_data->block_id == block_id)
13957 *block_dependency = TNG_PARTICLE_DEPENDENT;
13958 return(TNG_SUCCESS);
13961 for(i = 0; i < tng_data->n_data_blocks; i++)
13963 np_data = &tng_data->non_tr_data[i];
13964 if(np_data->block_id == block_id)
13966 *block_dependency = 0;
13967 return(TNG_SUCCESS);
13971 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13972 if(stat == TNG_SUCCESS)
13974 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13975 return(TNG_SUCCESS);
13979 stat = tng_data_find(tng_data, block_id, &np_data);
13980 if(stat == TNG_SUCCESS)
13982 *block_dependency = TNG_FRAME_DEPENDENT;
13983 return(TNG_SUCCESS);
13987 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13988 if(stat != TNG_SUCCESS)
13992 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13993 if(stat == TNG_SUCCESS)
13995 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13996 return(TNG_SUCCESS);
14000 stat = tng_data_find(tng_data, block_id, &np_data);
14001 if(stat == TNG_SUCCESS)
14003 *block_dependency = TNG_FRAME_DEPENDENT;
14004 return(TNG_SUCCESS);
14010 return(TNG_FAILURE);
14013 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
14014 (const tng_trajectory_t tng_data,
14016 int64_t *n_values_per_frame)
14019 tng_function_status stat;
14020 tng_particle_data_t p_data;
14021 tng_non_particle_data_t np_data;
14023 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14024 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14026 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
14028 p_data = &tng_data->non_tr_particle_data[i];
14029 if(p_data->block_id == block_id)
14031 *n_values_per_frame = p_data->n_values_per_frame;
14032 return(TNG_SUCCESS);
14035 for(i = 0; i < tng_data->n_data_blocks; i++)
14037 np_data = &tng_data->non_tr_data[i];
14038 if(np_data->block_id == block_id)
14040 *n_values_per_frame = np_data->n_values_per_frame;
14041 return(TNG_SUCCESS);
14045 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14046 if(stat == TNG_SUCCESS)
14048 *n_values_per_frame = p_data->n_values_per_frame;
14049 return(TNG_SUCCESS);
14053 stat = tng_data_find(tng_data, block_id, &np_data);
14054 if(stat == TNG_SUCCESS)
14056 *n_values_per_frame = np_data->n_values_per_frame;
14057 return(TNG_SUCCESS);
14061 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14062 if(stat != TNG_SUCCESS)
14066 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14067 if(stat == TNG_SUCCESS)
14069 *n_values_per_frame = p_data->n_values_per_frame;
14070 return(TNG_SUCCESS);
14074 stat = tng_data_find(tng_data, block_id, &np_data);
14075 if(stat == TNG_SUCCESS)
14077 *n_values_per_frame = np_data->n_values_per_frame;
14078 return(TNG_SUCCESS);
14084 return(TNG_FAILURE);
14087 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14088 (tng_trajectory_t tng_data,
14089 const int64_t frame_nr,
14090 const int64_t block_id,
14091 const void *values,
14092 const char hash_mode)
14094 int64_t header_pos, file_pos;
14095 int64_t output_file_len, n_values_per_frame, size, contents_size;
14096 int64_t header_size, temp_first, temp_last;
14097 int64_t i, last_frame, temp_current;
14098 tng_gen_block_t block;
14099 tng_trajectory_frame_set_t frame_set;
14100 FILE *temp = tng_data->input_file;
14101 struct tng_non_particle_data data;
14102 tng_function_status stat;
14103 char dependency, sparse_data, datatype;
14106 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14107 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14108 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14110 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14112 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14113 __FILE__, __LINE__);
14114 return(TNG_CRITICAL);
14117 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14118 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14119 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14120 tng_data->first_trajectory_frame_set_input_file_pos =
14121 tng_data->first_trajectory_frame_set_output_file_pos;
14122 tng_data->last_trajectory_frame_set_input_file_pos =
14123 tng_data->last_trajectory_frame_set_output_file_pos;
14124 tng_data->current_trajectory_frame_set_input_file_pos =
14125 tng_data->current_trajectory_frame_set_output_file_pos;
14127 tng_data->input_file = tng_data->output_file;
14129 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14131 frame_set = &tng_data->current_trajectory_frame_set;
14133 if(stat != TNG_SUCCESS)
14135 last_frame = frame_set->first_frame +
14136 frame_set->n_frames - 1;
14137 /* If the wanted frame would be in the frame set after the last
14138 * frame set create a new frame set. */
14139 if(stat == TNG_FAILURE &&
14140 last_frame < frame_nr)
14141 /* (last_frame < frame_nr &&
14142 tng_data->current_trajectory_frame_set.first_frame +
14143 tng_data->frame_set_n_frames >= frame_nr))*/
14145 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14147 last_frame = frame_nr - 1;
14149 tng_frame_set_new(tng_data,
14151 tng_data->frame_set_n_frames);
14152 file_pos = ftello(tng_data->output_file);
14153 fseeko(tng_data->output_file, 0, SEEK_END);
14154 output_file_len = ftello(tng_data->output_file);
14155 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14157 /* Read mapping blocks from the last frame set */
14158 tng_block_init(&block);
14160 stat = tng_block_header_read(tng_data, block);
14161 while(file_pos < output_file_len &&
14162 stat != TNG_CRITICAL &&
14163 block->id != TNG_TRAJECTORY_FRAME_SET &&
14166 if(block->id == TNG_PARTICLE_MAPPING)
14168 tng_trajectory_mapping_block_read(tng_data, block,
14173 fseeko(tng_data->output_file, block->block_contents_size,
14176 file_pos = ftello(tng_data->output_file);
14177 if(file_pos < output_file_len)
14179 stat = tng_block_header_read(tng_data, block);
14183 tng_block_destroy(&block);
14184 /* Write the frame set to disk */
14185 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14187 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14188 return(TNG_CRITICAL);
14193 tng_data->input_file = temp;
14194 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14195 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14196 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14201 tng_block_init(&block);
14203 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14205 fseeko(tng_data->output_file, 0, SEEK_END);
14206 output_file_len = ftello(tng_data->output_file);
14207 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14209 /* Read past the frame set block first */
14210 stat = tng_block_header_read(tng_data, block);
14211 if(stat == TNG_CRITICAL)
14213 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14214 file_pos, __FILE__, __LINE__);
14215 tng_block_destroy(&block);
14216 tng_data->input_file = temp;
14218 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14219 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14220 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14223 fseeko(tng_data->output_file, block->block_contents_size,
14226 /* Read all block headers until next frame set block or
14227 * until the wanted block id is found */
14228 stat = tng_block_header_read(tng_data, block);
14229 while(file_pos < output_file_len &&
14230 stat != TNG_CRITICAL &&
14231 block->id != block_id &&
14232 block->id != TNG_TRAJECTORY_FRAME_SET &&
14235 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14236 file_pos = ftello(tng_data->output_file);
14237 if(file_pos < output_file_len)
14239 stat = tng_block_header_read(tng_data, block);
14242 if(stat == TNG_CRITICAL)
14244 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14245 file_pos, __FILE__, __LINE__);
14246 tng_block_destroy(&block);
14247 tng_data->input_file = temp;
14248 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14249 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14250 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14254 contents_size = block->block_contents_size;
14255 header_size = block->header_contents_size;
14257 header_pos = ftello(tng_data->output_file) - header_size;
14258 frame_set = &tng_data->current_trajectory_frame_set;
14260 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14262 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14263 tng_block_destroy(&block);
14264 return(TNG_CRITICAL);
14266 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14268 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14269 tng_block_destroy(&block);
14270 return(TNG_CRITICAL);
14272 data.datatype = datatype;
14274 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14275 (dependency & TNG_PARTICLE_DEPENDENT))
14277 tng_block_destroy(&block);
14278 tng_data->input_file = temp;
14280 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14281 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14282 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14283 return(TNG_FAILURE);
14286 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14288 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14289 tng_block_destroy(&block);
14290 return(TNG_CRITICAL);
14293 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14294 tng_data->input_file) == 0)
14296 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14297 tng_block_destroy(&block);
14298 return(TNG_CRITICAL);
14300 if(tng_data->output_endianness_swap_func_64)
14302 if(tng_data->output_endianness_swap_func_64(tng_data,
14303 &data.n_values_per_frame)
14306 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14307 __FILE__, __LINE__);
14311 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14312 tng_data->input_file) == 0)
14314 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14315 tng_block_destroy(&block);
14316 return(TNG_CRITICAL);
14318 if(tng_data->output_endianness_swap_func_64)
14320 if(tng_data->output_endianness_swap_func_64(tng_data,
14324 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14325 __FILE__, __LINE__);
14329 if(data.codec_id != TNG_UNCOMPRESSED)
14331 if(fread(&data.compression_multiplier,
14332 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14335 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14336 tng_block_destroy(&block);
14337 return(TNG_CRITICAL);
14339 if(tng_data->output_endianness_swap_func_64)
14341 if(tng_data->output_endianness_swap_func_64(tng_data,
14342 (int64_t *)&data.compression_multiplier)
14345 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14346 __FILE__, __LINE__);
14352 data.compression_multiplier = 1;
14357 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14358 1, tng_data->input_file) == 0)
14360 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14361 tng_block_destroy(&block);
14362 return(TNG_CRITICAL);
14364 if(tng_data->output_endianness_swap_func_64)
14366 if(tng_data->output_endianness_swap_func_64(tng_data,
14367 &data.first_frame_with_data)
14370 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14371 __FILE__, __LINE__);
14375 if(fread(&data.stride_length, sizeof(data.stride_length),
14376 1, tng_data->input_file) == 0)
14378 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14379 tng_block_destroy(&block);
14380 return(TNG_CRITICAL);
14382 if(tng_data->output_endianness_swap_func_64)
14384 if(tng_data->output_endianness_swap_func_64(tng_data,
14385 &data.stride_length)
14388 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14389 __FILE__, __LINE__);
14395 data.first_frame_with_data = 0;
14396 data.stride_length = 1;
14398 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14400 tng_data->input_file = temp;
14402 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14403 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14404 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14406 switch(data.datatype)
14408 case(TNG_INT_DATA):
14409 size = sizeof(int64_t);
14411 case(TNG_FLOAT_DATA):
14412 size = sizeof(float);
14414 case(TNG_DOUBLE_DATA):
14415 size = sizeof(double);
14418 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14420 tng_block_destroy(&block);
14421 return(TNG_FAILURE);
14424 n_values_per_frame = data.n_values_per_frame;
14426 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14427 data.first_frame_with_data)) /
14428 data.stride_length;
14429 file_pos *= size * n_values_per_frame;
14431 if(file_pos > contents_size)
14433 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14435 tng_block_destroy(&block);
14436 return(TNG_FAILURE);
14439 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
14441 /* If the endianness is not big endian the data needs to be swapped */
14442 if((data.datatype == TNG_INT_DATA ||
14443 data.datatype == TNG_DOUBLE_DATA) &&
14444 tng_data->output_endianness_swap_func_64)
14446 copy = malloc(n_values_per_frame * size);
14447 memcpy(copy, values, n_values_per_frame * size);
14448 for(i = 0; i < n_values_per_frame; i++)
14450 if(tng_data->output_endianness_swap_func_64(tng_data,
14454 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14455 __FILE__, __LINE__);
14458 fwrite(copy, n_values_per_frame, size,
14459 tng_data->output_file);
14462 else if(data.datatype == TNG_FLOAT_DATA &&
14463 tng_data->output_endianness_swap_func_32)
14465 copy = malloc(n_values_per_frame * size);
14466 memcpy(copy, values, n_values_per_frame * size);
14467 for(i = 0; i < n_values_per_frame; i++)
14469 if(tng_data->output_endianness_swap_func_32(tng_data,
14473 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14474 __FILE__, __LINE__);
14477 fwrite(copy, n_values_per_frame, size,
14478 tng_data->output_file);
14484 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14487 fflush(tng_data->output_file);
14489 /* Update the number of written frames in the frame set. */
14490 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14492 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14495 /* If the last frame has been written update the hash */
14496 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14497 data.first_frame_with_data) >=
14498 frame_set->n_frames)
14500 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14504 tng_block_destroy(&block);
14506 return(TNG_SUCCESS);
14509 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14510 (tng_trajectory_t tng_data,
14511 const int64_t frame_nr,
14512 const int64_t block_id,
14513 const int64_t val_first_particle,
14514 const int64_t val_n_particles,
14515 const void *values,
14516 const char hash_mode)
14518 int64_t header_pos, file_pos, tot_n_particles;
14519 int64_t output_file_len, n_values_per_frame, size, contents_size;
14520 int64_t header_size, temp_first, temp_last;
14521 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14522 int64_t i, last_frame, temp_current;
14523 tng_gen_block_t block;
14524 tng_trajectory_frame_set_t frame_set;
14525 FILE *temp = tng_data->input_file;
14526 struct tng_particle_data data;
14527 tng_function_status stat;
14528 tng_particle_mapping_t mapping;
14529 char dependency, sparse_data, datatype;
14532 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14533 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14534 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14535 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14536 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14538 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14540 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14541 __FILE__, __LINE__);
14542 return(TNG_CRITICAL);
14545 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14546 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14547 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14548 tng_data->first_trajectory_frame_set_input_file_pos =
14549 tng_data->first_trajectory_frame_set_output_file_pos;
14550 tng_data->last_trajectory_frame_set_input_file_pos =
14551 tng_data->last_trajectory_frame_set_output_file_pos;
14552 tng_data->current_trajectory_frame_set_input_file_pos =
14553 tng_data->current_trajectory_frame_set_output_file_pos;
14555 tng_data->input_file = tng_data->output_file;
14557 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14559 frame_set = &tng_data->current_trajectory_frame_set;
14561 if(stat != TNG_SUCCESS)
14563 last_frame = frame_set->first_frame +
14564 frame_set->n_frames - 1;
14565 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14567 /* If the wanted frame would be in the frame set after the last
14568 * frame set create a new frame set. */
14569 if(stat == TNG_FAILURE &&
14570 (last_frame < frame_nr &&
14571 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14573 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14575 last_frame = frame_nr - 1;
14577 tng_frame_set_new(tng_data,
14579 tng_data->frame_set_n_frames);
14581 file_pos = ftello(tng_data->output_file);
14582 fseeko(tng_data->output_file, 0, SEEK_END);
14583 output_file_len = ftello(tng_data->output_file);
14584 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14586 /* Read mapping blocks from the last frame set */
14587 tng_block_init(&block);
14589 stat = tng_block_header_read(tng_data, block);
14590 while(file_pos < output_file_len &&
14591 stat != TNG_CRITICAL &&
14592 block->id != TNG_TRAJECTORY_FRAME_SET &&
14595 if(block->id == TNG_PARTICLE_MAPPING)
14597 tng_trajectory_mapping_block_read(tng_data, block,
14602 fseeko(tng_data->output_file, block->block_contents_size,
14605 file_pos = ftello(tng_data->output_file);
14606 if(file_pos < output_file_len)
14608 stat = tng_block_header_read(tng_data, block);
14612 tng_block_destroy(&block);
14613 /* Write the frame set to disk */
14614 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14616 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14622 tng_data->input_file = temp;
14623 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14624 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14625 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14631 tng_block_init(&block);
14633 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14635 fseeko(tng_data->output_file, 0, SEEK_END);
14636 output_file_len = ftello(tng_data->output_file);
14637 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14639 /* Read past the frame set block first */
14640 stat = tng_block_header_read(tng_data, block);
14641 if(stat == TNG_CRITICAL)
14643 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14644 file_pos, __FILE__, __LINE__);
14645 tng_block_destroy(&block);
14646 tng_data->input_file = temp;
14648 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14649 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14650 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14653 fseeko(tng_data->output_file, block->block_contents_size,
14656 if(tng_data->var_num_atoms_flag)
14658 tot_n_particles = frame_set->n_particles;
14662 tot_n_particles = tng_data->n_particles;
14665 if(val_n_particles < tot_n_particles)
14667 mapping_block_end_pos = -1;
14668 /* Read all mapping blocks to find the right place to put the data */
14669 stat = tng_block_header_read(tng_data, block);
14670 while(file_pos < output_file_len &&
14671 stat != TNG_CRITICAL &&
14672 block->id != TNG_TRAJECTORY_FRAME_SET &&
14675 if(block->id == TNG_PARTICLE_MAPPING)
14677 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14681 fseeko(tng_data->output_file, block->block_contents_size,
14684 file_pos = ftello(tng_data->output_file);
14685 if(block->id == TNG_PARTICLE_MAPPING)
14687 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14688 if(val_first_particle >= mapping->num_first_particle &&
14689 val_first_particle < mapping->num_first_particle +
14690 mapping->n_particles &&
14691 val_first_particle + val_n_particles <=
14692 mapping->num_first_particle + mapping->n_particles)
14694 mapping_block_end_pos = file_pos;
14697 if(file_pos < output_file_len)
14699 stat = tng_block_header_read(tng_data, block);
14702 if(stat == TNG_CRITICAL)
14704 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14705 file_pos, __FILE__, __LINE__);
14706 tng_block_destroy(&block);
14707 tng_data->input_file = temp;
14709 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14710 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14711 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14714 if(mapping_block_end_pos < 0)
14716 tng_block_destroy(&block);
14717 tng_data->input_file = temp;
14719 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14720 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14721 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14722 return(TNG_FAILURE);
14724 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
14727 /* Read all block headers until next frame set block or
14728 * until the wanted block id is found */
14729 stat = tng_block_header_read(tng_data, block);
14730 while(file_pos < output_file_len &&
14731 stat != TNG_CRITICAL &&
14732 block->id != block_id &&
14733 block->id != TNG_PARTICLE_MAPPING &&
14734 block->id != TNG_TRAJECTORY_FRAME_SET &&
14737 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14738 file_pos = ftello(tng_data->output_file);
14739 if(file_pos < output_file_len)
14741 stat = tng_block_header_read(tng_data, block);
14744 if(stat == TNG_CRITICAL)
14746 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14747 file_pos, __FILE__, __LINE__);
14748 tng_block_destroy(&block);
14749 tng_data->input_file = temp;
14751 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14752 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14753 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14757 contents_size = block->block_contents_size;
14758 header_size = block->header_contents_size;
14760 header_pos = ftello(tng_data->output_file) - header_size;
14761 frame_set = &tng_data->current_trajectory_frame_set;
14763 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14765 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14766 tng_block_destroy(&block);
14767 return(TNG_CRITICAL);
14770 data.datatype = datatype;
14772 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14774 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14775 tng_block_destroy(&block);
14776 return(TNG_CRITICAL);
14779 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14780 !(dependency & TNG_PARTICLE_DEPENDENT))
14782 tng_block_destroy(&block);
14783 tng_data->input_file = temp;
14785 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14786 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14787 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14788 return(TNG_FAILURE);
14791 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14793 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14794 tng_block_destroy(&block);
14795 return(TNG_CRITICAL);
14798 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14799 tng_data->input_file) == 0)
14801 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14802 tng_block_destroy(&block);
14803 return(TNG_CRITICAL);
14805 if(tng_data->output_endianness_swap_func_64)
14807 if(tng_data->output_endianness_swap_func_64(tng_data,
14808 &data.n_values_per_frame)
14811 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14812 __FILE__, __LINE__);
14816 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14817 tng_data->input_file) == 0)
14819 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14820 tng_block_destroy(&block);
14821 return(TNG_CRITICAL);
14823 if(tng_data->output_endianness_swap_func_64)
14825 if(tng_data->output_endianness_swap_func_64(tng_data,
14829 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14830 __FILE__, __LINE__);
14834 if(data.codec_id != TNG_UNCOMPRESSED)
14836 if(fread(&data.compression_multiplier,
14837 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14840 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14841 tng_block_destroy(&block);
14842 return(TNG_CRITICAL);
14845 if(tng_data->output_endianness_swap_func_64)
14847 if(tng_data->output_endianness_swap_func_64(tng_data,
14848 (int64_t *)&data.compression_multiplier)
14851 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14852 __FILE__, __LINE__);
14858 data.compression_multiplier = 1;
14863 if(fread(&data.first_frame_with_data,
14864 sizeof(data.first_frame_with_data),
14865 1, tng_data->input_file) == 0)
14867 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14868 tng_block_destroy(&block);
14869 return(TNG_CRITICAL);
14871 if(tng_data->output_endianness_swap_func_64)
14873 if(tng_data->output_endianness_swap_func_64(tng_data,
14874 &data.first_frame_with_data)
14877 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14878 __FILE__, __LINE__);
14882 if(fread(&data.stride_length, sizeof(data.stride_length),
14883 1, tng_data->input_file) == 0)
14885 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14886 tng_block_destroy(&block);
14887 return(TNG_CRITICAL);
14889 if(tng_data->output_endianness_swap_func_64)
14891 if(tng_data->output_endianness_swap_func_64(tng_data,
14892 &data.stride_length)
14895 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14896 __FILE__, __LINE__);
14902 data.first_frame_with_data = 0;
14903 data.stride_length = 1;
14905 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14907 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14908 tng_data->input_file) == 0)
14910 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14911 tng_block_destroy(&block);
14912 return(TNG_CRITICAL);
14914 if(tng_data->output_endianness_swap_func_64)
14916 if(tng_data->output_endianness_swap_func_64(tng_data,
14917 &num_first_particle)
14920 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14921 __FILE__, __LINE__);
14925 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14926 tng_data->input_file) == 0)
14928 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14929 tng_block_destroy(&block);
14930 return(TNG_CRITICAL);
14932 if(tng_data->output_endianness_swap_func_64)
14934 if(tng_data->output_endianness_swap_func_64(tng_data,
14935 &block_n_particles)
14938 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14939 __FILE__, __LINE__);
14944 tng_data->input_file = temp;
14946 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14947 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14948 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14951 switch(data.datatype)
14953 case(TNG_INT_DATA):
14954 size = sizeof(int64_t);
14956 case(TNG_FLOAT_DATA):
14957 size = sizeof(float);
14959 case(TNG_DOUBLE_DATA):
14960 size = sizeof(double);
14963 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14965 tng_block_destroy(&block);
14966 return(TNG_FAILURE);
14969 n_values_per_frame = data.n_values_per_frame;
14971 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14972 data.first_frame_with_data)) /
14973 data.stride_length;
14974 file_pos *= block_n_particles * size * n_values_per_frame;
14976 if(file_pos > contents_size)
14978 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14980 tng_block_destroy(&block);
14981 return(TNG_FAILURE);
14984 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
14986 /* If the endianness is not big endian the data needs to be swapped */
14987 if((data.datatype == TNG_INT_DATA ||
14988 data.datatype == TNG_DOUBLE_DATA) &&
14989 tng_data->output_endianness_swap_func_64)
14991 copy = malloc(val_n_particles * n_values_per_frame * size);
14992 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14993 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14995 if(tng_data->output_endianness_swap_func_64(tng_data,
14996 (int64_t *) copy+i)
14999 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15000 __FILE__, __LINE__);
15003 fwrite(copy, val_n_particles * n_values_per_frame, size,
15004 tng_data->output_file);
15007 else if(data.datatype == TNG_FLOAT_DATA &&
15008 tng_data->output_endianness_swap_func_32)
15010 copy = malloc(val_n_particles * n_values_per_frame * size);
15011 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15012 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15014 if(tng_data->output_endianness_swap_func_32(tng_data,
15015 (int32_t *) copy+i)
15018 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15019 __FILE__, __LINE__);
15022 fwrite(copy, val_n_particles * n_values_per_frame, size,
15023 tng_data->output_file);
15029 fwrite(values, val_n_particles * n_values_per_frame, size,
15030 tng_data->output_file);
15032 fflush(tng_data->output_file);
15034 /* Update the number of written frames in the frame set. */
15035 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
15037 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
15040 /* If the last frame has been written update the hash */
15041 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
15042 data.first_frame_with_data) >=
15043 frame_set->n_frames)
15045 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
15049 tng_block_destroy(&block);
15050 return(TNG_SUCCESS);
15053 static tng_function_status tng_data_values_alloc
15054 (const tng_trajectory_t tng_data,
15055 union data_values ***values,
15056 const int64_t n_frames,
15057 const int64_t n_values_per_frame,
15061 tng_function_status stat;
15063 if(n_frames <= 0 || n_values_per_frame <= 0)
15065 return(TNG_FAILURE);
15070 stat = tng_data_values_free(tng_data, *values, n_frames,
15071 n_values_per_frame,
15073 if(stat != TNG_SUCCESS)
15075 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15076 __FILE__, __LINE__);
15080 *values = malloc(sizeof(union data_values *) * n_frames);
15083 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15084 sizeof(union data_values **) * n_frames,
15085 __FILE__, __LINE__);
15086 return(TNG_CRITICAL);
15090 for(i = 0; i < n_frames; i++)
15092 (*values)[i] = malloc(sizeof(union data_values) *
15093 n_values_per_frame);
15096 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15097 sizeof(union data_values) * n_values_per_frame,
15098 __FILE__, __LINE__);
15101 return(TNG_CRITICAL);
15104 return(TNG_SUCCESS);
15107 /* FIXME: This needs ***values */
15108 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15109 (const tng_trajectory_t tng_data,
15110 union data_values **values,
15111 const int64_t n_frames,
15112 const int64_t n_values_per_frame,
15120 for(i = 0; i < n_frames; i++)
15124 if(type == TNG_CHAR_DATA)
15126 for(j = 0; j < n_values_per_frame; j++)
15130 free(values[i][j].c);
15131 values[i][j].c = 0;
15143 return(TNG_SUCCESS);
15146 static tng_function_status tng_particle_data_values_alloc
15147 (const tng_trajectory_t tng_data,
15148 union data_values ****values,
15149 const int64_t n_frames,
15150 const int64_t n_particles,
15151 const int64_t n_values_per_frame,
15155 tng_function_status stat;
15157 if(n_particles == 0 || n_values_per_frame == 0)
15159 return(TNG_FAILURE);
15164 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15165 n_particles, n_values_per_frame,
15167 if(stat != TNG_SUCCESS)
15169 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15170 __FILE__, __LINE__);
15174 *values = malloc(sizeof(union data_values **) * n_frames);
15177 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15178 sizeof(union data_values **) * n_frames,
15179 __FILE__, __LINE__);
15180 return(TNG_CRITICAL);
15184 for(i = 0; i < n_frames; i++)
15186 (*values)[i] = malloc(sizeof(union data_values *) *
15190 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15191 sizeof(union data_values *) * n_particles,
15192 __FILE__, __LINE__);
15195 return(TNG_CRITICAL);
15197 for(j = 0; j < n_particles; j++)
15199 (*values)[i][j] = malloc(sizeof(union data_values) *
15200 n_values_per_frame);
15201 if(!(*values)[i][j])
15203 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15204 sizeof(union data_values *) * n_particles,
15205 __FILE__, __LINE__);
15206 tng_particle_data_values_free(tng_data, *values, n_frames,
15207 n_particles, n_values_per_frame,
15210 return(TNG_CRITICAL);
15214 return(TNG_SUCCESS);
15217 /* FIXME: This needs ****values */
15218 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15219 (const tng_trajectory_t tng_data,
15220 union data_values ***values,
15221 const int64_t n_frames,
15222 const int64_t n_particles,
15223 const int64_t n_values_per_frame,
15231 for(i = 0; i < n_frames; i++)
15235 for(j = 0; j < n_particles; j++)
15237 if(type == TNG_CHAR_DATA)
15239 for(k = 0; k < n_values_per_frame; k++)
15241 if(values[i][j][k].c)
15243 free(values[i][j][k].c);
15244 values[i][j][k].c = 0;
15248 free(values[i][j]);
15259 return(TNG_SUCCESS);
15263 tng_function_status DECLSPECDLLEXPORT tng_data_get
15264 (tng_trajectory_t tng_data,
15265 const int64_t block_id,
15266 union data_values ***values,
15268 int64_t *n_values_per_frame,
15271 int64_t i, j, file_pos, block_index;
15274 tng_non_particle_data_t data;
15275 tng_trajectory_frame_set_t frame_set;
15276 tng_gen_block_t block;
15277 tng_function_status stat;
15279 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15280 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15281 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15282 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15284 frame_set = &tng_data->current_trajectory_frame_set;
15289 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15291 tng_block_init(&block);
15292 file_pos = ftello(tng_data->input_file);
15293 /* Read all blocks until next frame set block */
15294 stat = tng_block_header_read(tng_data, block);
15295 while(file_pos < tng_data->input_file_len &&
15296 stat != TNG_CRITICAL &&
15297 block->id != TNG_TRAJECTORY_FRAME_SET &&
15300 /* Use hash by default */
15301 stat = tng_block_read_next(tng_data, block,
15303 if(stat != TNG_CRITICAL)
15305 file_pos = ftello(tng_data->input_file);
15306 if(file_pos < tng_data->input_file_len)
15308 stat = tng_block_header_read(tng_data, block);
15312 tng_block_destroy(&block);
15313 if(stat == TNG_CRITICAL)
15315 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15316 file_pos, __FILE__, __LINE__);
15320 for(i = 0; i < frame_set->n_data_blocks; i++)
15322 data = &frame_set->tr_data[i];
15323 if(data->block_id == block_id)
15329 if(block_index < 0)
15331 return(TNG_FAILURE);
15335 *n_frames = tng_max_i64(1, data->n_frames);
15336 *n_values_per_frame = data->n_values_per_frame;
15337 *type = data->datatype;
15341 if(tng_data_values_alloc(tng_data, values, *n_frames,
15342 *n_values_per_frame,
15346 return(TNG_CRITICAL);
15352 case TNG_CHAR_DATA:
15353 for(i = 0; i < *n_frames; i++)
15355 for(j = 0; j < *n_values_per_frame; j++)
15357 len = strlen(data->strings[i][j]) + 1;
15358 (*values)[i][j].c = malloc(len);
15359 strncpy((*values)[i][j].c, data->strings[i][j], len);
15364 size = sizeof(int);
15365 for(i = 0; i < *n_frames; i++)
15367 for(j = 0; j < *n_values_per_frame; j++)
15369 (*values)[i][j].i = *(int *)((char *)data->values + size *
15370 (i*(*n_values_per_frame) + j));
15374 case TNG_FLOAT_DATA:
15375 size = sizeof(float);
15376 for(i = 0; i < *n_frames; i++)
15378 for(j = 0; j < *n_values_per_frame; j++)
15380 (*values)[i][j].f = *(float *)((char *)data->values + size *
15381 (i*(*n_values_per_frame) + j));
15385 case TNG_DOUBLE_DATA:
15387 size = sizeof(double);
15388 for(i = 0; i < *n_frames; i++)
15390 for(j = 0; j < *n_values_per_frame; j++)
15392 (*values)[i][j].d = *(double *)((char *)data->values + size *
15393 (i*(*n_values_per_frame) + j));
15398 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15400 return(TNG_SUCCESS);
15403 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15404 const int64_t block_id,
15407 int64_t *stride_length,
15408 int64_t *n_values_per_frame,
15411 int64_t file_pos, data_size, n_frames_div, block_index;
15413 tng_non_particle_data_t data;
15414 tng_trajectory_frame_set_t frame_set;
15415 tng_gen_block_t block;
15417 tng_function_status stat;
15419 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15420 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15421 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15422 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15423 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15425 frame_set = &tng_data->current_trajectory_frame_set;
15430 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15432 tng_block_init(&block);
15433 file_pos = ftello(tng_data->input_file);
15434 /* Read all blocks until next frame set block */
15435 stat = tng_block_header_read(tng_data, block);
15436 while(file_pos < tng_data->input_file_len &&
15437 stat != TNG_CRITICAL &&
15438 block->id != TNG_TRAJECTORY_FRAME_SET &&
15441 /* Use hash by default */
15442 stat = tng_block_read_next(tng_data, block,
15444 if(stat != TNG_CRITICAL)
15446 file_pos = ftello(tng_data->input_file);
15447 if(file_pos < tng_data->input_file_len)
15449 stat = tng_block_header_read(tng_data, block);
15453 tng_block_destroy(&block);
15454 if(stat == TNG_CRITICAL)
15456 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15457 file_pos, __FILE__, __LINE__);
15461 for(i = 0; i < frame_set->n_data_blocks; i++)
15463 data = &frame_set->tr_data[i];
15464 if(data->block_id == block_id)
15470 if(block_index < 0)
15472 return(TNG_FAILURE);
15476 *type = data->datatype;
15480 case TNG_CHAR_DATA:
15481 return(TNG_FAILURE);
15483 size = sizeof(int64_t);
15485 case TNG_FLOAT_DATA:
15486 size = sizeof(float);
15488 case TNG_DOUBLE_DATA:
15490 size = sizeof(double);
15493 *n_frames = data->n_frames;
15494 *n_values_per_frame = data->n_values_per_frame;
15495 *stride_length = data->stride_length;
15496 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15497 *n_frames / *stride_length;
15499 data_size = n_frames_div * size *
15500 *n_values_per_frame;
15502 temp = realloc(*values, data_size);
15505 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15506 data_size, __FILE__, __LINE__);
15509 return(TNG_CRITICAL);
15514 memcpy(*values, data->values, data_size);
15516 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15518 return(TNG_SUCCESS);
15521 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15522 (tng_trajectory_t tng_data,
15523 const int64_t block_id,
15524 const int64_t start_frame_nr,
15525 const int64_t end_frame_nr,
15526 const char hash_mode,
15527 union data_values ***values,
15528 int64_t *n_values_per_frame,
15531 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15532 int64_t block_index;
15535 tng_non_particle_data_t data;
15536 tng_trajectory_frame_set_t frame_set;
15537 tng_gen_block_t block;
15538 tng_function_status stat;
15540 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15541 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15542 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15543 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15547 frame_set = &tng_data->current_trajectory_frame_set;
15548 first_frame = frame_set->first_frame;
15550 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15551 if(stat != TNG_SUCCESS)
15557 /* Do not re-read the frame set. */
15558 if(first_frame != frame_set->first_frame ||
15559 frame_set->n_data_blocks <= 0)
15561 tng_block_init(&block);
15562 file_pos = ftello(tng_data->input_file);
15563 /* Read all blocks until next frame set block */
15564 stat = tng_block_header_read(tng_data, block);
15565 while(file_pos < tng_data->input_file_len &&
15566 stat != TNG_CRITICAL &&
15567 block->id != TNG_TRAJECTORY_FRAME_SET &&
15570 stat = tng_block_read_next(tng_data, block,
15572 if(stat != TNG_CRITICAL)
15574 file_pos = ftello(tng_data->input_file);
15575 if(file_pos < tng_data->input_file_len)
15577 stat = tng_block_header_read(tng_data, block);
15581 tng_block_destroy(&block);
15582 if(stat == TNG_CRITICAL)
15584 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15585 file_pos, __FILE__, __LINE__);
15591 /* See if there is a data block of this ID.
15592 * Start checking the last read frame set */
15593 for(i = 0; i < frame_set->n_data_blocks; i++)
15595 data = &frame_set->tr_data[i];
15596 if(data->block_id == block_id)
15603 if(block_index < 0)
15605 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15606 block_id, __FILE__, __LINE__);
15607 return(TNG_FAILURE);
15610 n_frames = end_frame_nr - start_frame_nr + 1;
15611 *n_values_per_frame = data->n_values_per_frame;
15612 *type = data->datatype;
15616 if(tng_data_values_alloc(tng_data, values, n_frames,
15617 *n_values_per_frame,
15618 *type) != TNG_SUCCESS)
15620 return(TNG_CRITICAL);
15624 current_frame_pos = start_frame_nr - frame_set->first_frame;
15625 /* It's not very elegant to reuse so much of the code in the different case
15626 * statements, but it's unnecessarily slow to have the switch-case block
15627 * inside the for loops. */
15630 case TNG_CHAR_DATA:
15631 for(i=0; i<n_frames; i++)
15633 if(current_frame_pos == frame_set->n_frames)
15635 stat = tng_frame_set_read_next(tng_data, hash_mode);
15636 if(stat != TNG_SUCCESS)
15640 current_frame_pos = 0;
15642 for(j = 0; j < *n_values_per_frame; j++)
15644 len = strlen(data->strings[current_frame_pos][j]) + 1;
15645 (*values)[i][j].c = malloc(len);
15646 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15648 current_frame_pos++;
15652 size = sizeof(int);
15653 for(i=0; i<n_frames; i++)
15655 if(current_frame_pos == frame_set->n_frames)
15657 stat = tng_frame_set_read_next(tng_data, hash_mode);
15658 if(stat != TNG_SUCCESS)
15662 current_frame_pos = 0;
15664 for(j = 0; j < *n_values_per_frame; j++)
15666 (*values)[i][j].i = *(int *)((char *)data->values + size *
15667 (current_frame_pos *
15668 (*n_values_per_frame) + j));
15670 current_frame_pos++;
15673 case TNG_FLOAT_DATA:
15674 size = sizeof(float);
15675 for(i=0; i<n_frames; i++)
15677 if(current_frame_pos == frame_set->n_frames)
15679 stat = tng_frame_set_read_next(tng_data, hash_mode);
15680 if(stat != TNG_SUCCESS)
15684 current_frame_pos = 0;
15686 for(j = 0; j < *n_values_per_frame; j++)
15688 (*values)[i][j].f = *(float *)((char *)data->values + size *
15689 (current_frame_pos *
15690 (*n_values_per_frame) + j));
15692 current_frame_pos++;
15695 case TNG_DOUBLE_DATA:
15697 size = sizeof(double);
15698 for(i=0; i<n_frames; i++)
15700 if(current_frame_pos == frame_set->n_frames)
15702 stat = tng_frame_set_read_next(tng_data, hash_mode);
15703 if(stat != TNG_SUCCESS)
15707 current_frame_pos = 0;
15709 for(j = 0; j < *n_values_per_frame; j++)
15711 (*values)[i][j].d = *(double *)((char *)data->values + size *
15712 (current_frame_pos *
15713 (*n_values_per_frame) + j));
15715 current_frame_pos++;
15719 data->last_retrieved_frame = end_frame_nr;
15721 return(TNG_SUCCESS);
15724 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15725 (tng_trajectory_t tng_data,
15726 const int64_t block_id,
15727 const int64_t start_frame_nr,
15728 const int64_t end_frame_nr,
15729 const char hash_mode,
15731 int64_t *stride_length,
15732 int64_t *n_values_per_frame,
15735 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15736 int64_t file_pos, current_frame_pos, data_size, frame_size;
15737 int64_t last_frame_pos;
15739 tng_trajectory_frame_set_t frame_set;
15740 tng_non_particle_data_t np_data;
15741 tng_gen_block_t block;
15742 void *current_values = 0, *temp;
15743 tng_function_status stat;
15745 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15746 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15747 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15748 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15749 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15751 frame_set = &tng_data->current_trajectory_frame_set;
15752 first_frame = frame_set->first_frame;
15754 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15755 if(stat != TNG_SUCCESS)
15760 /* Do not re-read the frame set and only need the requested block. */
15761 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15762 stat = tng_data_find(tng_data, block_id, &np_data);
15763 if(first_frame != frame_set->first_frame ||
15764 stat != TNG_SUCCESS)
15766 tng_block_init(&block);
15767 if(stat != TNG_SUCCESS)
15769 fseeko(tng_data->input_file,
15770 tng_data->current_trajectory_frame_set_input_file_pos,
15772 stat = tng_block_header_read(tng_data, block);
15773 if(stat != TNG_SUCCESS)
15775 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15776 __FILE__, __LINE__);
15780 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15782 file_pos = ftello(tng_data->input_file);
15783 /* Read until next frame set block */
15784 stat = tng_block_header_read(tng_data, block);
15785 while(file_pos < tng_data->input_file_len &&
15786 stat != TNG_CRITICAL &&
15787 block->id != TNG_TRAJECTORY_FRAME_SET &&
15790 if(block->id == block_id)
15792 stat = tng_block_read_next(tng_data, block,
15794 if(stat != TNG_CRITICAL)
15796 file_pos = ftello(tng_data->input_file);
15797 if(file_pos < tng_data->input_file_len)
15799 stat = tng_block_header_read(tng_data, block);
15805 file_pos += block->block_contents_size + block->header_contents_size;
15806 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15807 if(file_pos < tng_data->input_file_len)
15809 stat = tng_block_header_read(tng_data, block);
15813 tng_block_destroy(&block);
15814 if(stat == TNG_CRITICAL)
15816 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15817 file_pos, __FILE__, __LINE__);
15822 stat = tng_data_find(tng_data, block_id, &np_data);
15823 if(stat != TNG_SUCCESS)
15828 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15829 &n_frames, stride_length,
15830 n_values_per_frame, type);
15832 if(stat != TNG_SUCCESS)
15836 free(current_values);
15841 if(n_frames == 1 && n_frames < frame_set->n_frames)
15847 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15852 case TNG_CHAR_DATA:
15853 return(TNG_FAILURE);
15855 size = sizeof(int64_t);
15857 case TNG_FLOAT_DATA:
15858 size = sizeof(float);
15860 case TNG_DOUBLE_DATA:
15862 size = sizeof(double);
15865 n_frames_div = (tot_n_frames % *stride_length) ?
15866 tot_n_frames / *stride_length + 1:
15867 tot_n_frames / *stride_length;
15868 data_size = n_frames_div * size * (*n_values_per_frame);
15870 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15871 size, n_frames_div, data_size);
15873 temp = realloc(*values, data_size);
15876 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15877 data_size, __FILE__, __LINE__);
15880 return(TNG_CRITICAL);
15885 if( n_frames == 1 && n_frames < frame_set->n_frames)
15887 memcpy(*values, current_values, size * (*n_values_per_frame));
15891 current_frame_pos = start_frame_nr - frame_set->first_frame;
15893 frame_size = size * (*n_values_per_frame);
15895 last_frame_pos = tng_min_i64(n_frames,
15896 end_frame_nr - start_frame_nr);
15898 n_frames_div = current_frame_pos / *stride_length;
15899 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15900 last_frame_pos / *stride_length + 1:
15901 last_frame_pos / *stride_length;
15902 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15904 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15905 n_frames_div_2 * frame_size);
15907 current_frame_pos += n_frames - current_frame_pos;
15909 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15911 stat = tng_frame_set_read_next(tng_data, hash_mode);
15912 if(stat != TNG_SUCCESS)
15916 free(current_values);
15923 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15924 &n_frames, stride_length,
15925 n_values_per_frame, type);
15927 if(stat != TNG_SUCCESS)
15931 free(current_values);
15938 last_frame_pos = tng_min_i64(n_frames,
15939 end_frame_nr - current_frame_pos);
15941 n_frames_div = current_frame_pos / *stride_length;
15942 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15943 last_frame_pos / *stride_length + 1:
15944 last_frame_pos / *stride_length;
15945 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15947 memcpy(((char *)*values) + n_frames_div * frame_size,
15949 n_frames_div_2 * frame_size);
15951 current_frame_pos += n_frames;
15957 free(current_values);
15960 np_data->last_retrieved_frame = end_frame_nr;
15962 return(TNG_SUCCESS);
15965 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15966 (tng_trajectory_t tng_data,
15967 const int64_t block_id,
15968 union data_values ****values,
15970 int64_t *n_particles,
15971 int64_t *n_values_per_frame,
15974 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15977 tng_particle_data_t data;
15978 tng_trajectory_frame_set_t frame_set;
15979 tng_gen_block_t block;
15980 char block_type_flag;
15981 tng_function_status stat;
15983 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15984 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15985 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15986 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15987 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15989 frame_set = &tng_data->current_trajectory_frame_set;
15994 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15996 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15998 block_type_flag = TNG_TRAJECTORY_BLOCK;
16002 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16005 tng_block_init(&block);
16006 file_pos = ftello(tng_data->input_file);
16007 /* Read all blocks until next frame set block */
16008 stat = tng_block_header_read(tng_data, block);
16009 while(file_pos < tng_data->input_file_len &&
16010 stat != TNG_CRITICAL &&
16011 block->id != TNG_TRAJECTORY_FRAME_SET &&
16014 /* Use hash by default */
16015 stat = tng_block_read_next(tng_data, block,
16017 if(stat != TNG_CRITICAL)
16019 file_pos = ftello(tng_data->input_file);
16020 if(file_pos < tng_data->input_file_len)
16022 stat = tng_block_header_read(tng_data, block);
16026 tng_block_destroy(&block);
16027 if(stat == TNG_CRITICAL)
16029 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16030 file_pos, __FILE__, __LINE__);
16034 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16036 data = &frame_set->tr_particle_data[i];
16037 if(data->block_id == block_id)
16040 block_type_flag = TNG_TRAJECTORY_BLOCK;
16044 if(block_index < 0)
16046 return(TNG_FAILURE);
16051 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16053 block_type_flag = TNG_TRAJECTORY_BLOCK;
16057 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16061 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16062 tng_data->var_num_atoms_flag)
16064 *n_particles = frame_set->n_particles;
16068 *n_particles = tng_data->n_particles;
16071 *n_frames = tng_max_i64(1, data->n_frames);
16072 *n_values_per_frame = data->n_values_per_frame;
16073 *type = data->datatype;
16077 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16078 *n_particles, *n_values_per_frame,
16082 return(TNG_CRITICAL);
16086 /* It's not very elegant to reuse so much of the code in the different case
16087 * statements, but it's unnecessarily slow to have the switch-case block
16088 * inside the for loops. */
16091 case TNG_CHAR_DATA:
16092 for(i = 0; i < *n_frames; i++)
16094 for(j = 0; j < *n_particles; j++)
16096 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16097 for(k = 0; k < *n_values_per_frame; k++)
16099 len = strlen(data->strings[i][j][k]) + 1;
16100 (*values)[i][mapping][k].c = malloc(len);
16101 strncpy((*values)[i][mapping][k].c,
16102 data->strings[i][j][k], len);
16108 size = sizeof(int);
16109 i_step = (*n_particles) * (*n_values_per_frame);
16110 for(i = 0; i < *n_frames; i++)
16112 for(j = 0; j < *n_particles; j++)
16114 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16115 for(k = 0; k < *n_values_per_frame; k++)
16117 (*values)[i][mapping][k].i = *(int *)
16118 ((char *)data->values + size *
16120 (*n_values_per_frame) + k));
16125 case TNG_FLOAT_DATA:
16126 size = sizeof(float);
16127 i_step = (*n_particles) * (*n_values_per_frame);
16128 for(i = 0; i < *n_frames; i++)
16130 for(j = 0; j < *n_particles; j++)
16132 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16133 for(k = 0; k < *n_values_per_frame; k++)
16135 (*values)[i][mapping][k].f = *(float *)
16136 ((char *)data->values + size *
16138 (*n_values_per_frame) + k));
16143 case TNG_DOUBLE_DATA:
16145 size = sizeof(double);
16146 i_step = (*n_particles) * (*n_values_per_frame);
16147 for(i = 0; i < *n_frames; i++)
16149 for(j = 0; j < *n_particles; j++)
16151 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16152 for(k = 0; k < *n_values_per_frame; k++)
16154 (*values)[i][mapping][k].d = *(double *)
16155 ((char *)data->values + size *
16157 (*n_values_per_frame) + k));
16163 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16165 return(TNG_SUCCESS);
16168 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16169 (tng_trajectory_t tng_data,
16170 const int64_t block_id,
16173 int64_t *stride_length,
16174 int64_t *n_particles,
16175 int64_t *n_values_per_frame,
16178 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16179 int64_t block_index;
16181 tng_particle_data_t data;
16182 tng_trajectory_frame_set_t frame_set;
16183 tng_gen_block_t block;
16185 char block_type_flag;
16186 tng_function_status stat;
16188 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16189 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16190 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16191 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16192 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16194 frame_set = &tng_data->current_trajectory_frame_set;
16199 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16201 tng_block_init(&block);
16202 file_pos = ftello(tng_data->input_file);
16203 /* Read all blocks until next frame set block */
16204 stat = tng_block_header_read(tng_data, block);
16205 while(file_pos < tng_data->input_file_len &&
16206 stat != TNG_CRITICAL &&
16207 block->id != TNG_TRAJECTORY_FRAME_SET &&
16210 /* Use hash by default */
16211 stat = tng_block_read_next(tng_data, block,
16213 if(stat != TNG_CRITICAL)
16215 file_pos = ftello(tng_data->input_file);
16216 if(file_pos < tng_data->input_file_len)
16218 stat = tng_block_header_read(tng_data, block);
16222 tng_block_destroy(&block);
16223 if(stat == TNG_CRITICAL)
16225 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16226 file_pos, __FILE__, __LINE__);
16230 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16232 data = &frame_set->tr_particle_data[i];
16233 if(data->block_id == block_id)
16239 if(block_index < 0)
16241 return(TNG_FAILURE);
16245 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16247 block_type_flag = TNG_TRAJECTORY_BLOCK;
16251 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16254 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16255 tng_data->var_num_atoms_flag)
16257 *n_particles = frame_set->n_particles;
16261 *n_particles = tng_data->n_particles;
16264 *type = data->datatype;
16268 case TNG_CHAR_DATA:
16269 return(TNG_FAILURE);
16271 size = sizeof(int64_t);
16273 case TNG_FLOAT_DATA:
16274 size = sizeof(float);
16276 case TNG_DOUBLE_DATA:
16278 size = sizeof(double);
16281 *n_frames = tng_max_i64(1, data->n_frames);
16282 *n_values_per_frame = data->n_values_per_frame;
16283 *stride_length = data->stride_length;
16285 n_frames_div = (*n_frames % *stride_length) ?
16286 *n_frames / *stride_length + 1:
16287 *n_frames / *stride_length;
16289 data_size = n_frames_div * size * (*n_particles) *
16290 (*n_values_per_frame);
16292 temp = realloc(*values, data_size);
16295 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16296 data_size, __FILE__, __LINE__);
16299 return(TNG_CRITICAL);
16304 if(frame_set->n_mapping_blocks <= 0)
16306 memcpy(*values, data->values, data_size);
16310 i_step = (*n_particles) * (*n_values_per_frame);
16311 for(i = 0; i < *n_frames; i++)
16313 for(j = 0; j < *n_particles; j++)
16315 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16316 memcpy(((char *)*values) + size * (i * i_step + mapping *
16317 (*n_values_per_frame)),
16318 (char *)data->values + size *
16319 (i * i_step + j * (*n_values_per_frame)),
16320 size * (*n_values_per_frame));
16325 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16327 return(TNG_SUCCESS);
16330 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16331 (tng_trajectory_t tng_data,
16332 const int64_t block_id,
16333 const int64_t start_frame_nr,
16334 const int64_t end_frame_nr,
16335 const char hash_mode,
16336 union data_values ****values,
16337 int64_t *n_particles,
16338 int64_t *n_values_per_frame,
16341 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16342 int64_t first_frame, block_index;
16345 tng_particle_data_t data;
16346 tng_trajectory_frame_set_t frame_set;
16347 tng_gen_block_t block;
16348 char block_type_flag;
16349 tng_function_status stat;
16351 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16352 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16353 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16354 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16355 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16359 frame_set = &tng_data->current_trajectory_frame_set;
16360 first_frame = frame_set->first_frame;
16362 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16363 if(stat != TNG_SUCCESS)
16368 /* Do not re-read the frame set. */
16369 if(first_frame != frame_set->first_frame ||
16370 frame_set->n_particle_data_blocks <= 0)
16372 tng_block_init(&block);
16373 file_pos = ftello(tng_data->input_file);
16374 /* Read all blocks until next frame set block */
16375 stat = tng_block_header_read(tng_data, block);
16376 while(file_pos < tng_data->input_file_len &&
16377 stat != TNG_CRITICAL &&
16378 block->id != TNG_TRAJECTORY_FRAME_SET &&
16381 stat = tng_block_read_next(tng_data, block,
16383 if(stat != TNG_CRITICAL)
16385 file_pos = ftello(tng_data->input_file);
16386 if(file_pos < tng_data->input_file_len)
16388 stat = tng_block_header_read(tng_data, block);
16392 tng_block_destroy(&block);
16393 if(stat == TNG_CRITICAL)
16395 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16396 file_pos, __FILE__, __LINE__);
16401 /* See if there is already a data block of this ID.
16402 * Start checking the last read frame set */
16403 for(i = frame_set->n_particle_data_blocks; i-- ;)
16405 data = &frame_set->tr_particle_data[i];
16406 if(data->block_id == block_id)
16409 block_type_flag = TNG_TRAJECTORY_BLOCK;
16414 if(block_index < 0)
16416 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16417 block_id, __FILE__, __LINE__);
16418 return(TNG_FAILURE);
16421 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16422 tng_data->var_num_atoms_flag)
16424 *n_particles = frame_set->n_particles;
16428 *n_particles = tng_data->n_particles;
16431 n_frames = end_frame_nr - start_frame_nr + 1;
16432 *n_values_per_frame = data->n_values_per_frame;
16433 *type = data->datatype;
16437 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16438 *n_particles, *n_values_per_frame,
16442 return(TNG_CRITICAL);
16446 current_frame_pos = start_frame_nr - frame_set->first_frame;
16447 /* It's not very elegant to reuse so much of the code in the different case
16448 * statements, but it's unnecessarily slow to have the switch-case block
16449 * inside the for loops. */
16452 case TNG_CHAR_DATA:
16453 for(i=0; i<n_frames; i++)
16455 if(current_frame_pos == frame_set->n_frames)
16457 stat = tng_frame_set_read_next(tng_data, hash_mode);
16458 if(stat != TNG_SUCCESS)
16462 current_frame_pos = 0;
16464 for(j = 0; j < *n_particles; j++)
16466 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16467 for(k = 0; k < *n_values_per_frame; k++)
16469 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16470 (*values)[i][mapping][k].c = malloc(len);
16471 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16474 current_frame_pos++;
16478 size = sizeof(int);
16479 i_step = (*n_particles) * (*n_values_per_frame);
16480 for(i=0; i<n_frames; i++)
16482 if(current_frame_pos == frame_set->n_frames)
16484 stat = tng_frame_set_read_next(tng_data, hash_mode);
16485 if(stat != TNG_SUCCESS)
16489 current_frame_pos = 0;
16491 for(j = 0; j < *n_particles; j++)
16493 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16494 for(k = 0; k < *n_values_per_frame; k++)
16496 (*values)[i][mapping][k].i = *(int *)
16497 ((char *)data->values + size *
16498 (current_frame_pos *
16500 (*n_values_per_frame) + k));
16503 current_frame_pos++;
16506 case TNG_FLOAT_DATA:
16507 size = sizeof(float);
16508 i_step = (*n_particles) * (*n_values_per_frame);
16509 for(i=0; i<n_frames; i++)
16511 if(current_frame_pos == frame_set->n_frames)
16513 stat = tng_frame_set_read_next(tng_data, hash_mode);
16514 if(stat != TNG_SUCCESS)
16518 current_frame_pos = 0;
16520 for(j=0; j<*n_particles; j++)
16522 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16523 for(k=0; k<*n_values_per_frame; k++)
16525 (*values)[i][mapping][k].f = *(float *)
16526 ((char *)data->values + size *
16527 (current_frame_pos *
16529 (*n_values_per_frame) + k));
16532 current_frame_pos++;
16535 case TNG_DOUBLE_DATA:
16537 size = sizeof(double);
16538 i_step = (*n_particles) * (*n_values_per_frame);
16539 for(i=0; i<n_frames; i++)
16541 if(current_frame_pos == frame_set->n_frames)
16543 stat = tng_frame_set_read_next(tng_data, hash_mode);
16544 if(stat != TNG_SUCCESS)
16548 current_frame_pos = 0;
16550 for(j=0; j<*n_particles; j++)
16552 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16553 for(k=0; k<*n_values_per_frame; k++)
16555 (*values)[i][mapping][k].d = *(double *)
16556 ((char *)data->values + size *
16557 (current_frame_pos *
16559 (*n_values_per_frame) + k));
16562 current_frame_pos++;
16566 data->last_retrieved_frame = end_frame_nr;
16568 return(TNG_SUCCESS);
16571 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16572 (tng_trajectory_t tng_data,
16573 const int64_t block_id,
16574 const int64_t start_frame_nr,
16575 const int64_t end_frame_nr,
16576 const char hash_mode,
16578 int64_t *n_particles,
16579 int64_t *stride_length,
16580 int64_t *n_values_per_frame,
16583 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16584 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16586 tng_trajectory_frame_set_t frame_set;
16587 tng_particle_data_t p_data;
16588 tng_gen_block_t block;
16589 void *current_values = 0, *temp;
16590 tng_function_status stat;
16592 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16593 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16594 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16595 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16596 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16597 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16599 frame_set = &tng_data->current_trajectory_frame_set;
16600 first_frame = frame_set->first_frame;
16602 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16603 if(stat != TNG_SUCCESS)
16608 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16609 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16610 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16611 if(first_frame != frame_set->first_frame ||
16612 stat != TNG_SUCCESS)
16614 tng_block_init(&block);
16615 if(stat != TNG_SUCCESS)
16617 fseeko(tng_data->input_file,
16618 tng_data->current_trajectory_frame_set_input_file_pos,
16620 stat = tng_block_header_read(tng_data, block);
16621 if(stat != TNG_SUCCESS)
16623 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16624 __FILE__, __LINE__);
16628 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16630 file_pos = ftello(tng_data->input_file);
16631 /* Read until next frame set block */
16632 stat = tng_block_header_read(tng_data, block);
16633 while(file_pos < tng_data->input_file_len &&
16634 stat != TNG_CRITICAL &&
16635 block->id != TNG_TRAJECTORY_FRAME_SET &&
16638 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16640 stat = tng_block_read_next(tng_data, block,
16642 if(stat != TNG_CRITICAL)
16644 file_pos = ftello(tng_data->input_file);
16645 if(file_pos < tng_data->input_file_len)
16647 stat = tng_block_header_read(tng_data, block);
16653 file_pos += block->block_contents_size + block->header_contents_size;
16654 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16655 if(file_pos < tng_data->input_file_len)
16657 stat = tng_block_header_read(tng_data, block);
16661 tng_block_destroy(&block);
16662 if(stat == TNG_CRITICAL)
16664 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16665 file_pos, __FILE__, __LINE__);
16669 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16670 if(stat != TNG_SUCCESS)
16675 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16676 &n_frames, stride_length, n_particles,
16677 n_values_per_frame, type);
16679 if(stat != TNG_SUCCESS || *n_particles == 0)
16683 free(current_values);
16688 if(n_frames == 1 && n_frames < frame_set->n_frames)
16694 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16699 case TNG_CHAR_DATA:
16700 return(TNG_FAILURE);
16702 size = sizeof(int64_t);
16704 case TNG_FLOAT_DATA:
16705 size = sizeof(float);
16707 case TNG_DOUBLE_DATA:
16709 size = sizeof(double);
16712 n_frames_div = (tot_n_frames % *stride_length) ?
16713 tot_n_frames / *stride_length + 1:
16714 tot_n_frames / *stride_length;
16716 data_size = n_frames_div * size * (*n_particles) *
16717 (*n_values_per_frame);
16719 temp = realloc(*values, data_size);
16722 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16723 data_size, __FILE__, __LINE__);
16726 return(TNG_CRITICAL);
16731 if( n_frames == 1 && n_frames < frame_set->n_frames)
16733 memcpy(*values, current_values, size * (*n_particles) *
16734 (*n_values_per_frame));
16738 current_frame_pos = start_frame_nr - frame_set->first_frame;
16740 frame_size = size * (*n_particles) * (*n_values_per_frame);
16742 last_frame_pos = tng_min_i64(n_frames,
16743 end_frame_nr - start_frame_nr);
16745 n_frames_div = current_frame_pos / *stride_length;
16746 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16747 last_frame_pos / *stride_length + 1:
16748 last_frame_pos / *stride_length;
16749 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16751 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16752 n_frames_div_2 * frame_size);
16754 current_frame_pos += n_frames - current_frame_pos;
16756 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16758 stat = tng_frame_set_read_next(tng_data, hash_mode);
16759 if(stat != TNG_SUCCESS)
16763 free(current_values);
16770 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16771 &n_frames, stride_length, n_particles,
16772 n_values_per_frame, type);
16774 if(stat != TNG_SUCCESS)
16778 free(current_values);
16785 last_frame_pos = tng_min_i64(n_frames,
16786 end_frame_nr - current_frame_pos);
16788 n_frames_div = current_frame_pos / *stride_length;
16789 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16790 last_frame_pos / *stride_length + 1:
16791 last_frame_pos / *stride_length;
16792 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16794 memcpy(((char *)*values) + n_frames_div * frame_size,
16796 n_frames_div_2 * frame_size);
16798 current_frame_pos += n_frames;
16804 free(current_values);
16807 p_data->last_retrieved_frame = end_frame_nr;
16809 return(TNG_SUCCESS);
16812 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16813 (const tng_trajectory_t tng_data,
16814 const int64_t block_id,
16816 int64_t *stride_length)
16818 tng_function_status stat;
16819 tng_non_particle_data_t np_data;
16820 tng_particle_data_t p_data;
16821 int64_t orig_file_pos, file_pos;
16822 int is_particle_data;
16824 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16831 stat = tng_frame_set_of_frame_find(tng_data, frame);
16832 if(stat != TNG_SUCCESS)
16837 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16838 stat = tng_data_find(tng_data, block_id, &np_data);
16839 if(stat != TNG_SUCCESS)
16841 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16842 if(stat != TNG_SUCCESS)
16844 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16845 /* If no specific frame was required read until this data block is found */
16848 file_pos = ftello(tng_data->input_file);
16849 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16851 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16852 file_pos = ftello(tng_data->input_file);
16855 if(stat != TNG_SUCCESS)
16857 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16861 stat = tng_data_find(tng_data, block_id, &np_data);
16862 if(stat != TNG_SUCCESS)
16864 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16865 if(stat != TNG_SUCCESS)
16867 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16873 is_particle_data = 1;
16878 is_particle_data = 0;
16883 is_particle_data = 1;
16888 is_particle_data = 0;
16890 if(is_particle_data)
16892 *stride_length = p_data->stride_length;
16896 *stride_length = np_data->stride_length;
16898 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16900 return(TNG_SUCCESS);
16903 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16904 (const tng_trajectory_t tng_data,
16907 struct tm *time_data;
16910 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16911 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16913 secs = tng_data->time;
16915 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16916 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16917 "%4d-%02d-%02d %02d:%02d:%02d",
16918 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16919 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16921 return(TNG_SUCCESS);
16925 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16926 (const char *filename,
16928 tng_trajectory_t *tng_data_p)
16930 tng_function_status stat;
16932 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16934 if(mode != 'r' && mode != 'w' && mode != 'a')
16936 return(TNG_FAILURE);
16939 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16941 tng_trajectory_destroy(tng_data_p);
16942 return(TNG_CRITICAL);
16945 if(mode == 'r' || mode == 'a')
16947 tng_input_file_set(*tng_data_p, filename);
16949 /* Read the file headers */
16950 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16952 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16954 if(stat != TNG_SUCCESS)
16962 tng_output_file_set(*tng_data_p, filename);
16964 else if(mode == 'a')
16966 if((*tng_data_p)->output_file)
16968 fclose((*tng_data_p)->output_file);
16970 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
16971 fseeko((*tng_data_p)->input_file,
16972 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16975 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16976 if(stat != TNG_SUCCESS)
16978 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16979 __FILE__, __LINE__);
16981 (*tng_data_p)->output_file = 0;
16983 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16984 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16985 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16986 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16987 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16988 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16989 if((*tng_data_p)->input_file)
16991 fclose((*tng_data_p)->input_file);
16992 (*tng_data_p)->input_file = 0;
16994 if((*tng_data_p)->input_file_path)
16996 free((*tng_data_p)->input_file_path);
16997 (*tng_data_p)->input_file_path = 0;
16999 tng_output_append_file_set(*tng_data_p, filename);
17001 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
17004 return(TNG_SUCCESS);
17007 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
17008 (tng_trajectory_t *tng_data_p)
17010 tng_trajectory_frame_set_t frame_set;
17012 if(tng_data_p == 0)
17014 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
17015 __FILE__, __LINE__);
17016 return(TNG_FAILURE);
17019 if(*tng_data_p == 0)
17021 return(TNG_SUCCESS);
17024 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
17026 if(frame_set->n_unwritten_frames > 0)
17028 frame_set->n_frames = frame_set->n_unwritten_frames;
17029 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
17032 return(tng_trajectory_destroy(tng_data_p));
17035 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
17036 (tng_trajectory_t tng_data,
17037 const int64_t frame_nr,
17040 int64_t first_frame;
17041 tng_trajectory_frame_set_t frame_set;
17042 tng_function_status stat;
17044 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17045 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
17047 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
17048 if(stat != TNG_SUCCESS)
17050 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
17051 frame_nr, __FILE__, __LINE__);
17055 frame_set = &tng_data->current_trajectory_frame_set;
17056 first_frame = frame_set->first_frame;
17058 if(tng_data->time_per_frame <= 0)
17060 return(TNG_FAILURE);
17063 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
17065 return(TNG_SUCCESS);
17069 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17070 (tng_trajectory_t tng_data,
17072 int64_t **molecule_cnt_list,
17073 tng_molecule_t *mols)
17075 tng_trajectory_frame_set_t frame_set;
17077 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17078 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17080 *n_mols = tng_data->n_molecules;
17082 frame_set = &tng_data->current_trajectory_frame_set;
17083 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17085 *molecule_cnt_list = frame_set->molecule_cnt_list;
17089 *molecule_cnt_list = tng_data->molecule_cnt_list;
17092 *mols = tng_data->molecules;
17094 return(TNG_SUCCESS);
17098 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17099 (tng_trajectory_t tng_data,
17102 tng_molecule_t *mol)
17104 tng_function_status stat;
17106 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17107 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17109 stat = tng_molecule_add(tng_data, name, mol);
17110 if(stat != TNG_SUCCESS)
17114 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17119 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17120 (tng_trajectory_t tng_data,
17121 const tng_molecule_t mol,
17122 int64_t *n_particles,
17127 char ***chain_names,
17128 int64_t **chain_ids)
17136 *n_particles = mol->n_atoms;
17138 *names = malloc(sizeof(char *) * *n_particles);
17139 *types = malloc(sizeof(char *) * *n_particles);
17140 *res_names = malloc(sizeof(char *) * *n_particles);
17141 *chain_names = malloc(sizeof(char *) * *n_particles);
17142 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17143 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17145 for(i = 0; i < *n_particles; i++)
17147 atom = &mol->atoms[i];
17148 res = atom->residue;
17149 chain = res->chain;
17150 (*names)[i] = malloc(strlen(atom->name));
17151 strcpy(*names[i], atom->name);
17152 (*types)[i] = malloc(strlen(atom->atom_type));
17153 strcpy(*types[i], atom->atom_type);
17154 (*res_names)[i] = malloc(strlen(res->name));
17155 strcpy(*res_names[i], res->name);
17156 (*chain_names)[i] = malloc(strlen(chain->name));
17157 strcpy(*chain_names[i], chain->name);
17158 (*res_ids)[i] = res->id;
17159 (*chain_ids)[i] = chain->id;
17162 return(TNG_SUCCESS);
17165 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17166 (tng_trajectory_t tng_data,
17167 tng_molecule_t mol,
17168 const int64_t n_particles,
17169 const char **names,
17170 const char **types,
17171 const char **res_names,
17172 const int64_t *res_ids,
17173 const char **chain_names,
17174 const int64_t *chain_ids)
17178 tng_residue_t residue;
17180 tng_function_status stat;
17182 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17183 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17184 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17185 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17186 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17187 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17188 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17190 for(i = 0; i < n_particles; i++)
17192 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17193 &chain) == TNG_FAILURE)
17195 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17197 if(stat != TNG_SUCCESS)
17202 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17203 &residue) == TNG_FAILURE)
17205 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17207 if(stat != TNG_SUCCESS)
17212 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17213 if(stat != TNG_SUCCESS)
17218 return(TNG_SUCCESS);
17221 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17222 (tng_trajectory_t tng_data,
17223 float **positions, int64_t *stride_length)
17225 int64_t n_frames, n_particles, n_values_per_frame;
17227 tng_function_status stat;
17229 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17230 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17231 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17233 stat = tng_num_frames_get(tng_data, &n_frames);
17234 if(stat != TNG_SUCCESS)
17239 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17240 0, n_frames - 1, TNG_USE_HASH,
17241 (void **)positions,
17244 &n_values_per_frame,
17250 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17251 (tng_trajectory_t tng_data,
17252 float **velocities, int64_t *stride_length)
17254 int64_t n_frames, n_particles, n_values_per_frame;
17256 tng_function_status stat;
17258 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17259 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17260 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17262 stat = tng_num_frames_get(tng_data, &n_frames);
17263 if(stat != TNG_SUCCESS)
17268 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17269 0, n_frames - 1, TNG_USE_HASH,
17270 (void **)velocities,
17273 &n_values_per_frame,
17279 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17280 (tng_trajectory_t tng_data,
17281 float **forces, int64_t *stride_length)
17283 int64_t n_frames, n_particles, n_values_per_frame;
17285 tng_function_status stat;
17287 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17288 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17289 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17291 stat = tng_num_frames_get(tng_data, &n_frames);
17292 if(stat != TNG_SUCCESS)
17297 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17298 0, n_frames - 1, TNG_USE_HASH,
17302 &n_values_per_frame,
17308 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17309 (tng_trajectory_t tng_data,
17311 int64_t *stride_length)
17313 int64_t n_frames, n_values_per_frame;
17315 tng_function_status stat;
17317 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17318 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17319 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17321 stat = tng_num_frames_get(tng_data, &n_frames);
17322 if(stat != TNG_SUCCESS)
17327 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17328 0, n_frames - 1, TNG_USE_HASH,
17329 (void **)box_shape,
17331 &n_values_per_frame,
17337 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17338 (tng_trajectory_t tng_data,
17339 const int64_t block_id,
17342 int64_t *retrieved_frame_number,
17343 double *retrieved_time)
17345 tng_trajectory_frame_set_t frame_set;
17346 tng_particle_data_t data = 0;
17347 tng_function_status stat;
17349 int64_t i, data_size, n_particles, file_pos;
17352 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17353 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17354 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17355 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17356 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17358 frame_set = &tng_data->current_trajectory_frame_set;
17360 stat = tng_particle_data_find(tng_data, block_id, &data);
17361 if(stat != TNG_SUCCESS)
17363 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17364 file_pos = ftello(tng_data->input_file);
17365 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17367 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17368 file_pos = ftello(tng_data->input_file);
17370 if(stat != TNG_SUCCESS)
17374 stat = tng_particle_data_find(tng_data, block_id, &data);
17375 if(stat != TNG_SUCCESS)
17380 if(data->last_retrieved_frame < 0)
17382 fseeko(tng_data->input_file,
17383 tng_data->first_trajectory_frame_set_input_file_pos,
17385 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17386 if(stat != TNG_SUCCESS)
17390 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17391 if(stat != TNG_SUCCESS)
17396 i = data->first_frame_with_data;
17400 if(data->n_frames == 1)
17402 i = data->last_retrieved_frame + 1;
17406 i = data->last_retrieved_frame + data->stride_length;
17408 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17410 stat = tng_frame_set_of_frame_find(tng_data, i);
17411 if(stat != TNG_SUCCESS)
17413 /* If the frame set search found the frame set after the starting
17414 * frame set there is a gap in the frame sets. So, even if the frame
17415 * was not found the next frame with data is still in the found
17417 if(stat == TNG_CRITICAL)
17421 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17423 return(TNG_FAILURE);
17425 i = frame_set->first_frame;
17428 if(data->last_retrieved_frame < frame_set->first_frame)
17430 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17431 if(stat != TNG_SUCCESS)
17437 data->last_retrieved_frame = i;
17438 *retrieved_frame_number = i;
17439 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17441 *retrieved_time = frame_set->first_frame_time +
17442 (i - frame_set->first_frame) *
17443 tng_data->time_per_frame;
17447 *retrieved_time = 0;
17450 if(data->stride_length > 1)
17452 i = (i - data->first_frame_with_data) / data->stride_length;
17456 i = (i - frame_set->first_frame);
17459 tng_num_particles_get(tng_data, &n_particles);
17461 *data_type = data->datatype;
17465 case TNG_CHAR_DATA:
17466 return(TNG_FAILURE);
17468 size = sizeof(int64_t);
17470 case TNG_FLOAT_DATA:
17471 size = sizeof(float);
17473 case TNG_DOUBLE_DATA:
17475 size = sizeof(double);
17478 data_size = size * n_particles * data->n_values_per_frame;
17480 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17481 // i, data_size, size, n_particles, data->n_values_per_frame);
17483 temp = realloc(*values, data_size);
17486 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17487 data_size, __FILE__, __LINE__);
17490 return(TNG_CRITICAL);
17495 memcpy(*values, (char *)data->values + i * data_size, data_size);
17497 return(TNG_SUCCESS);
17500 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17501 (tng_trajectory_t tng_data,
17502 const int64_t block_id,
17505 int64_t *retrieved_frame_number,
17506 double *retrieved_time)
17508 tng_trajectory_frame_set_t frame_set;
17509 tng_non_particle_data_t data = 0;
17510 tng_function_status stat;
17512 int64_t i, data_size, file_pos;
17515 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17516 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17517 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17518 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17519 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17521 frame_set = &tng_data->current_trajectory_frame_set;
17523 stat = tng_data_find(tng_data, block_id, &data);
17524 if(stat != TNG_SUCCESS)
17526 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17527 file_pos = ftello(tng_data->input_file);
17528 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17530 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17531 file_pos = ftello(tng_data->input_file);
17533 if(stat != TNG_SUCCESS)
17537 stat = tng_data_find(tng_data, block_id, &data);
17538 if(stat != TNG_SUCCESS)
17543 if(data->last_retrieved_frame < 0)
17545 fseeko(tng_data->input_file,
17546 tng_data->first_trajectory_frame_set_input_file_pos,
17548 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17549 if(stat != TNG_SUCCESS)
17553 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17554 if(stat != TNG_SUCCESS)
17559 i = data->first_frame_with_data;
17563 if(data->n_frames == 1)
17565 i = data->last_retrieved_frame + 1;
17569 i = data->last_retrieved_frame + data->stride_length;
17571 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17573 stat = tng_frame_set_of_frame_find(tng_data, i);
17574 if(stat != TNG_SUCCESS)
17576 /* If the frame set search found the frame set after the starting
17577 * frame set there is a gap in the frame sets. So, even if the frame
17578 * was not found the next frame with data is still in the found
17580 if(stat == TNG_CRITICAL)
17584 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17586 return(TNG_FAILURE);
17588 i = frame_set->first_frame;
17591 if(data->last_retrieved_frame < frame_set->first_frame)
17593 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17594 if(stat != TNG_SUCCESS)
17600 data->last_retrieved_frame = i;
17601 *retrieved_frame_number = i;
17602 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17604 *retrieved_time = frame_set->first_frame_time +
17605 (i - frame_set->first_frame) *
17606 tng_data->time_per_frame;
17610 *retrieved_time = 0;
17613 if(data->stride_length > 1)
17615 i = (i - data->first_frame_with_data) / data->stride_length;
17619 i = (i - frame_set->first_frame);
17622 *data_type = data->datatype;
17626 case TNG_CHAR_DATA:
17627 return(TNG_FAILURE);
17629 size = sizeof(int64_t);
17631 case TNG_FLOAT_DATA:
17632 size = sizeof(float);
17634 case TNG_DOUBLE_DATA:
17636 size = sizeof(double);
17639 data_size = size * data->n_values_per_frame;
17641 temp = realloc(*values, data_size);
17644 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17645 data_size, __FILE__, __LINE__);
17648 return(TNG_CRITICAL);
17653 memcpy(*values, (char *)data->values + i * data_size, data_size);
17655 return(TNG_SUCCESS);
17658 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17659 (tng_trajectory_t tng_data,
17660 const int64_t first_frame,
17661 const int64_t last_frame,
17663 int64_t *stride_length)
17665 int64_t n_particles, n_values_per_frame;
17667 tng_function_status stat;
17669 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17670 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17671 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17672 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17674 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17675 first_frame, last_frame,
17677 (void **)positions,
17680 &n_values_per_frame,
17686 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17687 (tng_trajectory_t tng_data,
17688 const int64_t first_frame,
17689 const int64_t last_frame,
17690 float **velocities,
17691 int64_t *stride_length)
17693 int64_t n_particles, n_values_per_frame;
17695 tng_function_status stat;
17697 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17698 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17699 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17700 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17702 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17703 first_frame, last_frame,
17705 (void **)velocities,
17708 &n_values_per_frame,
17714 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17715 (tng_trajectory_t tng_data,
17716 const int64_t first_frame,
17717 const int64_t last_frame,
17719 int64_t *stride_length)
17721 int64_t n_particles, n_values_per_frame;
17723 tng_function_status stat;
17725 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17726 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17727 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17728 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17730 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17731 first_frame, last_frame,
17736 &n_values_per_frame,
17742 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17743 (tng_trajectory_t tng_data,
17744 const int64_t first_frame,
17745 const int64_t last_frame,
17747 int64_t *stride_length)
17749 int64_t n_values_per_frame;
17751 tng_function_status stat;
17753 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17754 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17755 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17756 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17758 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17759 first_frame, last_frame,
17761 (void **)box_shape,
17763 &n_values_per_frame,
17769 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17770 (tng_trajectory_t tng_data,
17772 const int64_t n_values_per_frame,
17773 const int64_t block_id,
17774 const char *block_name,
17775 const char particle_dependency,
17776 const char compression)
17778 tng_trajectory_frame_set_t frame_set;
17779 tng_particle_data_t p_data;
17780 tng_non_particle_data_t np_data;
17781 int64_t n_particles, n_frames;
17782 tng_function_status stat;
17784 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17785 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17789 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17790 i, __FILE__, __LINE__);
17791 return(TNG_FAILURE);
17794 frame_set = &tng_data->current_trajectory_frame_set;
17796 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17798 n_frames = tng_data->frame_set_n_frames;
17800 stat = tng_frame_set_new(tng_data, 0, n_frames);
17801 if(stat != TNG_SUCCESS)
17803 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17810 n_frames = frame_set->n_frames;
17813 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17815 tng_num_particles_get(tng_data, &n_particles);
17816 if(n_particles <= 0)
17818 return(TNG_FAILURE);
17821 if(tng_particle_data_find(tng_data, block_id, &p_data)
17824 stat = tng_particle_data_block_add(tng_data, block_id,
17827 TNG_TRAJECTORY_BLOCK,
17828 n_frames, n_values_per_frame, i,
17831 if(stat != TNG_SUCCESS)
17833 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17834 __FILE__, __LINE__);
17837 p_data = &frame_set->tr_particle_data[frame_set->
17838 n_particle_data_blocks - 1];
17839 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17841 n_values_per_frame);
17842 if(stat != TNG_SUCCESS)
17844 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17845 __FILE__, __LINE__);
17851 if(p_data->stride_length != i)
17853 p_data->stride_length = i;
17854 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17856 n_values_per_frame);
17857 if(stat != TNG_SUCCESS)
17859 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17860 __FILE__, __LINE__);
17868 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17870 stat = tng_data_block_add(tng_data, block_id, block_name,
17871 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17872 n_frames, n_values_per_frame,
17873 i, compression, 0);
17874 if(stat != TNG_SUCCESS)
17876 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17877 __FILE__, __LINE__);
17880 np_data = &frame_set->tr_data[frame_set->
17881 n_data_blocks - 1];
17882 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17883 i, n_values_per_frame);
17884 if(stat != TNG_SUCCESS)
17886 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17887 __FILE__, __LINE__);
17893 if(np_data->stride_length != i)
17895 np_data->stride_length = i;
17896 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17897 i, n_values_per_frame);
17898 if(stat != TNG_SUCCESS)
17900 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17901 __FILE__, __LINE__);
17908 return(TNG_SUCCESS);
17911 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17912 (tng_trajectory_t tng_data,
17914 const int64_t n_values_per_frame,
17915 const int64_t block_id,
17916 const char *block_name,
17917 const char particle_dependency,
17918 const char compression)
17920 tng_trajectory_frame_set_t frame_set;
17921 tng_particle_data_t p_data;
17922 tng_non_particle_data_t np_data;
17923 int64_t n_particles, n_frames;
17924 tng_function_status stat;
17926 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17927 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17931 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17932 i, __FILE__, __LINE__);
17933 return(TNG_FAILURE);
17936 frame_set = &tng_data->current_trajectory_frame_set;
17938 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17940 n_frames = tng_data->frame_set_n_frames;
17942 stat = tng_frame_set_new(tng_data, 0, n_frames);
17943 if(stat != TNG_SUCCESS)
17945 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17952 n_frames = frame_set->n_frames;
17955 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17957 tng_num_particles_get(tng_data, &n_particles);
17959 if(n_particles <= 0)
17961 return(TNG_FAILURE);
17964 if(tng_particle_data_find(tng_data, block_id, &p_data)
17967 stat = tng_particle_data_block_add(tng_data, block_id,
17970 TNG_TRAJECTORY_BLOCK,
17971 n_frames, n_values_per_frame, i,
17974 if(stat != TNG_SUCCESS)
17976 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17977 __FILE__, __LINE__);
17980 p_data = &frame_set->tr_particle_data[frame_set->
17981 n_particle_data_blocks - 1];
17982 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17984 n_values_per_frame);
17985 if(stat != TNG_SUCCESS)
17987 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17988 __FILE__, __LINE__);
17994 p_data->stride_length = i;
17999 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18001 stat = tng_data_block_add(tng_data, block_id, block_name,
18002 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
18003 n_frames, n_values_per_frame,
18004 i, compression, 0);
18005 if(stat != TNG_SUCCESS)
18007 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18008 __FILE__, __LINE__);
18011 np_data = &frame_set->tr_data[frame_set->
18012 n_data_blocks - 1];
18013 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18014 i, n_values_per_frame);
18015 if(stat != TNG_SUCCESS)
18017 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18018 __FILE__, __LINE__);
18024 np_data->stride_length = i;
18028 return(TNG_SUCCESS);
18031 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
18032 (tng_trajectory_t tng_data,
18034 const int64_t n_values_per_frame,
18035 const int64_t block_id,
18036 const char *block_name,
18037 const char particle_dependency,
18038 const char compression)
18040 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
18041 "See documentation. %s: %d", __FILE__, __LINE__);
18042 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
18043 block_id, block_name,
18044 particle_dependency,
18047 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18048 (tng_trajectory_t tng_data,
18051 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18052 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18054 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18055 TNG_TRAJ_POSITIONS,
18057 TNG_PARTICLE_BLOCK_DATA,
18058 TNG_TNG_COMPRESSION));
18061 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18062 (tng_trajectory_t tng_data,
18065 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18066 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18068 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18069 TNG_TRAJ_POSITIONS,
18071 TNG_PARTICLE_BLOCK_DATA,
18072 TNG_TNG_COMPRESSION));
18075 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18076 (tng_trajectory_t tng_data,
18079 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18080 "See documentation. %s: %d", __FILE__, __LINE__);
18081 return(tng_util_pos_write_interval_set(tng_data, i));
18084 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18085 (tng_trajectory_t tng_data,
18088 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18089 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18091 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18092 TNG_TRAJ_VELOCITIES,
18094 TNG_PARTICLE_BLOCK_DATA,
18095 TNG_TNG_COMPRESSION));
18098 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18099 (tng_trajectory_t tng_data,
18102 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18103 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18105 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18106 TNG_TRAJ_VELOCITIES,
18108 TNG_PARTICLE_BLOCK_DATA,
18109 TNG_TNG_COMPRESSION));
18112 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18113 (tng_trajectory_t tng_data,
18116 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18117 "See documentation. %s: %d", __FILE__, __LINE__);
18118 return(tng_util_vel_write_interval_set(tng_data, i));
18121 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18122 (tng_trajectory_t tng_data,
18125 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18126 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18128 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18131 TNG_PARTICLE_BLOCK_DATA,
18132 TNG_GZIP_COMPRESSION));
18135 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18136 (tng_trajectory_t tng_data,
18139 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18140 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18142 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18145 TNG_PARTICLE_BLOCK_DATA,
18146 TNG_GZIP_COMPRESSION));
18149 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18150 (tng_trajectory_t tng_data,
18153 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18154 "See documentation. %s: %d", __FILE__, __LINE__);
18155 return(tng_util_force_write_interval_set(tng_data, i));
18158 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18159 (tng_trajectory_t tng_data,
18162 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18163 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18165 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18166 TNG_TRAJ_BOX_SHAPE,
18168 TNG_NON_PARTICLE_BLOCK_DATA,
18169 TNG_GZIP_COMPRESSION));
18172 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18173 (tng_trajectory_t tng_data,
18176 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18177 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18179 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18180 TNG_TRAJ_BOX_SHAPE,
18182 TNG_NON_PARTICLE_BLOCK_DATA,
18183 TNG_GZIP_COMPRESSION));
18186 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18187 (tng_trajectory_t tng_data,
18190 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18191 "See documentation. %s: %d", __FILE__, __LINE__);
18192 return(tng_util_box_shape_write_interval_set(tng_data, i));
18195 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18196 (tng_trajectory_t tng_data,
18197 const int64_t frame_nr,
18198 const float *values,
18199 const int64_t n_values_per_frame,
18200 const int64_t block_id,
18201 const char *block_name,
18202 const char particle_dependency,
18203 const char compression)
18205 tng_trajectory_frame_set_t frame_set;
18206 tng_particle_data_t p_data;
18207 tng_non_particle_data_t np_data;
18208 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18209 int64_t last_frame;
18210 int is_first_frame_flag = 0;
18211 char block_type_flag;
18212 tng_function_status stat;
18214 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18215 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18216 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18218 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18220 tng_num_particles_get(tng_data, &n_particles);
18221 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18226 return(TNG_FAILURE);
18229 frame_set = &tng_data->current_trajectory_frame_set;
18233 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18234 n_frames = stride_length = 1;
18238 block_type_flag = TNG_TRAJECTORY_BLOCK;
18240 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18242 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18243 if(stat != TNG_SUCCESS)
18245 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18250 last_frame = frame_set->first_frame +
18251 frame_set->n_frames - 1;
18252 if(frame_nr > last_frame)
18254 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18255 if(stat != TNG_SUCCESS)
18257 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18261 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18263 last_frame = frame_nr - 1;
18265 stat = tng_frame_set_new(tng_data, last_frame + 1,
18266 tng_data->frame_set_n_frames);
18267 if(stat != TNG_SUCCESS)
18269 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18274 if(frame_set->n_unwritten_frames == 0)
18276 is_first_frame_flag = 1;
18278 frame_set->n_unwritten_frames = frame_nr -
18279 frame_set->first_frame + 1;
18281 n_frames = frame_set->n_frames;
18284 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18286 if(tng_particle_data_find(tng_data, block_id, &p_data)
18289 stat = tng_particle_data_block_add(tng_data, block_id,
18293 n_frames, n_values_per_frame,
18297 if(stat != TNG_SUCCESS)
18299 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18300 __FILE__, __LINE__);
18303 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18305 p_data = &frame_set->tr_particle_data[frame_set->
18306 n_particle_data_blocks - 1];
18310 p_data = &tng_data->non_tr_particle_data[tng_data->
18311 n_particle_data_blocks - 1];
18313 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18314 stride_length, n_particles,
18315 n_values_per_frame);
18316 if(stat != TNG_SUCCESS)
18318 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18319 __FILE__, __LINE__);
18324 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18326 stride_length = p_data->stride_length;
18328 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18330 p_data->first_frame_with_data = frame_nr;
18335 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18338 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18339 n_values_per_frame, values, sizeof(float) *
18340 n_particles * n_values_per_frame);
18344 memcpy(p_data->values, values, sizeof(float) * n_particles *
18345 n_values_per_frame);
18350 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18352 stat = tng_data_block_add(tng_data, block_id, block_name,
18353 TNG_FLOAT_DATA, block_type_flag,
18354 n_frames, n_values_per_frame,
18355 stride_length, compression, 0);
18356 if(stat != TNG_SUCCESS)
18358 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18359 __FILE__, __LINE__);
18362 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18364 np_data = &frame_set->tr_data[frame_set->
18365 n_data_blocks - 1];
18369 np_data = &tng_data->non_tr_data[tng_data->
18370 n_data_blocks - 1];
18372 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18373 stride_length, n_values_per_frame);
18374 if(stat != TNG_SUCCESS)
18376 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18377 __FILE__, __LINE__);
18382 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18384 stride_length = np_data->stride_length;
18386 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18388 np_data->first_frame_with_data = frame_nr;
18393 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18396 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18397 n_values_per_frame, values, sizeof(float) *
18398 n_values_per_frame);
18402 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18406 return(TNG_SUCCESS);
18409 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18410 (tng_trajectory_t tng_data,
18411 const int64_t frame_nr,
18412 const double *values,
18413 const int64_t n_values_per_frame,
18414 const int64_t block_id,
18415 const char *block_name,
18416 const char particle_dependency,
18417 const char compression)
18419 tng_trajectory_frame_set_t frame_set;
18420 tng_particle_data_t p_data;
18421 tng_non_particle_data_t np_data;
18422 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18423 int64_t last_frame;
18424 int is_first_frame_flag = 0;
18425 char block_type_flag;
18426 tng_function_status stat;
18428 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18429 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18430 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18432 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18434 tng_num_particles_get(tng_data, &n_particles);
18435 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18440 return(TNG_FAILURE);
18443 frame_set = &tng_data->current_trajectory_frame_set;
18447 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18448 n_frames = stride_length = 1;
18452 block_type_flag = TNG_TRAJECTORY_BLOCK;
18454 n_frames = tng_data->frame_set_n_frames;
18456 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18458 stat = tng_frame_set_new(tng_data, 0, n_frames);
18459 if(stat != TNG_SUCCESS)
18461 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18468 n_frames = frame_set->n_frames;
18470 last_frame = frame_set->first_frame +
18471 frame_set->n_frames - 1;
18472 if(frame_nr > last_frame)
18474 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18475 if(stat != TNG_SUCCESS)
18477 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18481 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18483 last_frame = frame_nr - 1;
18485 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18486 if(stat != TNG_SUCCESS)
18488 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18493 if(frame_set->n_unwritten_frames == 0)
18495 is_first_frame_flag = 1;
18497 frame_set->n_unwritten_frames = frame_nr -
18498 frame_set->first_frame + 1;
18501 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18503 if(tng_particle_data_find(tng_data, block_id, &p_data)
18506 stat = tng_particle_data_block_add(tng_data, block_id,
18510 n_frames, n_values_per_frame,
18514 if(stat != TNG_SUCCESS)
18516 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18517 __FILE__, __LINE__);
18520 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18522 p_data = &frame_set->tr_particle_data[frame_set->
18523 n_particle_data_blocks - 1];
18527 p_data = &tng_data->non_tr_particle_data[tng_data->
18528 n_particle_data_blocks - 1];
18530 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18531 stride_length, n_particles,
18532 n_values_per_frame);
18533 if(stat != TNG_SUCCESS)
18535 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18536 __FILE__, __LINE__);
18541 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18543 stride_length = p_data->stride_length;
18545 if(is_first_frame_flag)
18547 p_data->first_frame_with_data = frame_nr;
18552 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18555 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18556 n_values_per_frame, values, sizeof(double) *
18557 n_particles * n_values_per_frame);
18561 memcpy(p_data->values, values, sizeof(double) * n_particles *
18562 n_values_per_frame);
18567 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18569 stat = tng_data_block_add(tng_data, block_id, block_name,
18570 TNG_DOUBLE_DATA, block_type_flag,
18571 n_frames, n_values_per_frame,
18572 stride_length, compression, 0);
18573 if(stat != TNG_SUCCESS)
18575 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18576 __FILE__, __LINE__);
18579 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18581 np_data = &frame_set->tr_data[frame_set->
18582 n_data_blocks - 1];
18586 np_data = &tng_data->non_tr_data[tng_data->
18587 n_data_blocks - 1];
18589 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18590 stride_length, n_values_per_frame);
18591 if(stat != TNG_SUCCESS)
18593 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18594 __FILE__, __LINE__);
18599 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18601 stride_length = np_data->stride_length;
18603 if(is_first_frame_flag)
18605 np_data->first_frame_with_data = frame_nr;
18610 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18613 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18614 n_values_per_frame, values, sizeof(double) *
18615 n_values_per_frame);
18619 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18623 return(TNG_SUCCESS);
18626 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18627 (tng_trajectory_t tng_data,
18628 const int64_t frame_nr,
18629 const float *positions)
18631 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18632 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18633 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18635 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18636 TNG_TRAJ_POSITIONS, "POSITIONS",
18637 TNG_PARTICLE_BLOCK_DATA,
18638 TNG_TNG_COMPRESSION));
18641 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18642 (tng_trajectory_t tng_data,
18643 const int64_t frame_nr,
18644 const double *positions)
18646 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18647 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18648 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18650 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18651 TNG_TRAJ_POSITIONS, "POSITIONS",
18652 TNG_PARTICLE_BLOCK_DATA,
18653 TNG_TNG_COMPRESSION));
18656 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18657 (tng_trajectory_t tng_data,
18658 const int64_t frame_nr,
18659 const float *velocities)
18661 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18662 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18663 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18665 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18666 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18667 TNG_PARTICLE_BLOCK_DATA,
18668 TNG_TNG_COMPRESSION));
18671 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18672 (tng_trajectory_t tng_data,
18673 const int64_t frame_nr,
18674 const double *velocities)
18676 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18677 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18678 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18680 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18681 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18682 TNG_PARTICLE_BLOCK_DATA,
18683 TNG_TNG_COMPRESSION));
18686 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18687 (tng_trajectory_t tng_data,
18688 const int64_t frame_nr,
18689 const float *forces)
18691 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18692 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18693 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18695 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18696 TNG_TRAJ_FORCES, "FORCES",
18697 TNG_PARTICLE_BLOCK_DATA,
18698 TNG_GZIP_COMPRESSION));
18701 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18702 (tng_trajectory_t tng_data,
18703 const int64_t frame_nr,
18704 const double *forces)
18706 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18707 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18708 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18710 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18711 TNG_TRAJ_FORCES, "FORCES",
18712 TNG_PARTICLE_BLOCK_DATA,
18713 TNG_GZIP_COMPRESSION));
18716 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18717 (tng_trajectory_t tng_data,
18718 const int64_t frame_nr,
18719 const float *box_shape)
18721 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18722 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18723 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18725 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18726 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18727 TNG_NON_PARTICLE_BLOCK_DATA,
18728 TNG_GZIP_COMPRESSION));
18731 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18732 (tng_trajectory_t tng_data,
18733 const int64_t frame_nr,
18734 const double *box_shape)
18736 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18737 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18738 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18740 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18741 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18742 TNG_NON_PARTICLE_BLOCK_DATA,
18743 TNG_GZIP_COMPRESSION));
18746 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18747 (tng_trajectory_t tng_data,
18748 const int64_t frame_nr,
18750 const float *values,
18751 const int64_t n_values_per_frame,
18752 const int64_t block_id,
18753 const char *block_name,
18754 const char particle_dependency,
18755 const char compression)
18757 tng_trajectory_frame_set_t frame_set;
18758 tng_function_status stat;
18760 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18761 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18762 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18763 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18765 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18766 block_id, block_name,
18767 particle_dependency,
18770 if(stat != TNG_SUCCESS)
18775 frame_set = &tng_data->current_trajectory_frame_set;
18777 /* first_frame_time is -1 when it is not yet set. */
18778 if(frame_set->first_frame_time < -0.1)
18780 if(frame_nr > frame_set->first_frame)
18782 stat = tng_frame_set_first_frame_time_set(tng_data,
18785 frame_set->first_frame) *
18786 tng_data->time_per_frame);
18790 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18796 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18797 (tng_trajectory_t tng_data,
18798 const int64_t frame_nr,
18800 const double *values,
18801 const int64_t n_values_per_frame,
18802 const int64_t block_id,
18803 const char *block_name,
18804 const char particle_dependency,
18805 const char compression)
18807 tng_trajectory_frame_set_t frame_set;
18808 tng_function_status stat;
18810 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18811 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18812 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18813 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18815 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18816 block_id, block_name,
18817 particle_dependency,
18820 if(stat != TNG_SUCCESS)
18825 frame_set = &tng_data->current_trajectory_frame_set;
18827 /* first_frame_time is -1 when it is not yet set. */
18828 if(frame_set->first_frame_time < -0.1)
18830 if(frame_nr > frame_set->first_frame)
18832 stat = tng_frame_set_first_frame_time_set(tng_data,
18835 frame_set->first_frame) *
18836 tng_data->time_per_frame);
18840 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18846 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18847 (tng_trajectory_t tng_data,
18848 const int64_t frame_nr,
18850 const float *positions)
18852 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18853 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18854 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18855 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18857 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18858 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18859 TNG_PARTICLE_BLOCK_DATA,
18860 TNG_TNG_COMPRESSION));
18863 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18864 (tng_trajectory_t tng_data,
18865 const int64_t frame_nr,
18867 const double *positions)
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(positions, "TNG library: positions must not be a NULL pointer");
18874 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18876 TNG_TRAJ_POSITIONS,
18878 TNG_PARTICLE_BLOCK_DATA,
18879 TNG_TNG_COMPRESSION));
18882 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18883 (tng_trajectory_t tng_data,
18884 const int64_t frame_nr,
18886 const float *velocities)
18888 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18889 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18890 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18891 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18893 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18895 TNG_TRAJ_VELOCITIES,
18897 TNG_PARTICLE_BLOCK_DATA,
18898 TNG_TNG_COMPRESSION));
18901 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18902 (tng_trajectory_t tng_data,
18903 const int64_t frame_nr,
18905 const double *velocities)
18907 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18908 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18909 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18910 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18912 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18914 TNG_TRAJ_VELOCITIES,
18916 TNG_PARTICLE_BLOCK_DATA,
18917 TNG_TNG_COMPRESSION));
18920 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18921 (tng_trajectory_t tng_data,
18922 const int64_t frame_nr,
18924 const float *forces)
18926 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18927 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18928 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18929 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18931 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18932 3, TNG_TRAJ_FORCES, "FORCES",
18933 TNG_PARTICLE_BLOCK_DATA,
18934 TNG_GZIP_COMPRESSION));
18937 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18938 (tng_trajectory_t tng_data,
18939 const int64_t frame_nr,
18941 const double *forces)
18943 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18944 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18945 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18946 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18948 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18950 TNG_TRAJ_FORCES, "FORCES",
18951 TNG_PARTICLE_BLOCK_DATA,
18952 TNG_GZIP_COMPRESSION));
18955 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18956 (tng_trajectory_t tng_data,
18957 const int64_t frame_nr,
18959 const float *box_shape)
18961 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18962 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18963 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18964 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18966 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18967 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18968 TNG_NON_PARTICLE_BLOCK_DATA,
18969 TNG_GZIP_COMPRESSION));
18972 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18973 (tng_trajectory_t tng_data,
18974 const int64_t frame_nr,
18976 const double *box_shape)
18978 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18979 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18980 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18981 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18983 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18984 time, box_shape, 9,
18985 TNG_TRAJ_BOX_SHAPE,
18987 TNG_NON_PARTICLE_BLOCK_DATA,
18988 TNG_GZIP_COMPRESSION));
18991 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18992 (tng_trajectory_t tng_data,
18993 const int64_t block_id,
18997 tng_trajectory_frame_set_t frame_set;
18998 tng_particle_data_t p_data = 0;
18999 tng_non_particle_data_t np_data = 0;
19000 tng_function_status stat;
19002 int block_type = -1;
19004 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19005 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
19006 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
19008 frame_set = &tng_data->current_trajectory_frame_set;
19010 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19011 if(stat == TNG_SUCCESS)
19013 block_type = TNG_PARTICLE_BLOCK_DATA;
19017 stat = tng_data_find(tng_data, block_id, &np_data);
19018 if(stat == TNG_SUCCESS)
19020 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19024 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19025 if(stat != TNG_SUCCESS)
19029 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19030 if(stat == TNG_SUCCESS)
19032 block_type = TNG_PARTICLE_BLOCK_DATA;
19036 stat = tng_data_find(tng_data, block_id, &np_data);
19037 if(stat == TNG_SUCCESS)
19039 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19048 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19050 if(p_data->last_retrieved_frame < 0)
19052 i = p_data->first_frame_with_data;
19056 i = p_data->last_retrieved_frame;
19059 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19061 if(np_data->last_retrieved_frame < 0)
19063 i = np_data->first_frame_with_data;
19067 i = np_data->last_retrieved_frame;
19072 return(TNG_FAILURE);
19074 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
19076 stat = tng_frame_set_of_frame_find(tng_data, i);
19077 if(stat != TNG_SUCCESS)
19081 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19082 if(stat != TNG_SUCCESS)
19084 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19085 __FILE__, __LINE__);
19089 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19091 *codec_id = p_data->codec_id;
19092 *factor = p_data->compression_multiplier;
19094 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19096 *codec_id = np_data->codec_id;
19097 *factor = np_data->compression_multiplier;
19099 return(TNG_SUCCESS);
19102 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19103 (tng_trajectory_t tng_data,
19104 int64_t current_frame,
19105 const int64_t n_requested_data_block_ids,
19106 const int64_t *requested_data_block_ids,
19107 int64_t *next_frame,
19108 int64_t *n_data_blocks_in_next_frame,
19109 int64_t **data_block_ids_in_next_frame)
19111 tng_trajectory_frame_set_t frame_set;
19112 tng_function_status stat;
19113 tng_particle_data_t p_data;
19114 tng_non_particle_data_t np_data;
19115 tng_gen_block_t block;
19116 int64_t i, j, block_id, *temp;
19117 int64_t data_frame, frame_diff, min_diff;
19118 int64_t size, frame_set_file_pos, file_pos;
19119 int found, read_all = 0;
19121 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19122 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19123 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19124 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19126 if(n_requested_data_block_ids)
19128 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.");
19129 size = sizeof(int64_t) * n_requested_data_block_ids;
19130 temp = realloc(*data_block_ids_in_next_frame, size);
19133 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19134 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19135 __FILE__, __LINE__);
19136 free(*data_block_ids_in_next_frame);
19137 *data_block_ids_in_next_frame = 0;
19138 return(TNG_CRITICAL);
19140 *data_block_ids_in_next_frame = temp;
19143 frame_set = &tng_data->current_trajectory_frame_set;
19145 current_frame += 1;
19147 if(current_frame < frame_set->first_frame ||
19148 current_frame >= frame_set->first_frame + frame_set->n_frames)
19150 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19151 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19152 if(stat != TNG_SUCCESS)
19154 /* If the frame set search found the frame set after the starting
19155 * frame set there is a gap in the frame sets. So, even if the frame
19156 * was not found the next frame with data is still in the found
19158 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19159 frame_set_file_pos)
19163 current_frame = frame_set->first_frame;
19167 /* Check for data blocks only if they have not already been found. */
19168 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19170 file_pos = ftello(tng_data->input_file);
19171 if(file_pos < tng_data->input_file_len)
19173 tng_block_init(&block);
19174 stat = tng_block_header_read(tng_data, block);
19175 while(file_pos < tng_data->input_file_len &&
19176 stat != TNG_CRITICAL &&
19177 block->id != TNG_TRAJECTORY_FRAME_SET &&
19180 stat = tng_block_read_next(tng_data, block,
19182 if(stat != TNG_CRITICAL)
19184 file_pos = ftello(tng_data->input_file);
19185 if(file_pos < tng_data->input_file_len)
19187 stat = tng_block_header_read(tng_data, block);
19191 tng_block_destroy(&block);
19192 if(stat == TNG_CRITICAL)
19194 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
19195 file_pos, __FILE__, __LINE__);
19204 *n_data_blocks_in_next_frame = 0;
19206 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19208 p_data = &frame_set->tr_particle_data[i];
19209 block_id = p_data->block_id;
19211 if(n_requested_data_block_ids > 0)
19214 for(j = 0; j < n_requested_data_block_ids; j++)
19216 if(block_id == requested_data_block_ids[j])
19228 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19229 p_data->last_retrieved_frame >=
19230 frame_set->first_frame + frame_set->n_frames))
19232 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19233 TNG_USE_HASH, block_id);
19234 if(stat == TNG_CRITICAL)
19236 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19237 __FILE__, __LINE__);
19240 if(stat == TNG_FAILURE)
19245 if(frame_set->first_frame != current_frame &&
19246 p_data->last_retrieved_frame >= 0)
19248 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19252 data_frame = p_data->first_frame_with_data;
19254 frame_diff = data_frame - current_frame;
19259 if(min_diff == -1 || frame_diff <= min_diff)
19261 if(frame_diff < min_diff)
19263 *n_data_blocks_in_next_frame = 1;
19267 *n_data_blocks_in_next_frame += 1;
19269 if(n_requested_data_block_ids <= 0)
19271 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19272 temp = realloc(*data_block_ids_in_next_frame, size);
19275 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19276 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19277 __FILE__, __LINE__);
19278 free(*data_block_ids_in_next_frame);
19279 *data_block_ids_in_next_frame = 0;
19280 return(TNG_CRITICAL);
19282 *data_block_ids_in_next_frame = temp;
19286 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19288 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19290 min_diff = frame_diff;
19293 for(i = 0; i < frame_set->n_data_blocks; i++)
19295 np_data = &frame_set->tr_data[i];
19296 block_id = np_data->block_id;
19298 if(n_requested_data_block_ids > 0)
19301 for(j = 0; j < n_requested_data_block_ids; j++)
19303 if(block_id == requested_data_block_ids[j])
19315 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19316 np_data->last_retrieved_frame >=
19317 frame_set->first_frame + frame_set->n_frames))
19319 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19320 TNG_USE_HASH, block_id);
19321 if(stat == TNG_CRITICAL)
19323 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19324 __FILE__, __LINE__);
19327 if(stat == TNG_FAILURE)
19332 if(frame_set->first_frame != current_frame &&
19333 np_data->last_retrieved_frame >= 0)
19335 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19339 data_frame = np_data->first_frame_with_data;
19341 frame_diff = data_frame - current_frame;
19346 if(min_diff == -1 || frame_diff <= min_diff)
19348 if(frame_diff < min_diff)
19350 *n_data_blocks_in_next_frame = 1;
19354 *n_data_blocks_in_next_frame += 1;
19356 if(n_requested_data_block_ids <= 0)
19358 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19359 temp = realloc(*data_block_ids_in_next_frame, size);
19362 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19363 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19364 __FILE__, __LINE__);
19365 free(*data_block_ids_in_next_frame);
19366 *data_block_ids_in_next_frame = 0;
19367 return(TNG_CRITICAL);
19369 *data_block_ids_in_next_frame = temp;
19373 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19375 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19377 min_diff = frame_diff;
19382 return(TNG_FAILURE);
19384 *next_frame = current_frame + min_diff;
19386 return(TNG_SUCCESS);
19390 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19391 (tng_trajectory_t tng_data,
19392 int64_t *n_data_blocks,
19393 int64_t **data_block_ids,
19394 char ***data_block_names,
19395 int64_t **stride_lengths,
19396 int64_t **n_values_per_frame,
19397 char **block_types,
19398 char **dependencies,
19399 char **compressions)
19401 tng_gen_block_t block;
19402 int64_t orig_file_pos, file_pos;
19404 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19405 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19406 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19407 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19408 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19410 orig_file_pos = ftello(tng_data->input_file);
19412 if(!tng_data->input_file_len)
19414 fseeko(tng_data->input_file, 0, SEEK_END);
19415 tng_data->input_file_len = ftello(tng_data->input_file);
19418 fseeko(tng_data->input_file, 0, SEEK_SET);
19421 *n_data_blocks = 0;
19423 tng_block_init(&block);
19425 while(file_pos < tng_data->input_file_len &&
19426 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19428 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19432 file_pos += (block->block_contents_size + block->header_contents_size);
19433 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
19436 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
19438 return(TNG_SUCCESS);
19441 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19442 (tng_trajectory_t tng_data,
19443 const int64_t prev_frame)
19445 tng_function_status stat;
19446 FILE *temp = tng_data->input_file;
19448 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19449 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19451 tng_data->input_file = tng_data->output_file;
19453 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19454 if(stat != TNG_SUCCESS)
19459 tng_data->current_trajectory_frame_set_output_file_pos =
19460 tng_data->current_trajectory_frame_set_input_file_pos;
19462 tng_data->input_file = temp;
19464 return(TNG_SUCCESS);