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;
5060 int64_t compressed_len;
5067 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
5069 if(block->id != TNG_TRAJ_POSITIONS &&
5070 block->id != TNG_TRAJ_VELOCITIES)
5072 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
5074 return(TNG_FAILURE);
5076 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
5078 fprintf(stderr, "TNG library: Data type not supported.\n");
5079 return(TNG_FAILURE);
5082 compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
5083 temp_data_contents = malloc(compressed_len);
5084 if(!temp_data_contents)
5086 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5087 uncompressed_len, __FILE__, __LINE__);
5088 return(TNG_CRITICAL);
5091 memcpy(temp_data_contents, (char *)start_pos, compressed_len);
5093 if(type == TNG_FLOAT_DATA)
5095 f_dest = malloc(uncompressed_len);
5098 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5099 uncompressed_len, __FILE__, __LINE__);
5100 free(temp_data_contents);
5101 return(TNG_CRITICAL);
5103 result = tng_compress_uncompress_float(temp_data_contents, f_dest);
5107 d_dest = malloc(uncompressed_len);
5110 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5111 uncompressed_len, __FILE__, __LINE__);
5112 free(temp_data_contents);
5113 return(TNG_CRITICAL);
5115 result = tng_compress_uncompress(temp_data_contents, d_dest);
5120 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
5121 free(temp_data_contents);
5122 return(TNG_FAILURE);
5125 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
5127 block->block_contents_size = (int64_t)(uncompressed_len + offset);
5129 temp = realloc(block->block_contents, uncompressed_len + offset);
5132 free(block->block_contents);
5133 block->block_contents = 0;
5142 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5143 block->block_contents_size, __FILE__, __LINE__);
5144 free(temp_data_contents);
5145 return(TNG_CRITICAL);
5148 if(type == TNG_FLOAT_DATA)
5150 memcpy(temp + offset, f_dest, uncompressed_len);
5154 memcpy(temp + offset, d_dest, uncompressed_len);
5157 block->block_contents = temp;
5159 free(temp_data_contents);
5168 return(TNG_SUCCESS);
5172 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
5173 tng_gen_block_t block,
5174 void *start_pos, const int len)
5178 unsigned long max_len, stat, offset;
5181 max_len = compressBound(len);
5182 dest = malloc(max_len);
5185 fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
5186 max_len, __FILE__, __LINE__);
5187 return(TNG_CRITICAL);
5190 stat = compress(dest, &max_len, start_pos, len);
5191 if(stat != (unsigned long)Z_OK)
5194 if(stat == (unsigned long)Z_MEM_ERROR)
5196 fprintf(stderr, "TNG library: Not enough memory. ");
5198 else if(stat == (unsigned long)Z_BUF_ERROR)
5200 fprintf(stderr, "TNG library: Destination buffer too small. ");
5202 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
5203 return(TNG_FAILURE);
5206 offset = (char *)start_pos - block->block_contents;
5208 block->block_contents_size = max_len + offset;
5210 temp = realloc(block->block_contents, block->block_contents_size);
5213 free(block->block_contents);
5215 block->block_contents = 0;
5216 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5217 block->block_contents_size, __FILE__, __LINE__);
5218 return(TNG_CRITICAL);
5221 block->block_contents = temp;
5223 memcpy(temp + offset, dest, max_len);
5227 return(TNG_SUCCESS);
5230 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5231 tng_gen_block_t block,
5233 unsigned long uncompressed_len)
5241 offset = (char *)start_pos - (char *)block->block_contents;
5243 dest = malloc(uncompressed_len);
5246 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5247 uncompressed_len, __FILE__, __LINE__);
5248 return(TNG_CRITICAL);
5251 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
5252 block->block_contents_size - offset);
5257 if(stat == (unsigned long)Z_MEM_ERROR)
5259 fprintf(stderr, "TNG library: Not enough memory. ");
5261 else if(stat == (unsigned long)Z_BUF_ERROR)
5263 fprintf(stderr, "TNG library: Destination buffer too small. ");
5265 else if(stat == (unsigned long)Z_DATA_ERROR)
5267 fprintf(stderr, "TNG library: Data corrupt. ");
5269 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
5271 return(TNG_FAILURE);
5275 block->block_contents_size = uncompressed_len + offset;
5277 temp = realloc(block->block_contents, uncompressed_len + offset);
5280 free(block->block_contents);
5281 block->block_contents = 0;
5283 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5284 block->block_contents_size, __FILE__, __LINE__);
5285 return(TNG_CRITICAL);
5288 memcpy(temp + offset, dest, uncompressed_len);
5290 block->block_contents = temp;
5293 return(TNG_SUCCESS);
5297 /** Allocate memory for storing particle data.
5298 * The allocated block will be refered to by data->values.
5299 * @param tng_data is a trajectory data container.
5300 * @param data is the data struct, which will contain the allocated memory in
5302 * @param n_frames is the number of frames of data to store.
5303 * @param n_particles is the number of particles with data.
5304 * @param n_values_per_frame is the number of data values per particle and
5306 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5307 * error has occured.
5309 static tng_function_status tng_allocate_particle_data_mem
5310 (tng_trajectory_t tng_data,
5311 tng_particle_data_t data,
5313 int64_t stride_length,
5314 const int64_t n_particles,
5315 const int64_t n_values_per_frame)
5318 int64_t i, j, k, size, frame_alloc;
5321 if(n_particles == 0 || n_values_per_frame == 0)
5323 return(TNG_FAILURE);
5326 if(data->strings && data->datatype == TNG_CHAR_DATA)
5328 for(i = 0; i < data->n_frames; i++)
5330 for(j = 0; j < n_particles; j++)
5332 for(k = 0; k < data->n_values_per_frame; k++)
5334 if(data->strings[i][j][k])
5336 free(data->strings[i][j][k]);
5339 free(data->strings[i][j]);
5341 free(data->strings[i]);
5343 free(data->strings);
5345 data->n_frames = n_frames;
5346 n_frames = tng_max_i64(1, n_frames);
5347 data->stride_length = tng_max_i64(1, stride_length);
5348 data->n_values_per_frame = n_values_per_frame;
5349 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5351 if(data->datatype == TNG_CHAR_DATA)
5353 data->strings = malloc(sizeof(char ***) * frame_alloc);
5354 for(i = 0; i < frame_alloc; i++)
5356 data->strings[i] = malloc(sizeof(char **) *
5358 if(!data->strings[i])
5360 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5361 sizeof(union data_values *) * n_particles,
5362 __FILE__, __LINE__);
5363 return(TNG_CRITICAL);
5365 for(j = 0; j < n_particles; j++)
5367 data->strings[i][j] = malloc(sizeof(char *) *
5368 n_values_per_frame);
5369 if(!data->strings[i][j])
5371 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5372 sizeof(union data_values) * n_values_per_frame,
5373 __FILE__, __LINE__);
5374 return(TNG_CRITICAL);
5376 for(k = 0; k < n_values_per_frame; k++)
5378 data->strings[i][j][k] = 0;
5385 switch(data->datatype)
5388 size = sizeof(int64_t);
5390 case TNG_FLOAT_DATA:
5391 size = sizeof(float);
5393 case TNG_DOUBLE_DATA:
5395 size = sizeof(double);
5398 values = realloc(data->values,
5399 size * frame_alloc *
5400 n_particles * n_values_per_frame);
5403 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5404 size * frame_alloc *
5405 n_particles * n_values_per_frame,
5406 __FILE__, __LINE__);
5409 return(TNG_CRITICAL);
5411 data->values = values;
5413 return(TNG_SUCCESS);
5416 static tng_function_status tng_particle_data_find
5417 (tng_trajectory_t tng_data,
5419 tng_particle_data_t *data)
5421 int64_t block_index, i;
5422 tng_trajectory_frame_set_t frame_set = &tng_data->
5423 current_trajectory_frame_set;
5424 char block_type_flag;
5426 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5427 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5429 block_type_flag = TNG_TRAJECTORY_BLOCK;
5433 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5437 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5439 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
5441 *data = &frame_set->tr_particle_data[i];
5442 if((*data)->block_id == id)
5451 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
5453 *data = &tng_data->non_tr_particle_data[i];
5454 if((*data)->block_id == id)
5461 if(block_index == -1)
5463 return(TNG_FAILURE);
5465 return(TNG_SUCCESS);
5468 static tng_function_status tng_data_find
5469 (tng_trajectory_t tng_data,
5471 tng_non_particle_data_t *data)
5473 int64_t block_index, i;
5474 tng_trajectory_frame_set_t frame_set = &tng_data->
5475 current_trajectory_frame_set;
5476 char block_type_flag;
5478 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5479 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5481 block_type_flag = TNG_TRAJECTORY_BLOCK;
5485 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5489 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5491 for(i = 0; i < frame_set->n_data_blocks; i++)
5493 *data = &frame_set->tr_data[i];
5494 if((*data)->block_id == id)
5500 if(block_index == -1)
5502 for(i = 0; i < tng_data->n_data_blocks; i++)
5504 *data = &tng_data->non_tr_data[i];
5505 if((*data)->block_id == id)
5515 for(i = 0; i < tng_data->n_data_blocks; i++)
5517 *data = &tng_data->non_tr_data[i];
5518 if((*data)->block_id == id)
5525 if(block_index == -1)
5527 return(TNG_FAILURE);
5529 return(TNG_SUCCESS);
5532 static tng_function_status tng_data_block_len_calculate
5533 (const tng_trajectory_t tng_data,
5534 const tng_particle_data_t data,
5535 const tng_bool is_particle_data,
5536 const int64_t n_frames,
5537 const int64_t frame_step,
5538 const int64_t stride_length,
5539 const int64_t num_first_particle,
5540 const int64_t n_particles,
5541 const char dependency,
5542 int64_t *data_start_pos,
5547 char ***first_dim_values, **second_dim_values;
5552 return(TNG_SUCCESS);
5555 switch(data->datatype)
5561 size = sizeof(int64_t);
5563 case TNG_FLOAT_DATA:
5564 size = sizeof(float);
5566 case TNG_DOUBLE_DATA:
5568 size = sizeof(double);
5571 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5572 sizeof(data->codec_id);
5573 if(is_particle_data)
5575 *len += sizeof(num_first_particle) + sizeof(n_particles);
5578 if(stride_length > 1)
5580 *len += sizeof(data->first_frame_with_data) +
5581 sizeof(data->stride_length);
5584 if(data->codec_id != TNG_UNCOMPRESSED)
5586 *len += sizeof(data->compression_multiplier);
5589 if(dependency & TNG_FRAME_DEPENDENT)
5591 *len += sizeof(char);
5594 *data_start_pos = *len;
5596 if(data->datatype == TNG_CHAR_DATA)
5598 if(is_particle_data)
5600 for(i = 0; i < n_frames; i++)
5602 first_dim_values = data->strings[i];
5603 for(j = num_first_particle; j < num_first_particle + n_particles;
5606 second_dim_values = first_dim_values[j];
5607 for(k = 0; k < data->n_values_per_frame; k++)
5609 *len += strlen(second_dim_values[k]) + 1;
5616 for(i = 0; i < n_frames; i++)
5618 second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
5619 for(j = 0; j < data->n_values_per_frame; j++)
5621 *len += strlen(second_dim_values[j]) + 1;
5628 *len += size * frame_step * n_particles * data->n_values_per_frame;
5631 return(TNG_SUCCESS);
5634 /** Read the values of a particle data block
5635 * @param tng_data is a trajectory data container.
5636 * @param block is the block to store the data (should already contain
5637 * the block headers and the block contents).
5638 * @param offset is the reading offset to point at the place where the actual
5639 * values are stored, starting from the beginning of the block_contents. The
5640 * offset is changed during the reading.
5641 * @param datatype is the type of data of the data block (char, int, float or
5643 * @param num_first_particle is the number of the first particle in the data
5644 * block. This should be the same as in the corresponding particle mapping
5646 * @param n_particles is the number of particles in the data block. This should
5647 * be the same as in the corresponding particle mapping block.
5648 * @param first_frame_with_data is the frame number of the first frame with data
5649 * in this data block.
5650 * @param stride_length is the number of frames between each data entry.
5651 * @param n_frames is the number of frames in this data block.
5652 * @param n_values is the number of values per particle and frame stored in this
5654 * @param codec_id is the ID of the codec to compress the data.
5655 * @param multiplier is the multiplication factor applied to each data value
5656 * before compression. This factor is applied since some compression algorithms
5657 * work only on integers.
5658 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5659 * error has occured.
5661 static tng_function_status tng_particle_data_read
5662 (tng_trajectory_t tng_data,
5663 tng_gen_block_t block,
5665 const char datatype,
5666 const int64_t num_first_particle,
5667 const int64_t n_particles,
5668 const int64_t first_frame_with_data,
5669 const int64_t stride_length,
5671 const int64_t n_values,
5672 const int64_t codec_id,
5673 const double multiplier)
5675 int64_t i, j, k, tot_n_particles, n_frames_div;
5678 char ***first_dim_values, **second_dim_values;
5679 tng_particle_data_t data;
5680 tng_trajectory_frame_set_t frame_set =
5681 &tng_data->current_trajectory_frame_set;
5682 char block_type_flag;
5684 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5692 size = sizeof(int64_t);
5694 case TNG_FLOAT_DATA:
5695 size = sizeof(float);
5697 case TNG_DOUBLE_DATA:
5699 size = sizeof(double);
5702 /* If the block does not exist, create it */
5703 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5705 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5707 block_type_flag = TNG_TRAJECTORY_BLOCK;
5711 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5714 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5717 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5718 __FILE__, __LINE__);
5719 return(TNG_CRITICAL);
5721 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5723 data = &frame_set->tr_particle_data[frame_set->
5724 n_particle_data_blocks - 1];
5728 data = &tng_data->non_tr_particle_data[tng_data->
5729 n_particle_data_blocks - 1];
5731 data->block_id = block->id;
5733 data->block_name = malloc(strlen(block->name) + 1);
5734 if(!data->block_name)
5736 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5737 (int)strlen(block->name)+1, __FILE__, __LINE__);
5738 return(TNG_CRITICAL);
5740 strcpy(data->block_name, block->name);
5742 data->datatype = datatype;
5745 /* FIXME: Memory leak from strings. */
5748 data->codec_id = codec_id;
5749 data->compression_multiplier = multiplier;
5750 data->last_retrieved_frame = -1;
5753 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5754 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5755 tng_data->var_num_atoms_flag)
5757 tot_n_particles = frame_set->n_particles;
5761 tot_n_particles = tng_data->n_particles;
5764 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5766 if(codec_id != TNG_UNCOMPRESSED)
5768 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5771 case TNG_XTC_COMPRESSION:
5772 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5774 case TNG_TNG_COMPRESSION:
5775 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5776 if(tng_uncompress(tng_data, block, datatype,
5777 block->block_contents + *offset,
5778 data_size) != TNG_SUCCESS)
5780 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5781 __FILE__, __LINE__);
5782 return(TNG_CRITICAL);
5784 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5787 case TNG_GZIP_COMPRESSION:
5788 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5789 if(tng_gzip_uncompress(tng_data, block,
5790 block->block_contents + *offset,
5791 data_size) != TNG_SUCCESS)
5793 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5795 return(TNG_CRITICAL);
5797 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5802 /* Allocate memory */
5803 if(!data->values || data->n_frames != n_frames ||
5804 data->n_values_per_frame != n_values)
5806 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5808 tot_n_particles, n_values) !=
5811 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5812 __FILE__, __LINE__);
5813 return(TNG_CRITICAL);
5817 data->first_frame_with_data = first_frame_with_data;
5819 if(datatype == TNG_CHAR_DATA)
5821 for(i = 0; i < n_frames_div; i++)
5823 first_dim_values = data->strings[i];
5824 for(j = num_first_particle; j < num_first_particle + n_particles;
5827 second_dim_values = first_dim_values[j];
5828 for(k = 0; k < n_values; k++)
5830 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5832 if(second_dim_values[k])
5834 free(second_dim_values[k]);
5836 second_dim_values[k] = malloc(len);
5837 if(!second_dim_values[k])
5839 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5840 len, __FILE__, __LINE__);
5841 return(TNG_CRITICAL);
5843 strncpy(second_dim_values[k],
5844 block->block_contents+*offset, len);
5852 memcpy((char *)data->values + n_frames_div * size * n_values *
5854 block->block_contents + *offset,
5855 block->block_contents_size - *offset);
5858 case TNG_FLOAT_DATA:
5859 if(tng_data->input_endianness_swap_func_32)
5861 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5863 if(tng_data->input_endianness_swap_func_32(tng_data,
5864 (int32_t *)((char *)data->values + i))
5867 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5868 __FILE__, __LINE__);
5874 case TNG_DOUBLE_DATA:
5875 if(tng_data->input_endianness_swap_func_64)
5877 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5879 if(tng_data->input_endianness_swap_func_64(tng_data,
5880 (int64_t *)((char *)data->values + i))
5883 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5884 __FILE__, __LINE__);
5893 return(TNG_SUCCESS);
5896 /** Write a particle data block
5897 * @param tng_data is a trajectory data container.
5898 * @param block is the block to store the data (should already contain
5899 * the block headers and the block contents).
5900 * @param block_index is the index number of the data block in the frame set.
5901 * @param mapping is the particle mapping that is relevant for the data block.
5902 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5903 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5904 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5905 * error has occured.
5907 static tng_function_status tng_particle_data_block_write
5908 (tng_trajectory_t tng_data,
5909 tng_gen_block_t block,
5910 const int64_t block_index,
5911 const tng_particle_mapping_t mapping,
5912 const char hash_mode)
5914 int64_t n_particles, num_first_particle, n_frames, stride_length;
5915 int64_t frame_step, data_start_pos;
5918 size_t len, offset = 0;
5919 char dependency, temp, *temp_name;
5921 char ***first_dim_values, **second_dim_values;
5922 tng_trajectory_frame_set_t frame_set;
5923 tng_function_status stat;
5925 tng_particle_data_t data;
5926 char block_type_flag;
5928 frame_set = &tng_data->current_trajectory_frame_set;
5930 /* If we have already started writing frame sets it is too late to write
5931 * non-trajectory data blocks */
5932 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5934 block_type_flag = TNG_TRAJECTORY_BLOCK;
5938 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5941 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5943 return(TNG_CRITICAL);
5946 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5948 data = &frame_set->tr_particle_data[block_index];
5950 /* If this data block has not had any data added in this frame set
5951 * do not write it. */
5952 if(data->first_frame_with_data < frame_set->first_frame)
5954 return(TNG_SUCCESS);
5957 stride_length = tng_max_i64(1, data->stride_length);
5961 data = &tng_data->non_tr_particle_data[block_index];
5965 switch(data->datatype)
5971 size = sizeof(int64_t);
5973 case TNG_FLOAT_DATA:
5974 size = sizeof(float);
5976 case TNG_DOUBLE_DATA:
5978 size = sizeof(double);
5981 len = strlen(data->block_name) + 1;
5983 if(!block->name || strlen(block->name) < len)
5985 temp_name = realloc(block->name, len);
5988 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5989 __FILE__, __LINE__);
5992 return(TNG_CRITICAL);
5994 block->name = temp_name;
5996 strncpy(block->name, data->block_name, len);
5997 block->id = data->block_id;
5999 /* If writing frame independent data data->n_frames is 0, but n_frames
6000 is used for the loop writing the data (and reserving memory) and needs
6002 n_frames = tng_max_i64(1, data->n_frames);
6004 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6006 /* If the frame set is finished before writing the full number of frames
6007 make sure the data block is not longer than the frame set. */
6008 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6010 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6013 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6014 n_frames / stride_length;
6016 /* TNG compression will use compression precision to get integers from
6017 * floating point data. The compression multiplier stores that information
6018 * to be able to return the precision of the compressed data. */
6019 if(data->codec_id == TNG_TNG_COMPRESSION)
6021 data->compression_multiplier = tng_data->compression_precision;
6023 /* Uncompressed data blocks do not use compression multipliers at all.
6024 * GZip compression does not need it either. */
6025 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6027 data->compression_multiplier = 1.0;
6030 if(mapping && mapping->n_particles != 0)
6032 n_particles = mapping->n_particles;
6033 num_first_particle = mapping->num_first_particle;
6037 num_first_particle = 0;
6038 if(tng_data->var_num_atoms_flag)
6040 n_particles = frame_set->n_particles;
6044 n_particles = tng_data->n_particles;
6048 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6050 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6054 dependency = TNG_PARTICLE_DEPENDENT;
6057 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6058 frame_step, stride_length, num_first_particle,
6059 n_particles, dependency, &data_start_pos,
6060 &block->block_contents_size) != TNG_SUCCESS)
6062 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6063 __FILE__, __LINE__);
6064 return(TNG_CRITICAL);
6067 if(block->block_contents)
6069 free(block->block_contents);
6071 block->block_contents = malloc(block->block_contents_size);
6072 if(!block->block_contents)
6074 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6075 block->block_contents_size, __FILE__, __LINE__);
6076 return(TNG_CRITICAL);
6080 memcpy(block->block_contents, &data->datatype, sizeof(char));
6081 offset += sizeof(char);
6083 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6084 offset += sizeof(char);
6086 if(dependency & TNG_FRAME_DEPENDENT)
6088 if(stride_length > 1)
6096 memcpy(block->block_contents+offset, &temp, sizeof(char));
6097 offset += sizeof(char);
6100 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6101 sizeof(data->n_values_per_frame));
6102 if(tng_data->output_endianness_swap_func_64)
6104 if(tng_data->output_endianness_swap_func_64(tng_data,
6105 (int64_t *)block->header_contents+offset)
6108 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6109 __FILE__, __LINE__);
6112 offset += sizeof(data->n_values_per_frame);
6114 memcpy(block->block_contents+offset, &data->codec_id,
6115 sizeof(data->codec_id));
6116 if(tng_data->output_endianness_swap_func_64)
6118 if(tng_data->output_endianness_swap_func_64(tng_data,
6119 (int64_t *)block->header_contents+offset)
6122 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6123 __FILE__, __LINE__);
6126 offset += sizeof(data->codec_id);
6128 if(data->codec_id != TNG_UNCOMPRESSED)
6130 memcpy(block->block_contents+offset, &data->compression_multiplier,
6131 sizeof(data->compression_multiplier));
6132 if(tng_data->output_endianness_swap_func_64)
6134 if(tng_data->output_endianness_swap_func_64(tng_data,
6135 (int64_t *)block->header_contents+offset)
6138 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6139 __FILE__, __LINE__);
6142 offset += sizeof(data->compression_multiplier);
6145 if(data->n_frames > 0 && stride_length > 1)
6147 /* FIXME: first_frame_with_data is not reliably set */
6148 if(data->first_frame_with_data == 0)
6150 data->first_frame_with_data = frame_set->first_frame;
6152 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6153 sizeof(data->first_frame_with_data));
6154 if(tng_data->output_endianness_swap_func_64)
6156 if(tng_data->output_endianness_swap_func_64(tng_data,
6157 (int64_t *)block->header_contents+offset)
6160 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6161 __FILE__, __LINE__);
6164 offset += sizeof(data->first_frame_with_data);
6166 memcpy(block->block_contents+offset, &stride_length,
6167 sizeof(stride_length));
6168 if(tng_data->output_endianness_swap_func_64)
6170 if(tng_data->output_endianness_swap_func_64(tng_data,
6171 (int64_t *)block->header_contents+offset)
6174 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6175 __FILE__, __LINE__);
6178 offset += sizeof(stride_length);
6182 memcpy(block->block_contents+offset, &num_first_particle,
6183 sizeof(num_first_particle));
6184 if(tng_data->output_endianness_swap_func_64)
6186 if(tng_data->output_endianness_swap_func_64(tng_data,
6187 (int64_t *)block->header_contents+offset)
6190 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6191 __FILE__, __LINE__);
6194 offset += sizeof(num_first_particle);
6196 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
6197 if(tng_data->output_endianness_swap_func_64)
6199 if(tng_data->output_endianness_swap_func_64(tng_data,
6200 (int64_t *)block->header_contents+offset)
6203 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6204 __FILE__, __LINE__);
6207 offset += sizeof(n_particles);
6209 if(data->datatype == TNG_CHAR_DATA)
6213 for(i = 0; i < frame_step; i++)
6215 first_dim_values = data->strings[i];
6216 for(j = num_first_particle; j < num_first_particle + n_particles;
6219 second_dim_values = first_dim_values[j];
6220 for(k = 0; k < data->n_values_per_frame; k++)
6222 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6223 strncpy(block->block_contents+offset,
6224 second_dim_values[k], len);
6231 else if(data->values)
6233 memcpy(block->block_contents + offset, data->values,
6234 block->block_contents_size - offset);
6236 switch(data->datatype)
6238 case TNG_FLOAT_DATA:
6239 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6240 data->codec_id == TNG_TNG_COMPRESSION)
6242 if(tng_data->input_endianness_swap_func_32)
6244 for(i = offset; i < block->block_contents_size; i+=size)
6246 if(tng_data->input_endianness_swap_func_32(tng_data,
6247 (int32_t *)(block->block_contents + i))
6250 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6251 __FILE__, __LINE__);
6258 multiplier = data->compression_multiplier;
6259 if(fabs(multiplier - 1.0) > 0.00001 ||
6260 tng_data->input_endianness_swap_func_32)
6262 for(i = offset; i < block->block_contents_size; i+=size)
6264 *(float *)(block->block_contents + i) *= (float)multiplier;
6265 if(tng_data->input_endianness_swap_func_32 &&
6266 tng_data->input_endianness_swap_func_32(tng_data,
6267 (int32_t *)(block->block_contents + i))
6270 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6271 __FILE__, __LINE__);
6278 if(tng_data->input_endianness_swap_func_64)
6280 for(i = offset; i < block->block_contents_size; i+=size)
6282 if(tng_data->input_endianness_swap_func_64(tng_data,
6283 (int64_t *)(block->block_contents + i))
6286 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6287 __FILE__, __LINE__);
6292 case TNG_DOUBLE_DATA:
6293 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6294 data->codec_id == TNG_TNG_COMPRESSION)
6296 if(tng_data->input_endianness_swap_func_64)
6298 for(i = offset; i < block->block_contents_size; i+=size)
6300 if(tng_data->input_endianness_swap_func_64(tng_data,
6301 (int64_t *)(block->block_contents + i))
6304 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6305 __FILE__, __LINE__);
6312 multiplier = data->compression_multiplier;
6313 if(fabs(multiplier - 1.0) > 0.00001 ||
6314 tng_data->input_endianness_swap_func_64)
6316 for(i = offset; i < block->block_contents_size; i+=size)
6318 *(double *)(block->block_contents + i) *= multiplier;
6319 if(tng_data->input_endianness_swap_func_64 &&
6320 tng_data->input_endianness_swap_func_64(tng_data,
6321 (int64_t *)(block->block_contents + i))
6324 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6325 __FILE__, __LINE__);
6337 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6340 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6341 frame_set->n_unwritten_frames = 0;
6343 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6345 switch(data->codec_id)
6347 case TNG_XTC_COMPRESSION:
6348 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6349 data->codec_id = TNG_UNCOMPRESSED;
6351 case TNG_TNG_COMPRESSION:
6352 stat = tng_compress(tng_data, block, frame_step,
6353 n_particles, data->datatype,
6354 block->block_contents + data_start_pos);
6355 if(stat != TNG_SUCCESS)
6357 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6358 __FILE__, __LINE__);
6359 if(stat == TNG_CRITICAL)
6361 return(TNG_CRITICAL);
6363 /* Set the data again, but with no compression (to write only
6364 * the relevant data) */
6365 data->codec_id = TNG_UNCOMPRESSED;
6366 stat = tng_particle_data_block_write(tng_data, block,
6367 block_index, mapping,
6373 case TNG_GZIP_COMPRESSION:
6374 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6375 stat = tng_gzip_compress(tng_data, block,
6376 block->block_contents + data_start_pos,
6377 block->block_contents_size - data_start_pos);
6378 if(stat != TNG_SUCCESS)
6380 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6382 if(stat == TNG_CRITICAL)
6384 return(TNG_CRITICAL);
6386 /* Set the data again, but with no compression (to write only
6387 * the relevant data) */
6388 data->codec_id = TNG_UNCOMPRESSED;
6389 stat = tng_particle_data_block_write(tng_data, block,
6390 block_index, mapping,
6394 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6400 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6402 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6403 tng_data->output_file_path, __FILE__, __LINE__);
6404 return(TNG_CRITICAL);
6407 if(fwrite(block->block_contents, block->block_contents_size, 1,
6408 tng_data->output_file) != 1)
6410 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6412 return(TNG_CRITICAL);
6415 return(TNG_SUCCESS);
6419 /** Create a non-particle data block
6420 * @param tng_data is a trajectory data container.
6421 * @param block_type_flag specifies if this is a trajectory block or a
6422 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6423 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6424 * error has occured.
6426 static tng_function_status tng_data_block_create
6427 (tng_trajectory_t tng_data,
6428 const char block_type_flag)
6430 tng_trajectory_frame_set_t frame_set =
6431 &tng_data->current_trajectory_frame_set;
6433 tng_non_particle_data_t data;
6435 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6437 frame_set->n_data_blocks++;
6438 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6439 frame_set->n_data_blocks);
6442 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6443 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6444 __FILE__, __LINE__);
6445 free(frame_set->tr_data);
6446 frame_set->tr_data = 0;
6447 return(TNG_CRITICAL);
6449 frame_set->tr_data = data;
6453 tng_data->n_data_blocks++;
6454 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6455 tng_data->n_data_blocks);
6458 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6459 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6460 __FILE__, __LINE__);
6461 free(tng_data->non_tr_data);
6462 tng_data->non_tr_data = 0;
6463 return(TNG_CRITICAL);
6465 tng_data->non_tr_data = data;
6468 return(TNG_SUCCESS);
6472 /** Allocate memory for storing non-particle data.
6473 * The allocated block will be refered to by data->values.
6474 * @param tng_data is a trajectory data container.
6475 * @param data is the data struct, which will contain the allocated memory in
6477 * @param n_frames is the number of frames of data to store.
6478 * @param n_values_per_frame is the number of data values per frame.
6479 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6480 * error has occured.
6482 static tng_function_status tng_allocate_data_mem
6483 (tng_trajectory_t tng_data,
6484 tng_non_particle_data_t data,
6486 int64_t stride_length,
6487 const int64_t n_values_per_frame)
6490 int64_t i, j, size, frame_alloc;
6493 if(n_values_per_frame == 0)
6495 return(TNG_FAILURE);
6498 if(data->strings && data->datatype == TNG_CHAR_DATA)
6500 for(i = 0; i < data->n_frames; i++)
6502 for(j = 0; j < data->n_values_per_frame; j++)
6504 if(data->strings[i][j])
6506 free(data->strings[i][j]);
6507 data->strings[i][j] = 0;
6510 free(data->strings[i]);
6511 data->strings[i] = 0;
6513 free(data->strings);
6515 data->n_frames = n_frames;
6516 data->stride_length = tng_max_i64(1, stride_length);
6517 n_frames = tng_max_i64(1, n_frames);
6518 data->n_values_per_frame = n_values_per_frame;
6519 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6521 if(data->datatype == TNG_CHAR_DATA)
6523 data->strings = malloc(sizeof(char **) * frame_alloc);
6524 for(i = 0; i < frame_alloc; i++)
6526 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6527 if(!data->strings[i])
6529 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6531 __FILE__, __LINE__);
6532 return(TNG_CRITICAL);
6534 for(j = 0; j < n_values_per_frame; j++)
6536 data->strings[i][j] = 0;
6542 switch(data->datatype)
6545 size = sizeof(int64_t);
6547 case TNG_FLOAT_DATA:
6548 size = sizeof(float);
6550 case TNG_DOUBLE_DATA:
6552 size = sizeof(double);
6555 values = realloc(data->values,
6556 size * frame_alloc *
6557 n_values_per_frame);
6560 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6561 size * frame_alloc *
6563 __FILE__, __LINE__);
6566 return(TNG_CRITICAL);
6568 data->values = values;
6571 return(TNG_SUCCESS);
6574 /** Read the values of a non-particle data block
6575 * @param tng_data is a trajectory data container.
6576 * @param block is the block to store the data (should already contain
6577 * the block headers and the block contents).
6578 * @param offset is the reading offset to point at the place where the actual
6579 * values are stored, starting from the beginning of the block_contents. The
6580 * offset is changed during the reading.
6581 * @param datatype is the type of data of the data block (char, int, float or
6583 * @param first_frame_with_data is the frame number of the first frame with data
6584 * in this data block.
6585 * @param stride_length is the number of frames between each data entry.
6586 * @param n_frames is the number of frames in this data block.
6587 * @param n_values is the number of values per frame stored in this data block.
6588 * @param codec_id is the ID of the codec to compress the data.
6589 * @param multiplier is the multiplication factor applied to each data value
6590 * before compression. This factor is applied since some compression algorithms
6591 * work only on integers.
6592 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6593 * error has occured.
6595 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6596 tng_gen_block_t block,
6598 const char datatype,
6599 const int64_t first_frame_with_data,
6600 const int64_t stride_length,
6602 const int64_t n_values,
6603 const int64_t codec_id,
6604 const double multiplier)
6606 int64_t i, j, n_frames_div;
6611 tng_non_particle_data_t data;
6612 tng_trajectory_frame_set_t frame_set =
6613 &tng_data->current_trajectory_frame_set;
6614 char block_type_flag;
6616 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6618 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6626 size = sizeof(int64_t);
6628 case TNG_FLOAT_DATA:
6629 size = sizeof(float);
6631 case TNG_DOUBLE_DATA:
6633 size = sizeof(double);
6636 /* If the block does not exist, create it */
6637 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6639 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6641 block_type_flag = TNG_TRAJECTORY_BLOCK;
6645 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6648 if(tng_data_block_create(tng_data, block_type_flag) !=
6651 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6652 __FILE__, __LINE__);
6653 return(TNG_CRITICAL);
6655 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6657 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6661 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6663 data->block_id = block->id;
6665 data->block_name = malloc(strlen(block->name) + 1);
6666 if(!data->block_name)
6668 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6669 (int)strlen(block->name)+1, __FILE__, __LINE__);
6670 return(TNG_CRITICAL);
6672 strcpy(data->block_name, block->name);
6674 data->datatype = datatype;
6677 /* FIXME: Memory leak from strings. */
6680 data->codec_id = codec_id;
6681 data->compression_multiplier = multiplier;
6682 data->last_retrieved_frame = -1;
6685 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6687 if(codec_id != TNG_UNCOMPRESSED)
6692 case TNG_GZIP_COMPRESSION:
6693 data_size = n_frames_div * size * n_values;
6694 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6695 if(tng_gzip_uncompress(tng_data, block,
6696 block->block_contents + *offset,
6697 data_size) != TNG_SUCCESS)
6699 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6701 return(TNG_CRITICAL);
6703 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6709 /* Allocate memory */
6710 if(!data->values || data->n_frames != n_frames ||
6711 data->n_values_per_frame != n_values)
6713 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6717 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6718 __FILE__, __LINE__);
6719 return(TNG_CRITICAL);
6723 data->first_frame_with_data = first_frame_with_data;
6725 if(datatype == TNG_CHAR_DATA)
6727 for(i = 0; i < n_frames_div; i++)
6729 for(j = 0; j < n_values; j++)
6731 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6733 if(data->strings[i][j])
6735 free(data->strings[i][j]);
6737 data->strings[i][j] = malloc(len);
6738 if(!data->strings[i][j])
6740 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6741 len, __FILE__, __LINE__);
6742 return(TNG_CRITICAL);
6744 strncpy(data->strings[i][j], block->block_contents+*offset,
6752 memcpy(data->values, block->block_contents + *offset,
6753 block->block_contents_size - *offset);
6756 case TNG_FLOAT_DATA:
6757 if(tng_data->input_endianness_swap_func_32)
6759 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6761 if(tng_data->input_endianness_swap_func_32(tng_data,
6762 (int32_t *)((char *)data->values + i))
6765 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6766 __FILE__, __LINE__);
6772 case TNG_DOUBLE_DATA:
6773 if(tng_data->input_endianness_swap_func_64)
6775 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6777 if(tng_data->input_endianness_swap_func_64(tng_data,
6778 (int64_t *)((char *)data->values + i))
6781 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6782 __FILE__, __LINE__);
6791 return(TNG_SUCCESS);
6794 /** Write a non-particle data block
6795 * @param tng_data is a trajectory data container.
6796 * @param block is the block to store the data (should already contain
6797 * the block headers and the block contents).
6798 * @param block_index is the index number of the data block in the frame set.
6799 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6800 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6801 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6802 * error has occured.
6804 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6805 tng_gen_block_t block,
6806 const int64_t block_index,
6807 const char hash_mode)
6809 int64_t n_frames, stride_length, frame_step, data_start_pos;
6811 int offset = 0, size;
6814 tng_function_status stat;
6816 char temp, dependency, *temp_name;
6818 tng_trajectory_frame_set_t frame_set =
6819 &tng_data->current_trajectory_frame_set;
6821 tng_non_particle_data_t data;
6822 char block_type_flag;
6824 /* If we have already started writing frame sets it is too late to write
6825 * non-trajectory data blocks */
6826 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6828 block_type_flag = TNG_TRAJECTORY_BLOCK;
6832 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6835 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6837 return(TNG_CRITICAL);
6840 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6842 data = &frame_set->tr_data[block_index];
6844 /* If this data block has not had any data added in this frame set
6845 * do not write it. */
6846 if(data->first_frame_with_data < frame_set->first_frame)
6848 return(TNG_SUCCESS);
6851 stride_length = tng_max_i64(1, data->stride_length);
6855 data = &tng_data->non_tr_data[block_index];
6859 switch(data->datatype)
6865 size = sizeof(int64_t);
6867 case TNG_FLOAT_DATA:
6868 size = sizeof(float);
6870 case TNG_DOUBLE_DATA:
6872 size = sizeof(double);
6875 len = (unsigned int)strlen(data->block_name) + 1;
6877 if(!block->name || strlen(block->name) < len)
6879 temp_name = realloc(block->name, len);
6882 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6883 __FILE__, __LINE__);
6886 return(TNG_CRITICAL);
6888 block->name = temp_name;
6890 strncpy(block->name, data->block_name, len);
6891 block->id = data->block_id;
6893 /* If writing frame independent data data->n_frames is 0, but n_frames
6894 is used for the loop writing the data (and reserving memory) and needs
6896 n_frames = tng_max_i64(1, data->n_frames);
6898 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6900 /* If the frame set is finished before writing the full number of frames
6901 make sure the data block is not longer than the frame set. */
6902 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6904 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6907 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6908 n_frames / stride_length;
6910 /* TNG compression will use compression precision to get integers from
6911 * floating point data. The compression multiplier stores that information
6912 * to be able to return the precision of the compressed data. */
6913 if(data->codec_id == TNG_TNG_COMPRESSION)
6915 data->compression_multiplier = tng_data->compression_precision;
6917 /* Uncompressed data blocks do not use compression multipliers at all.
6918 * GZip compression does not need it either. */
6919 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6921 data->compression_multiplier = 1.0;
6924 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6926 dependency = TNG_FRAME_DEPENDENT;
6933 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6934 frame_step, stride_length, 0,
6935 1, dependency, &data_start_pos,
6936 &block->block_contents_size) != TNG_SUCCESS)
6938 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6939 __FILE__, __LINE__);
6940 return(TNG_CRITICAL);
6943 if(block->block_contents)
6945 free(block->block_contents);
6947 block->block_contents = malloc(block->block_contents_size);
6948 if(!block->block_contents)
6950 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6951 block->block_contents_size, __FILE__, __LINE__);
6952 return(TNG_CRITICAL);
6956 memcpy(block->block_contents, &data->datatype, sizeof(char));
6957 offset += sizeof(char);
6959 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6960 offset += sizeof(char);
6962 if(dependency & TNG_FRAME_DEPENDENT)
6964 if(stride_length > 1)
6972 memcpy(block->block_contents+offset, &temp, sizeof(char));
6973 offset += sizeof(char);
6976 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6977 sizeof(data->n_values_per_frame));
6978 if(tng_data->output_endianness_swap_func_64)
6980 if(tng_data->output_endianness_swap_func_64(tng_data,
6981 (int64_t *)block->header_contents+offset)
6984 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6985 __FILE__, __LINE__);
6988 offset += sizeof(data->n_values_per_frame);
6990 memcpy(block->block_contents+offset, &data->codec_id,
6991 sizeof(data->codec_id));
6992 if(tng_data->output_endianness_swap_func_64)
6994 if(tng_data->output_endianness_swap_func_64(tng_data,
6995 (int64_t *)block->header_contents+offset)
6998 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6999 __FILE__, __LINE__);
7002 offset += sizeof(data->codec_id);
7004 if(data->codec_id != TNG_UNCOMPRESSED)
7006 memcpy(block->block_contents+offset, &data->compression_multiplier,
7007 sizeof(data->compression_multiplier));
7008 if(tng_data->output_endianness_swap_func_64)
7010 if(tng_data->output_endianness_swap_func_64(tng_data,
7011 (int64_t *)block->header_contents+offset)
7014 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7015 __FILE__, __LINE__);
7018 offset += sizeof(data->compression_multiplier);
7021 if(data->n_frames > 0 && stride_length > 1)
7023 /* FIXME: first_frame_with_data is not reliably set */
7024 if(data->first_frame_with_data == 0)
7026 data->first_frame_with_data = frame_set->first_frame;
7028 memcpy(block->block_contents+offset, &data->first_frame_with_data,
7029 sizeof(data->first_frame_with_data));
7030 if(tng_data->output_endianness_swap_func_64)
7032 if(tng_data->output_endianness_swap_func_64(tng_data,
7033 (int64_t *)block->header_contents+offset)
7036 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7037 __FILE__, __LINE__);
7040 offset += sizeof(data->first_frame_with_data);
7042 memcpy(block->block_contents+offset, &stride_length,
7043 sizeof(data->stride_length));
7044 if(tng_data->output_endianness_swap_func_64)
7046 if(tng_data->output_endianness_swap_func_64(tng_data,
7047 (int64_t *)block->header_contents+offset)
7050 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7051 __FILE__, __LINE__);
7054 offset += sizeof(data->stride_length);
7057 if(data->datatype == TNG_CHAR_DATA)
7061 for(i = 0; i < frame_step; i++)
7063 for(j = 0; j < data->n_values_per_frame; j++)
7065 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7066 strncpy(block->block_contents+offset, data->strings[i][j],
7073 else if(data->values)
7075 memcpy(block->block_contents + offset, data->values,
7076 block->block_contents_size - offset);
7077 switch(data->datatype)
7079 case TNG_FLOAT_DATA:
7080 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7081 data->codec_id == TNG_TNG_COMPRESSION)
7083 if(tng_data->input_endianness_swap_func_32)
7085 for(i = offset; i < block->block_contents_size; i+=size)
7087 if(tng_data->input_endianness_swap_func_32(tng_data,
7088 (int32_t *)(block->block_contents + i))
7091 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7092 __FILE__, __LINE__);
7099 multiplier = data->compression_multiplier;
7100 if(fabs(multiplier - 1.0) > 0.00001 ||
7101 tng_data->input_endianness_swap_func_32)
7103 for(i = offset; block->block_contents_size; i+=size)
7105 *(float *)(block->block_contents + i) *= (float)multiplier;
7106 if(tng_data->input_endianness_swap_func_32 &&
7107 tng_data->input_endianness_swap_func_32(tng_data,
7108 (int32_t *)(block->block_contents + i))
7111 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7112 __FILE__, __LINE__);
7119 if(tng_data->input_endianness_swap_func_64)
7121 for(i = offset; i < block->block_contents_size; i+=size)
7123 if(tng_data->input_endianness_swap_func_64(tng_data,
7124 (int64_t *)(block->block_contents + i))
7127 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7128 __FILE__, __LINE__);
7133 case TNG_DOUBLE_DATA:
7134 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7135 data->codec_id == TNG_TNG_COMPRESSION)
7137 if(tng_data->input_endianness_swap_func_64)
7139 for(i = offset; i < block->block_contents_size; i+=size)
7141 if(tng_data->input_endianness_swap_func_64(tng_data,
7142 (int64_t *)(block->block_contents + i))
7145 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7146 __FILE__, __LINE__);
7153 multiplier = data->compression_multiplier;
7154 if(fabs(multiplier - 1.0) > 0.00001 ||
7155 tng_data->input_endianness_swap_func_64)
7157 for(i = offset; i < block->block_contents_size; i+=size)
7159 *(double *)(block->block_contents + i) *= multiplier;
7160 if(tng_data->input_endianness_swap_func_64 &&
7161 tng_data->input_endianness_swap_func_64(tng_data,
7162 (int64_t *)(block->block_contents + i))
7165 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7166 __FILE__, __LINE__);
7178 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7181 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7182 frame_set->n_unwritten_frames = 0;
7184 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7186 switch(data->codec_id)
7189 case TNG_GZIP_COMPRESSION:
7190 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7191 stat = tng_gzip_compress(tng_data, block,
7192 block->block_contents + data_start_pos,
7193 block->block_contents_size - data_start_pos);
7194 if(stat != TNG_SUCCESS)
7196 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7198 if(stat == TNG_CRITICAL)
7200 return(TNG_CRITICAL);
7202 data->codec_id = TNG_UNCOMPRESSED;
7204 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7210 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7212 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7213 tng_data->output_file_path, __FILE__, __LINE__);
7214 return(TNG_CRITICAL);
7217 if(fwrite(block->block_contents, block->block_contents_size, 1,
7218 tng_data->output_file) != 1)
7220 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7221 __FILE__, __LINE__);
7222 return(TNG_CRITICAL);
7225 return(TNG_SUCCESS);
7228 /** Read the meta information of a data block (particle or non-particle data).
7229 * @param tng_data is a trajectory data container.
7230 * @param block is the block to store the data (should already contain
7231 * the block headers).
7232 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7233 * error has occured.
7235 static tng_function_status tng_data_block_meta_information_read
7236 (tng_trajectory_t tng_data,
7237 tng_gen_block_t block,
7244 int64_t *first_frame_with_data,
7245 int64_t *stride_length,
7247 int64_t *num_first_particle,
7248 int64_t *block_n_particles,
7254 if(block->block_contents)
7256 contents = block->block_contents;
7260 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7261 contents = malloc(meta_size);
7264 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7265 meta_size, __FILE__, __LINE__);
7268 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7270 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7272 return(TNG_CRITICAL);
7276 memcpy(datatype, contents+*offset,
7278 *offset += sizeof(*datatype);
7280 memcpy(dependency, contents+*offset,
7281 sizeof(*dependency));
7282 *offset += sizeof(*dependency);
7284 if(*dependency & TNG_FRAME_DEPENDENT)
7286 memcpy(sparse_data, contents+*offset,
7287 sizeof(*sparse_data));
7288 *offset += sizeof(*sparse_data);
7291 memcpy(n_values, contents+*offset,
7293 if(tng_data->input_endianness_swap_func_64)
7295 if(tng_data->input_endianness_swap_func_64(tng_data,
7299 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7300 __FILE__, __LINE__);
7303 *offset += sizeof(*n_values);
7305 memcpy(codec_id, contents+*offset,
7307 if(tng_data->input_endianness_swap_func_64)
7309 if(tng_data->input_endianness_swap_func_64(tng_data,
7313 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7314 __FILE__, __LINE__);
7317 *offset += sizeof(*codec_id);
7319 if(*codec_id != TNG_UNCOMPRESSED)
7321 memcpy(multiplier, contents+*offset,
7322 sizeof(*multiplier));
7323 if(tng_data->input_endianness_swap_func_64)
7325 if(tng_data->input_endianness_swap_func_64(tng_data,
7326 (int64_t *) multiplier)
7329 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7330 __FILE__, __LINE__);
7333 *offset += sizeof(*multiplier);
7340 if(*dependency & TNG_FRAME_DEPENDENT)
7344 memcpy(first_frame_with_data, contents+*offset,
7345 sizeof(*first_frame_with_data));
7346 if(tng_data->input_endianness_swap_func_64)
7348 if(tng_data->input_endianness_swap_func_64(tng_data,
7349 first_frame_with_data)
7352 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7353 __FILE__, __LINE__);
7356 *offset += sizeof(*first_frame_with_data);
7358 memcpy(stride_length, contents+*offset,
7359 sizeof(*stride_length));
7360 if(tng_data->input_endianness_swap_func_64)
7362 if(tng_data->input_endianness_swap_func_64(tng_data,
7366 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7367 __FILE__, __LINE__);
7370 *offset += sizeof(*stride_length);
7371 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7372 (*first_frame_with_data -
7373 tng_data->current_trajectory_frame_set.first_frame);
7377 *first_frame_with_data = 0;
7379 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7384 *first_frame_with_data = 0;
7389 if (*dependency & TNG_PARTICLE_DEPENDENT)
7391 memcpy(num_first_particle, contents+*offset,
7392 sizeof(*num_first_particle));
7393 if(tng_data->input_endianness_swap_func_64)
7395 if(tng_data->input_endianness_swap_func_64(tng_data,
7399 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7400 __FILE__, __LINE__);
7403 *offset += sizeof(*num_first_particle);
7405 memcpy(block_n_particles, contents+*offset,
7406 sizeof(*block_n_particles));
7407 if(tng_data->input_endianness_swap_func_64)
7409 if(tng_data->input_endianness_swap_func_64(tng_data,
7413 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7414 __FILE__, __LINE__);
7417 *offset += sizeof(*block_n_particles);
7420 if(!block->block_contents)
7424 return(TNG_SUCCESS);
7427 /** Read the contents of a data block (particle or non-particle data).
7428 * @param tng_data is a trajectory data container.
7429 * @param block is the block to store the data (should already contain
7430 * the block headers).
7431 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7432 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7433 * compared to the md5 hash of the read contents to ensure valid data.
7434 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7435 * error has occured.
7437 static tng_function_status tng_data_block_contents_read
7438 (tng_trajectory_t tng_data,
7439 tng_gen_block_t block,
7440 const char hash_mode)
7442 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7443 int64_t stride_length, block_n_particles, num_first_particle;
7445 char datatype, dependency, sparse_data;
7449 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7451 return(TNG_CRITICAL);
7454 if(block->block_contents)
7456 free(block->block_contents);
7459 block->block_contents = malloc(block->block_contents_size);
7460 if(!block->block_contents)
7462 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7463 block->block_contents_size, __FILE__, __LINE__);
7464 return(TNG_CRITICAL);
7467 /* Read the whole block into block_contents to be able to write it to
7468 * disk even if it cannot be interpreted. */
7469 if(fread(block->block_contents, block->block_contents_size, 1,
7470 tng_data->input_file) == 0)
7472 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7473 return(TNG_CRITICAL);
7476 /* FIXME: Does not check if the size of the contents matches the expected
7477 * size or if the contents can be read. */
7479 if(hash_mode == TNG_USE_HASH)
7481 tng_md5_hash_match_verify(block, &same_hash);
7482 if(same_hash != TNG_TRUE)
7484 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7485 block->name, __FILE__, __LINE__);
7486 /* return(TNG_FAILURE); */
7490 if(tng_data_block_meta_information_read(tng_data, block,
7492 &dependency, &sparse_data,
7493 &n_values, &codec_id,
7494 &first_frame_with_data,
7495 &stride_length, &n_frames,
7496 &num_first_particle,
7498 &multiplier) == TNG_CRITICAL)
7500 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7501 block->name, __FILE__, __LINE__);
7502 return(TNG_CRITICAL);
7505 if (dependency & TNG_PARTICLE_DEPENDENT)
7507 return(tng_particle_data_read(tng_data, block,
7511 first_frame_with_data,
7514 codec_id, multiplier));
7518 return(tng_data_read(tng_data, block,
7520 first_frame_with_data,
7523 codec_id, multiplier));
7528 // ** Move the blocks in a frame set so that there is no unused space between
7529 // * them. This can only be done on the last frame set in the file and should
7530 // * be done e.g. if the last frame set in the file has fewer frames than
7531 // * default or after compressing data blocks in a frame set.
7532 // * @param tng_data is a trajectory data container.
7533 // * @details the current_trajectory_frame_set is the one that will be modified.
7534 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7535 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7536 // * FIXME: This function is not finished!!!
7538 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7540 // tng_gen_block_t block;
7541 // tng_trajectory_frame_set_t frame_set;
7542 // FILE *temp = tng_data->input_file;
7543 // int64_t pos, contents_start_pos, output_file_len;
7545 // frame_set = &tng_data->current_trajectory_frame_set;
7547 // if(frame_set->n_written_frames == frame_set->n_frames)
7549 // return(TNG_SUCCESS);
7552 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7553 // tng_data->last_trajectory_frame_set_output_file_pos)
7557 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7559 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7560 // __FILE__, __LINE__);
7561 // return(TNG_CRITICAL);
7564 // tng_block_init(&block);
7565 // // output_file_pos = ftello(tng_data->output_file);
7567 // tng_data->input_file = tng_data->output_file;
7569 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7571 // fseeko(tng_data->output_file, pos, SEEK_SET);
7572 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7574 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7575 // __FILE__, __LINE__);
7576 // tng_data->input_file = temp;
7577 // tng_block_destroy(&block);
7578 // return(TNG_CRITICAL);
7581 // contents_start_pos = ftello(tng_data->output_file);
7583 // fseeko(tng_data->output_file, 0, SEEK_END);
7584 // output_file_len = ftello(tng_data->output_file);
7585 // pos = contents_start_pos + block->block_contents_size;
7586 // fseeko(tng_data->output_file, pos,
7589 // while(pos < output_file_len)
7591 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7593 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7594 // __FILE__, __LINE__);
7595 // tng_data->input_file = temp;
7596 // tng_block_destroy(&block);
7597 // return(TNG_CRITICAL);
7599 // pos += block->header_contents_size + block->block_contents_size;
7600 // fseeko(tng_data->output_file, pos, SEEK_SET);
7603 // return(TNG_SUCCESS);
7606 /** Finish writing the current frame set. Update the number of frames
7607 * and the hashes of the frame set and all its data blocks (if hash_mode
7609 * @param tng_data is a trajectory data container.
7610 * @param hash_mode specifies whether to update the block md5 hash when
7611 * updating the pointers.
7612 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7613 * error has occured.
7615 static tng_function_status tng_frame_set_finalize
7616 (tng_trajectory_t tng_data, const char hash_mode)
7618 tng_gen_block_t block;
7619 tng_trajectory_frame_set_t frame_set;
7620 FILE *temp = tng_data->input_file;
7621 int64_t pos, contents_start_pos, output_file_len;
7623 frame_set = &tng_data->current_trajectory_frame_set;
7625 if(frame_set->n_written_frames == frame_set->n_frames)
7627 return(TNG_SUCCESS);
7630 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7632 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7633 __FILE__, __LINE__);
7634 return(TNG_CRITICAL);
7637 tng_block_init(&block);
7638 /* output_file_pos = ftello(tng_data->output_file); */
7640 tng_data->input_file = tng_data->output_file;
7642 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7644 fseeko(tng_data->output_file, pos, SEEK_SET);
7646 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7648 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7649 __FILE__, __LINE__);
7650 tng_data->input_file = temp;
7651 tng_block_destroy(&block);
7652 return(TNG_CRITICAL);
7655 contents_start_pos = ftello(tng_data->output_file);
7657 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7658 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7659 1, tng_data->output_file) != 1)
7661 tng_data->input_file = temp;
7662 tng_block_destroy(&block);
7663 return(TNG_CRITICAL);
7667 if(hash_mode == TNG_USE_HASH)
7669 tng_md5_hash_update(tng_data, block, pos,
7670 pos + block->header_contents_size);
7673 fseeko(tng_data->output_file, 0, SEEK_END);
7674 output_file_len = ftello(tng_data->output_file);
7675 pos = contents_start_pos + block->block_contents_size;
7676 fseeko(tng_data->output_file, pos, SEEK_SET);
7678 while(pos < output_file_len)
7680 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7682 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7683 __FILE__, __LINE__);
7684 tng_data->input_file = temp;
7685 tng_block_destroy(&block);
7686 return(TNG_CRITICAL);
7689 if(hash_mode == TNG_USE_HASH)
7691 tng_md5_hash_update(tng_data, block, pos,
7692 pos + block->header_contents_size);
7694 pos += block->header_contents_size + block->block_contents_size;
7695 fseeko(tng_data->output_file, pos, SEEK_SET);
7698 tng_data->input_file = temp;
7699 tng_block_destroy(&block);
7700 return(TNG_SUCCESS);
7704 // ** Sets the name of a file contents block
7705 // * @param tng_data is a trajectory data container.
7706 // * @param block is the block, of which to change names.
7707 // * @param new_name is the new name of the block.
7708 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7709 // * error has occured.
7711 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7712 // tng_gen_block_t block,
7713 // const char *new_name)
7717 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7719 // * If the currently stored string length is not enough to store the new
7720 // * string it is freed and reallocated. *
7721 // if(block->name && strlen(block->name) < len)
7723 // free(block->name);
7728 // block->name = malloc(len);
7731 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7732 // __FILE__, __LINE__);
7733 // return(TNG_CRITICAL);
7737 // strncpy(block->name, new_name, len);
7739 // return(TNG_SUCCESS);
7743 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7744 const tng_atom_t atom,
7745 tng_residue_t *residue)
7749 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7751 *residue = atom->residue;
7753 return(TNG_SUCCESS);
7756 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7757 const tng_atom_t atom,
7762 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7763 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7765 strncpy(name, atom->name, max_len - 1);
7766 name[max_len - 1] = 0;
7768 if(strlen(atom->name) > (unsigned int)max_len - 1)
7770 return(TNG_FAILURE);
7772 return(TNG_SUCCESS);
7775 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7777 const char *new_name)
7782 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7783 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7785 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7787 /* If the currently stored string length is not enough to store the new
7788 * string it is freed and reallocated. */
7789 if(atom->name && strlen(atom->name) < len)
7796 atom->name = malloc(len);
7799 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7800 __FILE__, __LINE__);
7801 return(TNG_CRITICAL);
7805 strncpy(atom->name, new_name, len);
7807 return(TNG_SUCCESS);
7810 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7811 const tng_atom_t atom,
7816 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7817 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7819 strncpy(type, atom->atom_type, max_len - 1);
7820 type[max_len - 1] = 0;
7822 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7824 return(TNG_FAILURE);
7826 return(TNG_SUCCESS);
7829 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7831 const char *new_type)
7836 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7837 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7839 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7841 /* If the currently stored string length is not enough to store the new
7842 * string it is freed and reallocated. */
7843 if(atom->atom_type && strlen(atom->atom_type) < len)
7845 free(atom->atom_type);
7846 atom->atom_type = 0;
7848 if(!atom->atom_type)
7850 atom->atom_type = malloc(len);
7851 if(!atom->atom_type)
7853 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7854 __FILE__, __LINE__);
7855 return(TNG_CRITICAL);
7859 strncpy(atom->atom_type, new_type, len);
7861 return(TNG_SUCCESS);
7864 /** Initialise an atom struct
7865 * @param atom is the atom to initialise.
7866 * @return TNG_SUCCESS (0) if successful.
7868 static tng_function_status tng_atom_init(tng_atom_t atom)
7871 atom->atom_type = 0;
7873 return(TNG_SUCCESS);
7876 /** Free the memory in an atom struct
7877 * @param atom is the atom to destroy.
7878 * @return TNG_SUCCESS (0) if successful.
7880 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7889 free(atom->atom_type);
7890 atom->atom_type = 0;
7893 return(TNG_SUCCESS);
7896 tng_function_status DECLSPECDLLEXPORT tng_version_major
7897 (const tng_trajectory_t tng_data,
7902 *version = TNG_VERSION_MAJOR;
7904 return(TNG_SUCCESS);
7907 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7908 (const tng_trajectory_t tng_data,
7913 *version = TNG_VERSION_MINOR;
7915 return(TNG_SUCCESS);
7918 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7919 (const tng_trajectory_t tng_data,
7924 *patch_level = TNG_VERSION_PATCHLEVEL;
7926 return(TNG_SUCCESS);
7929 tng_function_status DECLSPECDLLEXPORT tng_version
7930 (const tng_trajectory_t tng_data,
7935 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
7937 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
7939 return(TNG_SUCCESS);
7942 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7943 (tng_trajectory_t tng_data,
7945 tng_molecule_t *molecule)
7949 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7950 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7952 /* Set ID to the ID of the last molecule + 1 */
7953 if(tng_data->n_molecules)
7955 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7962 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7965 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7966 (tng_trajectory_t tng_data,
7969 tng_molecule_t *molecule)
7971 tng_molecule_t new_molecules;
7972 int64_t *new_molecule_cnt_list;
7973 tng_function_status stat = TNG_SUCCESS;
7975 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7976 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7978 new_molecules = realloc(tng_data->molecules,
7979 sizeof(struct tng_molecule) *
7980 (tng_data->n_molecules + 1));
7984 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7985 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7986 __FILE__, __LINE__);
7987 free(tng_data->molecules);
7988 tng_data->molecules = 0;
7989 return(TNG_CRITICAL);
7992 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7994 (tng_data->n_molecules + 1));
7996 if(!new_molecule_cnt_list)
7998 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7999 sizeof(int64_t) * (tng_data->n_molecules + 1),
8000 __FILE__, __LINE__);
8001 free(tng_data->molecule_cnt_list);
8002 tng_data->molecule_cnt_list = 0;
8003 free(new_molecules);
8004 return(TNG_CRITICAL);
8007 tng_data->molecules = new_molecules;
8008 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8010 *molecule = &new_molecules[tng_data->n_molecules];
8012 tng_molecule_init(tng_data, *molecule);
8013 tng_molecule_name_set(tng_data, *molecule, name);
8015 /* FIXME: Should this be a function argument instead? */
8016 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8018 (*molecule)->id = id;
8020 tng_data->n_molecules++;
8025 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
8026 (tng_trajectory_t tng_data,
8027 tng_molecule_t *molecule_p)
8029 int64_t *new_molecule_cnt_list, id;
8030 tng_molecule_t new_molecules, molecule;
8032 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8034 /* Set ID to the ID of the last molecule + 1 */
8035 if(tng_data->n_molecules)
8037 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
8044 new_molecules = realloc(tng_data->molecules,
8045 sizeof(struct tng_molecule) *
8046 (tng_data->n_molecules + 1));
8050 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8051 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8052 __FILE__, __LINE__);
8053 free(tng_data->molecules);
8054 tng_data->molecules = 0;
8055 return(TNG_CRITICAL);
8058 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8060 (tng_data->n_molecules + 1));
8062 if(!new_molecule_cnt_list)
8064 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8065 sizeof(int64_t) * (tng_data->n_molecules + 1),
8066 __FILE__, __LINE__);
8067 free(tng_data->molecule_cnt_list);
8068 tng_data->molecule_cnt_list = 0;
8069 free(new_molecules);
8070 return(TNG_CRITICAL);
8073 molecule = *molecule_p;
8075 tng_data->molecules = new_molecules;
8076 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8078 new_molecules[tng_data->n_molecules] = *molecule;
8080 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8084 molecule = &new_molecules[tng_data->n_molecules];
8086 *molecule_p = molecule;
8090 tng_data->n_molecules++;
8092 return(TNG_SUCCESS);
8095 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8096 const tng_molecule_t molecule,
8101 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8102 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8104 strncpy(name, molecule->name, max_len - 1);
8105 name[max_len - 1] = 0;
8107 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8109 return(TNG_FAILURE);
8111 return(TNG_SUCCESS);
8114 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8115 (tng_trajectory_t tng_data,
8116 tng_molecule_t molecule,
8117 const char *new_name)
8122 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8123 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8125 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8127 /* If the currently stored string length is not enough to store the new
8128 * string it is freed and reallocated. */
8129 if(molecule->name && strlen(molecule->name) < len)
8131 free(molecule->name);
8136 molecule->name = malloc(len);
8139 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8140 __FILE__, __LINE__);
8141 return(TNG_CRITICAL);
8145 strncpy(molecule->name, new_name, len);
8147 return(TNG_SUCCESS);
8150 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8151 (const tng_trajectory_t tng_data,
8152 const tng_molecule_t molecule,
8155 int64_t i, index = -1;
8157 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8158 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8160 for(i = 0; i < tng_data->n_molecules; i++)
8162 if(&tng_data->molecules[i] == molecule)
8170 return(TNG_FAILURE);
8172 *cnt = tng_data->molecule_cnt_list[index];
8174 return(TNG_SUCCESS);
8177 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8178 (tng_trajectory_t tng_data,
8179 tng_molecule_t molecule,
8182 int64_t i, old_cnt, index = -1;
8184 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8186 for(i = 0; i < tng_data->n_molecules; i++)
8188 if(&tng_data->molecules[i] == molecule)
8196 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8197 __FILE__, __LINE__);
8198 return(TNG_FAILURE);
8200 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8202 old_cnt = tng_data->molecule_cnt_list[index];
8203 tng_data->molecule_cnt_list[index] = cnt;
8205 tng_data->n_particles += (cnt-old_cnt) *
8206 tng_data->molecules[index].n_atoms;
8210 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8211 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8213 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8214 tng_data->molecules[index].n_atoms;
8217 return(TNG_SUCCESS);
8220 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8221 (tng_trajectory_t tng_data,
8224 tng_molecule_t *molecule)
8226 int64_t i, n_molecules;
8228 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8229 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8230 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8232 n_molecules = tng_data->n_molecules;
8234 for(i = n_molecules - 1; i >= 0; i--)
8236 *molecule = &tng_data->molecules[i];
8237 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8239 if(nr == -1 || nr == (*molecule)->id)
8241 return(TNG_SUCCESS);
8248 return(TNG_FAILURE);
8251 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8252 (tng_trajectory_t tng_data,
8254 tng_molecule_t *molecule)
8256 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8257 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8259 if(index >= tng_data->n_molecules)
8262 return(TNG_FAILURE);
8264 *molecule = &tng_data->molecules[index];
8265 return(TNG_SUCCESS);
8268 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8269 tng_trajectory_t tng_data_dest)
8271 tng_molecule_t molecule, molecule_temp;
8272 tng_chain_t chain, chain_temp;
8273 tng_residue_t residue, residue_temp;
8274 tng_atom_t atom, atom_temp;
8275 tng_bond_t bond_temp;
8276 tng_function_status stat;
8277 int64_t i, j, k, l, *list_temp;
8279 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8280 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8282 for(i = 0; i < tng_data_dest->n_molecules; i++)
8284 molecule = &tng_data_dest->molecules[i];
8285 tng_molecule_destroy(tng_data_dest, molecule);
8288 tng_data_dest->n_molecules = 0;
8289 tng_data_dest->n_particles = 0;
8291 molecule_temp = realloc(tng_data_dest->molecules,
8292 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8295 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8296 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8297 __FILE__, __LINE__);
8298 free(tng_data_dest->molecules);
8299 tng_data_dest->molecules = 0;
8300 return(TNG_CRITICAL);
8302 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8303 sizeof(int64_t) * tng_data_src->n_molecules);
8306 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8307 sizeof(int64_t) * tng_data_src->n_molecules,
8308 __FILE__, __LINE__);
8309 free(tng_data_dest->molecule_cnt_list);
8310 tng_data_dest->molecule_cnt_list = 0;
8311 free(molecule_temp);
8312 return(TNG_CRITICAL);
8315 tng_data_dest->molecules = molecule_temp;
8316 tng_data_dest->molecule_cnt_list = list_temp;
8318 for(i = 0; i < tng_data_src->n_molecules; i++)
8320 molecule = &tng_data_src->molecules[i];
8321 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8323 if(stat != TNG_SUCCESS)
8325 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8326 __FILE__, __LINE__);
8329 molecule_temp->quaternary_str = molecule->quaternary_str;
8330 for(j = 0; j < molecule->n_chains; j++)
8332 chain = &molecule->chains[j];
8333 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8334 chain->name, chain->id,
8336 if(stat != TNG_SUCCESS)
8338 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8339 __FILE__, __LINE__);
8342 for(k = 0; k < chain->n_residues; k++)
8344 residue = &chain->residues[k];
8345 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8346 residue->name, residue->id,
8348 if(stat != TNG_SUCCESS)
8350 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8351 __FILE__, __LINE__);
8354 for(l = 0; l < residue->n_atoms; l++)
8356 atom = &molecule->atoms[residue->atoms_offset + l];
8357 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8358 atom->name, atom->atom_type,
8359 atom->id, &atom_temp);
8360 if(stat != TNG_SUCCESS)
8362 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8363 __FILE__, __LINE__);
8369 molecule_temp->n_bonds = molecule->n_bonds;
8370 if(molecule->n_bonds > 0)
8372 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8376 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8377 sizeof(struct tng_bond) * molecule->n_bonds,
8378 __FILE__, __LINE__);
8379 free(molecule_temp->bonds);
8380 molecule_temp->n_bonds = 0;
8381 return(TNG_CRITICAL);
8383 molecule_temp->bonds = bond_temp;
8384 for(j = 0; j < molecule->n_bonds; j++)
8386 molecule_temp->bonds[j] = molecule->bonds[j];
8389 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8390 tng_data_src->molecule_cnt_list[i]);
8391 if(stat != TNG_SUCCESS)
8393 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8394 __FILE__, __LINE__);
8398 return(TNG_SUCCESS);
8401 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8402 (const tng_trajectory_t tng_data,
8403 const tng_molecule_t molecule,
8407 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8408 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8410 *n = molecule->n_chains;
8412 return(TNG_SUCCESS);
8415 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8416 (tng_trajectory_t tng_data,
8417 tng_molecule_t molecule,
8422 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8423 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8425 if(index >= molecule->n_chains)
8428 return(TNG_FAILURE);
8430 *chain = &molecule->chains[index];
8431 return(TNG_SUCCESS);
8434 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8435 (const tng_trajectory_t tng_data,
8436 const tng_molecule_t molecule,
8440 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8441 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8443 *n = molecule->n_residues;
8445 return(TNG_SUCCESS);
8448 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8449 (const tng_trajectory_t tng_data,
8450 const tng_molecule_t molecule,
8451 const int64_t index,
8452 tng_residue_t *residue)
8455 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8456 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8458 if(index >= molecule->n_residues)
8461 return(TNG_FAILURE);
8463 *residue = &molecule->residues[index];
8464 return(TNG_SUCCESS);
8467 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8468 (const tng_trajectory_t tng_data,
8469 const tng_molecule_t molecule,
8473 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8474 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8476 *n = molecule->n_atoms;
8478 return(TNG_SUCCESS);
8481 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8482 (const tng_trajectory_t tng_data,
8483 const tng_molecule_t molecule,
8484 const int64_t index,
8488 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8489 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8491 if(index >= molecule->n_atoms)
8494 return(TNG_FAILURE);
8496 *atom = &molecule->atoms[index];
8497 return(TNG_SUCCESS);
8500 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8501 (tng_trajectory_t tng_data,
8502 tng_molecule_t molecule,
8507 int64_t i, n_chains;
8510 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8511 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8513 n_chains = molecule->n_chains;
8515 for(i = n_chains - 1; i >= 0; i--)
8517 *chain = &molecule->chains[i];
8518 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8520 if(nr == -1 || nr == (*chain)->id)
8522 return(TNG_SUCCESS);
8529 return(TNG_FAILURE);
8532 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8533 (tng_trajectory_t tng_data,
8534 tng_molecule_t molecule,
8540 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8541 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8543 /* Set ID to the ID of the last chain + 1 */
8544 if(molecule->n_chains)
8546 id = molecule->chains[molecule->n_chains-1].id + 1;
8553 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8557 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8558 (tng_trajectory_t tng_data,
8559 tng_molecule_t molecule,
8564 tng_chain_t new_chains;
8565 tng_function_status stat = TNG_SUCCESS;
8567 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8568 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8570 new_chains = realloc(molecule->chains,
8571 sizeof(struct tng_chain) *
8572 (molecule->n_chains + 1));
8576 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8577 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8578 __FILE__, __LINE__);
8579 free(molecule->chains);
8580 molecule->chains = 0;
8581 return(TNG_CRITICAL);
8584 molecule->chains = new_chains;
8586 *chain = &new_chains[molecule->n_chains];
8589 tng_chain_name_set(tng_data, *chain, name);
8591 (*chain)->molecule = molecule;
8592 (*chain)->n_residues = 0;
8594 molecule->n_chains++;
8601 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8602 (const tng_trajectory_t tng_data,
8603 tng_molecule_t molecule,
8604 const int64_t from_atom_id,
8605 const int64_t to_atom_id,
8608 tng_bond_t new_bonds;
8611 new_bonds = realloc(molecule->bonds,
8612 sizeof(struct tng_bond) *
8613 (molecule->n_bonds + 1));
8617 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8618 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8619 __FILE__, __LINE__);
8621 free(molecule->bonds);
8622 molecule->bonds = 0;
8623 return(TNG_CRITICAL);
8626 molecule->bonds = new_bonds;
8628 *bond = &new_bonds[molecule->n_bonds];
8630 (*bond)->from_atom_id = from_atom_id;
8631 (*bond)->to_atom_id = to_atom_id;
8633 molecule->n_bonds++;
8635 return(TNG_SUCCESS);
8638 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8639 (tng_trajectory_t tng_data,
8640 tng_molecule_t molecule,
8648 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8650 n_atoms = molecule->n_atoms;
8652 for(i = n_atoms - 1; i >= 0; i--)
8654 *atom = &molecule->atoms[i];
8655 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8657 if(id == -1 || id == (*atom)->id)
8659 return(TNG_SUCCESS);
8666 return(TNG_FAILURE);
8669 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8670 const tng_chain_t chain,
8675 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8676 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8678 strncpy(name, chain->name, max_len - 1);
8679 name[max_len - 1] = 0;
8681 if(strlen(chain->name) > (unsigned int)max_len - 1)
8683 return(TNG_FAILURE);
8685 return(TNG_SUCCESS);
8688 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8689 (tng_trajectory_t tng_data,
8691 const char *new_name)
8696 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8698 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8700 /* If the currently stored string length is not enough to store the new
8701 * string it is freed and reallocated. */
8702 if(chain->name && strlen(chain->name) < len)
8709 chain->name = malloc(len);
8712 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8713 __FILE__, __LINE__);
8714 return(TNG_CRITICAL);
8718 strncpy(chain->name, new_name, len);
8720 return(TNG_SUCCESS);
8723 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8724 (const tng_trajectory_t tng_data,
8725 const tng_chain_t chain,
8729 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8730 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8732 *n = chain->n_residues;
8734 return(TNG_SUCCESS);
8737 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8738 (const tng_trajectory_t tng_data,
8739 const tng_chain_t chain,
8740 const int64_t index,
8741 tng_residue_t *residue)
8744 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8745 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8747 if(index >= chain->n_residues)
8750 return(TNG_FAILURE);
8752 *residue = &chain->residues[index];
8753 return(TNG_SUCCESS);
8756 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8757 (tng_trajectory_t tng_data,
8761 tng_residue_t *residue)
8763 int64_t i, n_residues;
8766 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8768 n_residues = chain->n_residues;
8770 for(i = n_residues - 1; i >= 0; i--)
8772 *residue = &chain->residues[i];
8773 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8775 if(id == -1 || id == (*residue)->id)
8777 return(TNG_SUCCESS);
8784 return(TNG_FAILURE);
8787 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8788 (tng_trajectory_t tng_data,
8791 tng_residue_t *residue)
8795 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8796 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8798 /* Set ID to the ID of the last residue + 1 */
8799 if(chain->n_residues)
8801 id = chain->residues[chain->n_residues-1].id + 1;
8808 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8812 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8813 (tng_trajectory_t tng_data,
8817 tng_residue_t *residue)
8820 tng_residue_t new_residues, temp_residue, last_residue;
8821 tng_molecule_t molecule = chain->molecule;
8822 tng_function_status stat = TNG_SUCCESS;
8824 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8825 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8827 if(chain->n_residues)
8829 curr_index = chain->residues - molecule->residues;
8836 new_residues = realloc(molecule->residues,
8837 sizeof(struct tng_residue) *
8838 (molecule->n_residues + 1));
8842 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8843 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8844 __FILE__, __LINE__);
8845 free(molecule->residues);
8846 molecule->residues = 0;
8847 return(TNG_CRITICAL);
8850 molecule->residues = new_residues;
8852 if(curr_index != -1)
8854 chain->residues = new_residues + curr_index;
8855 if(molecule->n_residues)
8857 last_residue = &new_residues[molecule->n_residues - 1];
8859 temp_residue = chain->residues + (chain->n_residues - 1);
8860 /* Make space in list of residues to add the new residues together with the other
8861 * residues of this chain */
8862 if(temp_residue != last_residue)
8865 memmove(temp_residue + 1, temp_residue,
8866 last_residue - temp_residue);
8872 curr_index = molecule->n_residues;
8875 *residue = &molecule->residues[curr_index + chain->n_residues];
8877 if(!chain->n_residues)
8879 chain->residues = *residue;
8883 chain->residues = &molecule->residues[curr_index];
8886 (*residue)->name = 0;
8887 tng_residue_name_set(tng_data, *residue, name);
8889 (*residue)->chain = chain;
8890 (*residue)->n_atoms = 0;
8891 (*residue)->atoms_offset = 0;
8893 chain->n_residues++;
8894 molecule->n_residues++;
8896 (*residue)->id = id;
8901 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8902 const tng_residue_t residue,
8907 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8908 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8910 strncpy(name, residue->name, max_len - 1);
8911 name[max_len - 1] = 0;
8913 if(strlen(residue->name) > (unsigned int)max_len - 1)
8915 return(TNG_FAILURE);
8917 return(TNG_SUCCESS);
8920 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8921 tng_residue_t residue,
8922 const char *new_name)
8927 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8928 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8930 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8932 /* If the currently stored string length is not enough to store the new
8933 * string it is freed and reallocated. */
8934 if(residue->name && strlen(residue->name) < len)
8936 free(residue->name);
8941 residue->name = malloc(len);
8944 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8945 __FILE__, __LINE__);
8946 return(TNG_CRITICAL);
8950 strncpy(residue->name, new_name, len);
8952 return(TNG_SUCCESS);
8955 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8956 (const tng_trajectory_t tng_data,
8957 const tng_residue_t residue,
8961 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8962 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8964 *n = residue->n_atoms;
8966 return(TNG_SUCCESS);
8969 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8970 (const tng_trajectory_t tng_data,
8971 const tng_residue_t residue,
8972 const int64_t index,
8976 tng_molecule_t molecule;
8979 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8980 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8982 if(index >= residue->n_atoms)
8985 return(TNG_FAILURE);
8987 chain = residue->chain;
8988 molecule = chain->molecule;
8990 if(index + residue->atoms_offset >= molecule->n_atoms)
8993 return(TNG_FAILURE);
8996 *atom = &molecule->atoms[residue->atoms_offset + index];
8997 return(TNG_SUCCESS);
9000 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
9001 (tng_trajectory_t tng_data,
9002 tng_residue_t residue,
9003 const char *atom_name,
9004 const char *atom_type,
9009 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9010 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9011 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9013 /* Set ID to the ID of the last atom + 1 */
9014 if(residue->chain->molecule->n_atoms)
9016 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
9023 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
9027 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
9028 (tng_trajectory_t tng_data,
9029 tng_residue_t residue,
9030 const char *atom_name,
9031 const char *atom_type,
9035 tng_atom_t new_atoms;
9036 tng_molecule_t molecule = residue->chain->molecule;
9037 tng_function_status stat = TNG_SUCCESS;
9039 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9040 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9041 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9043 if(!residue->n_atoms)
9045 residue->atoms_offset = molecule->n_atoms;
9048 new_atoms = realloc(molecule->atoms,
9049 sizeof(struct tng_atom) *
9050 (molecule->n_atoms + 1));
9054 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9055 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
9056 __FILE__, __LINE__);
9057 free(molecule->atoms);
9058 molecule->atoms = 0;
9059 return(TNG_CRITICAL);
9062 molecule->atoms = new_atoms;
9064 *atom = &new_atoms[molecule->n_atoms];
9066 tng_atom_init(*atom);
9067 tng_atom_name_set(tng_data, *atom, atom_name);
9068 tng_atom_type_set(tng_data, *atom, atom_type);
9070 (*atom)->residue = residue;
9073 molecule->n_atoms++;
9080 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
9081 tng_molecule_t *molecule_p)
9083 *molecule_p = malloc(sizeof(struct tng_molecule));
9086 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9087 sizeof(struct tng_molecule), __FILE__, __LINE__);
9088 return(TNG_CRITICAL);
9091 tng_molecule_init(tng_data, *molecule_p);
9093 return(TNG_SUCCESS);
9096 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9097 tng_molecule_t *molecule_p)
9101 return(TNG_SUCCESS);
9104 tng_molecule_destroy(tng_data, *molecule_p);
9109 return(TNG_SUCCESS);
9112 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9113 tng_molecule_t molecule)
9116 molecule->quaternary_str = 1;
9118 molecule->n_chains = 0;
9119 molecule->chains = 0;
9120 molecule->n_residues = 0;
9121 molecule->residues = 0;
9122 molecule->n_atoms = 0;
9123 molecule->atoms = 0;
9124 molecule->n_bonds = 0;
9125 molecule->bonds = 0;
9127 return(TNG_SUCCESS);
9130 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9131 tng_molecule_t molecule)
9138 free(molecule->name);
9142 if(molecule->chains)
9144 for(i = 0; i < molecule->n_chains; i++)
9146 if(molecule->chains[i].name)
9148 free(molecule->chains[i].name);
9149 molecule->chains[i].name = 0;
9152 free(molecule->chains);
9153 molecule->chains = 0;
9155 molecule->n_chains = 0;
9157 if(molecule->residues)
9159 for(i = 0; i < molecule->n_residues; i++)
9161 if(molecule->residues[i].name)
9163 free(molecule->residues[i].name);
9164 molecule->residues[i].name = 0;
9167 free(molecule->residues);
9168 molecule->residues = 0;
9170 molecule->n_residues = 0;
9174 for(i = 0; i < molecule->n_atoms; i++)
9176 tng_atom_destroy(&molecule->atoms[i]);
9178 free(molecule->atoms);
9179 molecule->atoms = 0;
9181 molecule->n_atoms = 0;
9185 free(molecule->bonds);
9186 molecule->bonds = 0;
9188 molecule->n_bonds = 0;
9190 return(TNG_SUCCESS);
9193 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9194 (const tng_trajectory_t tng_data,
9199 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9201 tng_bool found = TNG_FALSE;
9203 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9204 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9206 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9208 if(!molecule_cnt_list)
9210 return(TNG_FAILURE);
9213 for(i = 0; i < tng_data->n_molecules; i++)
9215 mol = &tng_data->molecules[i];
9216 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9218 cnt += mol->n_atoms * molecule_cnt_list[i];
9226 return(TNG_FAILURE);
9229 strncpy(name, mol->name, max_len - 1);
9230 name[max_len - 1] = 0;
9232 if(strlen(mol->name) > (unsigned int)max_len - 1)
9234 return(TNG_FAILURE);
9236 return(TNG_SUCCESS);
9239 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9240 (const tng_trajectory_t tng_data,
9244 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9246 tng_bool found = TNG_FALSE;
9248 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9249 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9251 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9253 if(!molecule_cnt_list)
9255 return(TNG_FAILURE);
9258 for(i = 0; i < tng_data->n_molecules; i++)
9260 mol = &tng_data->molecules[i];
9261 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9263 cnt += mol->n_atoms * molecule_cnt_list[i];
9271 return(TNG_FAILURE);
9276 return(TNG_SUCCESS);
9279 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9280 (const tng_trajectory_t tng_data,
9282 int64_t **from_atoms,
9285 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9286 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9290 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9291 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9292 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9293 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9295 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9297 if(!molecule_cnt_list)
9299 return(TNG_FAILURE);
9303 /* First count the total number of bonds to allocate memory */
9304 for(i = 0; i < tng_data->n_molecules; i++)
9306 mol = &tng_data->molecules[i];
9307 mol_cnt = molecule_cnt_list[i];
9308 *n_bonds += mol_cnt * mol->n_bonds;
9312 return(TNG_SUCCESS);
9315 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9318 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9319 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9320 return(TNG_CRITICAL);
9322 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9325 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9326 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9329 return(TNG_CRITICAL);
9333 for(i = 0; i < tng_data->n_molecules; i++)
9335 mol = &tng_data->molecules[i];
9336 mol_cnt = molecule_cnt_list[i];
9337 for(j = 0; j < mol_cnt; j++)
9339 for(k = 0; k < mol->n_bonds; k++)
9341 bond = &mol->bonds[k];
9342 from_atom = atom_cnt + bond->from_atom_id;
9343 to_atom = atom_cnt + bond->to_atom_id;
9344 (*from_atoms)[cnt] = from_atom;
9345 (*to_atoms)[cnt++] = to_atom;
9347 atom_cnt += mol->n_atoms;
9351 return(TNG_SUCCESS);
9354 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9355 (const tng_trajectory_t tng_data,
9360 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9363 tng_bool found = TNG_FALSE;
9365 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9366 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9368 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9370 if(!molecule_cnt_list)
9372 return(TNG_FAILURE);
9375 for(i = 0; i < tng_data->n_molecules; i++)
9377 mol = &tng_data->molecules[i];
9378 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9380 cnt += mol->n_atoms * molecule_cnt_list[i];
9383 atom = &mol->atoms[nr % mol->n_atoms];
9389 return(TNG_FAILURE);
9391 if(!atom->residue || !atom->residue->chain)
9393 return(TNG_FAILURE);
9396 strncpy(name, atom->residue->chain->name, max_len - 1);
9397 name[max_len - 1] = 0;
9399 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9401 return(TNG_FAILURE);
9403 return(TNG_SUCCESS);
9406 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9407 (const tng_trajectory_t tng_data,
9412 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9415 tng_bool found = TNG_FALSE;
9417 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9418 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9420 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9422 if(!molecule_cnt_list)
9424 return(TNG_FAILURE);
9427 for(i = 0; i < tng_data->n_molecules; i++)
9429 mol = &tng_data->molecules[i];
9430 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9432 cnt += mol->n_atoms * molecule_cnt_list[i];
9435 atom = &mol->atoms[nr % mol->n_atoms];
9441 return(TNG_FAILURE);
9445 return(TNG_FAILURE);
9448 strncpy(name, atom->residue->name, max_len - 1);
9449 name[max_len - 1] = 0;
9451 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9453 return(TNG_FAILURE);
9455 return(TNG_SUCCESS);
9458 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9459 (const tng_trajectory_t tng_data,
9463 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9466 tng_bool found = TNG_FALSE;
9468 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9469 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9471 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9473 if(!molecule_cnt_list)
9475 return(TNG_FAILURE);
9478 for(i = 0; i < tng_data->n_molecules; i++)
9480 mol = &tng_data->molecules[i];
9481 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9483 cnt += mol->n_atoms * molecule_cnt_list[i];
9486 atom = &mol->atoms[nr % mol->n_atoms];
9492 return(TNG_FAILURE);
9496 return(TNG_FAILURE);
9499 *id = atom->residue->id;
9501 return(TNG_SUCCESS);
9504 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9505 (const tng_trajectory_t tng_data,
9509 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9512 tng_bool found = TNG_FALSE;
9514 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9515 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9517 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9519 if(!molecule_cnt_list)
9521 return(TNG_FAILURE);
9524 for(i = 0; i < tng_data->n_molecules; i++)
9526 mol = &tng_data->molecules[i];
9527 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9529 cnt += mol->n_atoms * molecule_cnt_list[i];
9530 offset += mol->n_residues * molecule_cnt_list[i];
9533 atom = &mol->atoms[nr % mol->n_atoms];
9539 return(TNG_FAILURE);
9543 return(TNG_FAILURE);
9546 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9548 *id = atom->residue->id + offset;
9550 return(TNG_SUCCESS);
9553 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9554 (const tng_trajectory_t tng_data,
9559 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9562 tng_bool found = TNG_FALSE;
9564 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9565 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9567 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9569 if(!molecule_cnt_list)
9571 return(TNG_FAILURE);
9574 for(i = 0; i < tng_data->n_molecules; i++)
9576 mol = &tng_data->molecules[i];
9577 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9579 cnt += mol->n_atoms * molecule_cnt_list[i];
9582 atom = &mol->atoms[nr % mol->n_atoms];
9588 return(TNG_FAILURE);
9591 strncpy(name, atom->name, max_len - 1);
9592 name[max_len - 1] = 0;
9594 if(strlen(atom->name) > (unsigned int)max_len - 1)
9596 return(TNG_FAILURE);
9598 return(TNG_SUCCESS);
9601 tng_function_status tng_atom_type_of_particle_nr_get
9602 (const tng_trajectory_t tng_data,
9607 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9610 tng_bool found = TNG_FALSE;
9612 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9613 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9615 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9617 if(!molecule_cnt_list)
9619 return(TNG_FAILURE);
9622 for(i = 0; i < tng_data->n_molecules; i++)
9624 mol = &tng_data->molecules[i];
9625 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9627 cnt += mol->n_atoms * molecule_cnt_list[i];
9630 atom = &mol->atoms[nr % mol->n_atoms];
9636 return(TNG_FAILURE);
9639 strncpy(type, atom->atom_type, max_len - 1);
9640 type[max_len - 1] = 0;
9642 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9644 return(TNG_FAILURE);
9646 return(TNG_SUCCESS);
9649 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9650 (tng_trajectory_t tng_data,
9651 const int64_t num_first_particle,
9652 const int64_t n_particles,
9653 const int64_t *mapping_table)
9656 tng_particle_mapping_t mapping;
9657 tng_trajectory_frame_set_t frame_set;
9659 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9661 frame_set = &tng_data->current_trajectory_frame_set;
9663 /* Sanity check of the particle ranges. Split into multiple if
9664 * statements for improved readability */
9665 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9667 mapping = &frame_set->mappings[i];
9668 if(num_first_particle >= mapping->num_first_particle &&
9669 num_first_particle < mapping->num_first_particle +
9670 mapping->n_particles)
9672 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9673 return(TNG_FAILURE);
9675 if(num_first_particle + n_particles >=
9676 mapping->num_first_particle &&
9677 num_first_particle + n_particles <
9678 mapping->num_first_particle + mapping->n_particles)
9680 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9681 return(TNG_FAILURE);
9683 if(mapping->num_first_particle >= num_first_particle &&
9684 mapping->num_first_particle < num_first_particle +
9687 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9688 return(TNG_FAILURE);
9690 if(mapping->num_first_particle + mapping->n_particles >
9691 num_first_particle &&
9692 mapping->num_first_particle + mapping->n_particles <
9693 num_first_particle + n_particles)
9695 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9696 return(TNG_FAILURE);
9700 frame_set->n_mapping_blocks++;
9702 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9703 frame_set->n_mapping_blocks);
9707 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9708 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9709 __FILE__, __LINE__);
9710 free(frame_set->mappings);
9711 frame_set->mappings = 0;
9712 return(TNG_CRITICAL);
9714 frame_set->mappings = mapping;
9716 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9717 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9719 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9720 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9722 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9723 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9724 return(TNG_CRITICAL);
9727 for(i=0; i<n_particles; i++)
9729 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9732 return(TNG_SUCCESS);
9735 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9737 tng_trajectory_frame_set_t frame_set;
9738 tng_particle_mapping_t mapping;
9741 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9743 frame_set = &tng_data->current_trajectory_frame_set;
9745 if(frame_set->n_mapping_blocks && frame_set->mappings)
9747 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9749 mapping = &frame_set->mappings[i];
9750 if(mapping->real_particle_numbers)
9752 free(mapping->real_particle_numbers);
9753 mapping->real_particle_numbers = 0;
9756 free(frame_set->mappings);
9757 frame_set->mappings = 0;
9758 frame_set->n_mapping_blocks = 0;
9761 return(TNG_SUCCESS);
9764 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9767 tng_trajectory_frame_set_t frame_set;
9768 tng_trajectory_t tng_data;
9770 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9773 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9774 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9775 return(TNG_CRITICAL);
9778 tng_data = *tng_data_p;
9780 frame_set = &tng_data->current_trajectory_frame_set;
9782 tng_data->input_file_path = 0;
9783 tng_data->input_file = 0;
9784 tng_data->input_file_len = 0;
9785 tng_data->output_file_path = 0;
9786 tng_data->output_file = 0;
9788 tng_data->first_program_name = 0;
9789 tng_data->first_user_name = 0;
9790 tng_data->first_computer_name = 0;
9791 tng_data->first_pgp_signature = 0;
9792 tng_data->last_program_name = 0;
9793 tng_data->last_user_name = 0;
9794 tng_data->last_computer_name = 0;
9795 tng_data->last_pgp_signature = 0;
9796 tng_data->forcefield_name = 0;
9801 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9805 tng_data->time = seconds;
9808 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9809 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9810 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9811 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9812 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9813 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9814 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9815 tng_data->frame_set_n_frames = 100;
9816 tng_data->n_trajectory_frame_sets = 0;
9817 tng_data->medium_stride_length = 100;
9818 tng_data->long_stride_length = 10000;
9820 tng_data->time_per_frame = -1;
9822 tng_data->n_particle_data_blocks = 0;
9823 tng_data->n_data_blocks = 0;
9825 tng_data->non_tr_particle_data = 0;
9826 tng_data->non_tr_data = 0;
9828 tng_data->compress_algo_pos = 0;
9829 tng_data->compress_algo_vel = 0;
9830 tng_data->compression_precision = 1000;
9831 tng_data->distance_unit_exponential = -9;
9833 frame_set->first_frame = -1;
9834 frame_set->n_mapping_blocks = 0;
9835 frame_set->mappings = 0;
9836 frame_set->molecule_cnt_list = 0;
9838 frame_set->n_particle_data_blocks = 0;
9839 frame_set->n_data_blocks = 0;
9841 frame_set->tr_particle_data = 0;
9842 frame_set->tr_data = 0;
9844 frame_set->n_written_frames = 0;
9845 frame_set->n_unwritten_frames = 0;
9847 frame_set->next_frame_set_file_pos = -1;
9848 frame_set->prev_frame_set_file_pos = -1;
9849 frame_set->medium_stride_next_frame_set_file_pos = -1;
9850 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9851 frame_set->long_stride_next_frame_set_file_pos = -1;
9852 frame_set->long_stride_prev_frame_set_file_pos = -1;
9854 frame_set->first_frame_time = -1;
9856 tng_data->n_molecules = 0;
9857 tng_data->molecules = 0;
9858 tng_data->molecule_cnt_list = 0;
9859 tng_data->n_particles = 0;
9862 /* Check the endianness of the computer */
9863 static int32_t endianness_32 = 0x01234567;
9865 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9867 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9871 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9873 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9878 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9880 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9884 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9885 /* 0x0123456789ABCDEF */
9886 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9888 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9891 /* 0xEFCDAB8967452301 */
9892 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9894 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9897 /* 0x89ABCDEF01234567 */
9898 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9900 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9903 /* 0x45670123CDEF89AB */
9904 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9906 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9909 /* 0x23016745AB89EFCD */
9910 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9912 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9916 /* By default do not swap the byte order, i.e. keep the byte order of the
9917 * architecture. The input file endianness will be set when reading the
9918 * header. The output endianness can be changed - before the file is
9920 tng_data->input_endianness_swap_func_32 = 0;
9921 tng_data->input_endianness_swap_func_64 = 0;
9922 tng_data->output_endianness_swap_func_32 = 0;
9923 tng_data->output_endianness_swap_func_64 = 0;
9925 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9926 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9927 tng_data->current_trajectory_frame_set.n_frames = 0;
9929 return(TNG_SUCCESS);
9932 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9935 int64_t n_particles, n_values_per_frame;
9936 tng_trajectory_t tng_data = *tng_data_p;
9937 tng_trajectory_frame_set_t frame_set;
9941 return(TNG_SUCCESS);
9944 frame_set = &tng_data->current_trajectory_frame_set;
9946 if(tng_data->input_file_path)
9948 free(tng_data->input_file_path);
9949 tng_data->input_file_path = 0;
9952 if(tng_data->input_file)
9954 if(tng_data->output_file == tng_data->input_file)
9956 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9957 tng_data->output_file = 0;
9959 fclose(tng_data->input_file);
9960 tng_data->input_file = 0;
9963 if(tng_data->output_file_path)
9965 free(tng_data->output_file_path);
9966 tng_data->output_file_path = 0;
9969 if(tng_data->output_file)
9971 /* FIXME: Do not always write the hash */
9972 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9973 fclose(tng_data->output_file);
9974 tng_data->output_file = 0;
9977 if(tng_data->first_program_name)
9979 free(tng_data->first_program_name);
9980 tng_data->first_program_name = 0;
9983 if(tng_data->last_program_name)
9985 free(tng_data->last_program_name);
9986 tng_data->last_program_name = 0;
9989 if(tng_data->first_user_name)
9991 free(tng_data->first_user_name);
9992 tng_data->first_user_name = 0;
9995 if(tng_data->last_user_name)
9997 free(tng_data->last_user_name);
9998 tng_data->last_user_name = 0;
10001 if(tng_data->first_computer_name)
10003 free(tng_data->first_computer_name);
10004 tng_data->first_computer_name = 0;
10007 if(tng_data->last_computer_name)
10009 free(tng_data->last_computer_name);
10010 tng_data->last_computer_name = 0;
10013 if(tng_data->first_pgp_signature)
10015 free(tng_data->first_pgp_signature);
10016 tng_data->first_pgp_signature = 0;
10019 if(tng_data->last_pgp_signature)
10021 free(tng_data->last_pgp_signature);
10022 tng_data->last_pgp_signature = 0;
10025 if(tng_data->forcefield_name)
10027 free(tng_data->forcefield_name);
10028 tng_data->forcefield_name = 0;
10031 tng_frame_set_particle_mapping_free(tng_data);
10033 if(frame_set->molecule_cnt_list)
10035 free(frame_set->molecule_cnt_list);
10036 frame_set->molecule_cnt_list = 0;
10039 if(tng_data->var_num_atoms_flag)
10041 n_particles = frame_set->n_particles;
10045 n_particles = tng_data->n_particles;
10048 if(tng_data->non_tr_particle_data)
10050 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
10052 if(tng_data->non_tr_particle_data[i].values)
10054 free(tng_data->non_tr_particle_data[i].values);
10055 tng_data->non_tr_particle_data[i].values = 0;
10058 if(tng_data->non_tr_particle_data[i].strings)
10060 n_values_per_frame = tng_data->non_tr_particle_data[i].
10061 n_values_per_frame;
10062 if(tng_data->non_tr_particle_data[i].strings[0])
10064 for(j = 0; j < n_particles; j++)
10066 if(tng_data->non_tr_particle_data[i].strings[0][j])
10068 for(k = 0; k < n_values_per_frame; k++)
10070 if(tng_data->non_tr_particle_data[i].
10073 free(tng_data->non_tr_particle_data[i].
10075 tng_data->non_tr_particle_data[i].
10076 strings[0][j][k] = 0;
10079 free(tng_data->non_tr_particle_data[i].
10081 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
10084 free(tng_data->non_tr_particle_data[i].strings[0]);
10085 tng_data->non_tr_particle_data[i].strings[0] = 0;
10087 free(tng_data->non_tr_particle_data[i].strings);
10088 tng_data->non_tr_particle_data[i].strings = 0;
10091 if(tng_data->non_tr_particle_data[i].block_name)
10093 free(tng_data->non_tr_particle_data[i].block_name);
10094 tng_data->non_tr_particle_data[i].block_name = 0;
10097 free(tng_data->non_tr_particle_data);
10098 tng_data->non_tr_particle_data = 0;
10101 if(tng_data->non_tr_data)
10103 for(i = 0; i < tng_data->n_data_blocks; i++)
10105 if(tng_data->non_tr_data[i].values)
10107 free(tng_data->non_tr_data[i].values);
10108 tng_data->non_tr_data[i].values = 0;
10111 if(tng_data->non_tr_data[i].strings)
10113 n_values_per_frame = tng_data->non_tr_data[i].
10114 n_values_per_frame;
10115 if(tng_data->non_tr_data[i].strings[0])
10117 for(j = 0; j < n_values_per_frame; j++)
10119 if(tng_data->non_tr_data[i].strings[0][j])
10121 free(tng_data->non_tr_data[i].strings[0][j]);
10122 tng_data->non_tr_data[i].strings[0][j] = 0;
10125 free(tng_data->non_tr_data[i].strings[0]);
10126 tng_data->non_tr_data[i].strings[0] = 0;
10128 free(tng_data->non_tr_data[i].strings);
10129 tng_data->non_tr_data[i].strings = 0;
10132 if(tng_data->non_tr_data[i].block_name)
10134 free(tng_data->non_tr_data[i].block_name);
10135 tng_data->non_tr_data[i].block_name = 0;
10138 free(tng_data->non_tr_data);
10139 tng_data->non_tr_data = 0;
10142 tng_data->n_particle_data_blocks = 0;
10143 tng_data->n_data_blocks = 0;
10145 if(tng_data->compress_algo_pos)
10147 free(tng_data->compress_algo_pos);
10148 tng_data->compress_algo_pos = 0;
10150 if(tng_data->compress_algo_vel)
10152 free(tng_data->compress_algo_vel);
10153 tng_data->compress_algo_vel = 0;
10156 if(frame_set->tr_particle_data)
10158 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10160 if(frame_set->tr_particle_data[i].values)
10162 free(frame_set->tr_particle_data[i].values);
10163 frame_set->tr_particle_data[i].values = 0;
10166 if(frame_set->tr_particle_data[i].strings)
10168 n_values_per_frame = frame_set->tr_particle_data[i].
10169 n_values_per_frame;
10170 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10172 if(frame_set->tr_particle_data[i].strings[j])
10174 for(k = 0; k < n_particles; k++)
10176 if(frame_set->tr_particle_data[i].
10179 for(l = 0; l < n_values_per_frame; l++)
10181 if(frame_set->tr_particle_data[i].
10184 free(frame_set->tr_particle_data[i].
10186 frame_set->tr_particle_data[i].
10187 strings[j][k][l] = 0;
10190 free(frame_set->tr_particle_data[i].
10192 frame_set->tr_particle_data[i].
10196 free(frame_set->tr_particle_data[i].strings[j]);
10197 frame_set->tr_particle_data[i].strings[j] = 0;
10200 free(frame_set->tr_particle_data[i].strings);
10201 frame_set->tr_particle_data[i].strings = 0;
10204 if(frame_set->tr_particle_data[i].block_name)
10206 free(frame_set->tr_particle_data[i].block_name);
10207 frame_set->tr_particle_data[i].block_name = 0;
10210 free(frame_set->tr_particle_data);
10211 frame_set->tr_particle_data = 0;
10214 if(frame_set->tr_data)
10216 for(i = 0; i < frame_set->n_data_blocks; i++)
10218 if(frame_set->tr_data[i].values)
10220 free(frame_set->tr_data[i].values);
10221 frame_set->tr_data[i].values = 0;
10224 if(frame_set->tr_data[i].strings)
10226 n_values_per_frame = frame_set->tr_data[i].
10227 n_values_per_frame;
10228 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10230 if(frame_set->tr_data[i].strings[j])
10232 for(k = 0; k < n_values_per_frame; k++)
10234 if(frame_set->tr_data[i].strings[j][k])
10236 free(frame_set->tr_data[i].strings[j][k]);
10237 frame_set->tr_data[i].strings[j][k] = 0;
10240 free(frame_set->tr_data[i].strings[j]);
10241 frame_set->tr_data[i].strings[j] = 0;
10244 free(frame_set->tr_data[i].strings);
10245 frame_set->tr_data[i].strings = 0;
10248 if(frame_set->tr_data[i].block_name)
10250 free(frame_set->tr_data[i].block_name);
10251 frame_set->tr_data[i].block_name = 0;
10254 free(frame_set->tr_data);
10255 frame_set->tr_data = 0;
10258 frame_set->n_particle_data_blocks = 0;
10259 frame_set->n_data_blocks = 0;
10261 if(tng_data->molecules)
10263 for(i = 0; i < tng_data->n_molecules; i++)
10265 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10267 free(tng_data->molecules);
10268 tng_data->molecules = 0;
10269 tng_data->n_molecules = 0;
10271 if(tng_data->molecule_cnt_list)
10273 free(tng_data->molecule_cnt_list);
10274 tng_data->molecule_cnt_list = 0;
10280 return(TNG_SUCCESS);
10283 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10284 tng_trajectory_t *dest_p)
10286 tng_trajectory_frame_set_t frame_set;
10287 tng_trajectory_t dest;
10289 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10291 *dest_p = malloc(sizeof(struct tng_trajectory));
10294 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10295 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10296 return(TNG_CRITICAL);
10301 frame_set = &dest->current_trajectory_frame_set;
10303 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10304 if(!dest->input_file_path)
10306 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10307 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10308 return(TNG_CRITICAL);
10310 strcpy(dest->input_file_path, src->input_file_path);
10311 dest->input_file = 0;
10312 dest->input_file_len = src->input_file_len;
10313 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10314 if(!dest->output_file_path)
10316 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10317 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10318 return(TNG_CRITICAL);
10320 strcpy(dest->output_file_path, src->output_file_path);
10321 dest->output_file = 0;
10323 dest->first_program_name = 0;
10324 dest->first_user_name = 0;
10325 dest->first_computer_name = 0;
10326 dest->first_pgp_signature = 0;
10327 dest->last_program_name = 0;
10328 dest->last_user_name = 0;
10329 dest->last_computer_name = 0;
10330 dest->last_pgp_signature = 0;
10331 dest->forcefield_name = 0;
10333 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10334 dest->first_trajectory_frame_set_input_file_pos =
10335 src->first_trajectory_frame_set_input_file_pos;
10336 dest->last_trajectory_frame_set_input_file_pos =
10337 src->last_trajectory_frame_set_input_file_pos;
10338 dest->current_trajectory_frame_set_input_file_pos =
10339 src->current_trajectory_frame_set_input_file_pos;
10340 dest->first_trajectory_frame_set_output_file_pos =
10341 src->first_trajectory_frame_set_output_file_pos;
10342 dest->last_trajectory_frame_set_output_file_pos =
10343 src->last_trajectory_frame_set_output_file_pos;
10344 dest->current_trajectory_frame_set_output_file_pos =
10345 src->current_trajectory_frame_set_output_file_pos;
10346 dest->frame_set_n_frames = src->frame_set_n_frames;
10347 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10348 dest->medium_stride_length = src->medium_stride_length;
10349 dest->long_stride_length = src->long_stride_length;
10351 dest->time_per_frame = src->time_per_frame;
10353 /* Currently the non trajectory data blocks are not copied since it
10354 * can lead to problems when freeing memory in a parallel block. */
10355 dest->n_particle_data_blocks = 0;
10356 dest->n_data_blocks = 0;
10357 dest->non_tr_particle_data = 0;
10358 dest->non_tr_data = 0;
10360 dest->compress_algo_pos = 0;
10361 dest->compress_algo_vel = 0;
10362 dest->distance_unit_exponential = -9;
10363 dest->compression_precision = 1000;
10365 frame_set->n_mapping_blocks = 0;
10366 frame_set->mappings = 0;
10367 frame_set->molecule_cnt_list = 0;
10369 frame_set->n_particle_data_blocks = 0;
10370 frame_set->n_data_blocks = 0;
10372 frame_set->tr_particle_data = 0;
10373 frame_set->tr_data = 0;
10375 frame_set->next_frame_set_file_pos = -1;
10376 frame_set->prev_frame_set_file_pos = -1;
10377 frame_set->medium_stride_next_frame_set_file_pos = -1;
10378 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10379 frame_set->long_stride_next_frame_set_file_pos = -1;
10380 frame_set->long_stride_prev_frame_set_file_pos = -1;
10381 frame_set->first_frame = -1;
10383 dest->n_molecules = 0;
10384 dest->molecules = 0;
10385 dest->molecule_cnt_list = 0;
10386 dest->n_particles = src->n_particles;
10388 dest->endianness_32 = src->endianness_32;
10389 dest->endianness_64 = src->endianness_64;
10390 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10391 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10392 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10393 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10395 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10396 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10397 dest->current_trajectory_frame_set.n_frames = 0;
10399 return(TNG_SUCCESS);
10402 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10403 char *file_name, const int max_len)
10405 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10406 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10408 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10409 file_name[max_len - 1] = 0;
10411 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10413 return(TNG_FAILURE);
10415 return(TNG_SUCCESS);
10418 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10419 const char *file_name)
10424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10425 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10428 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10431 return(TNG_SUCCESS);
10434 if(tng_data->input_file)
10436 fclose(tng_data->input_file);
10439 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10440 temp = realloc(tng_data->input_file_path, len);
10443 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10444 __FILE__, __LINE__);
10445 free(tng_data->input_file_path);
10446 tng_data->input_file_path = 0;
10447 return(TNG_CRITICAL);
10449 tng_data->input_file_path = temp;
10451 strncpy(tng_data->input_file_path, file_name, len);
10453 return(tng_input_file_init(tng_data));
10456 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10457 char *file_name, const int max_len)
10459 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10460 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10462 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10463 file_name[max_len - 1] = 0;
10465 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10467 return(TNG_FAILURE);
10469 return(TNG_SUCCESS);
10472 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10473 const char *file_name)
10478 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10479 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10481 if(tng_data->output_file_path &&
10482 strcmp(tng_data->output_file_path, file_name) == 0)
10484 return(TNG_SUCCESS);
10487 if(tng_data->output_file)
10489 fclose(tng_data->output_file);
10492 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10493 temp = realloc(tng_data->output_file_path, len);
10496 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10497 __FILE__, __LINE__);
10498 free(tng_data->output_file_path);
10499 tng_data->output_file_path = 0;
10500 return(TNG_CRITICAL);
10502 tng_data->output_file_path = temp;
10504 strncpy(tng_data->output_file_path, file_name, len);
10506 return(tng_output_file_init(tng_data));
10509 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10510 (tng_trajectory_t tng_data,
10511 const char *file_name)
10516 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10517 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10519 if(tng_data->output_file_path &&
10520 strcmp(tng_data->output_file_path, file_name) == 0)
10522 return(TNG_SUCCESS);
10525 if(tng_data->output_file)
10527 fclose(tng_data->output_file);
10530 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10531 temp = realloc(tng_data->output_file_path, len);
10534 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10535 __FILE__, __LINE__);
10536 free(tng_data->output_file_path);
10537 tng_data->output_file_path = 0;
10538 return(TNG_CRITICAL);
10540 tng_data->output_file_path = temp;
10542 strncpy(tng_data->output_file_path, file_name, len);
10544 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10545 if(!tng_data->output_file)
10547 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10548 tng_data->output_file_path, __FILE__, __LINE__);
10549 return(TNG_CRITICAL);
10551 tng_data->input_file = tng_data->output_file;
10553 return(TNG_SUCCESS);
10556 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10557 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10559 tng_endianness_32 end_32;
10560 tng_endianness_64 end_64;
10562 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10563 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10565 if(tng_data->output_endianness_swap_func_32)
10567 /* If other endianness variants are added they must be added here as well */
10568 if(tng_data->output_endianness_swap_func_32 ==
10569 &tng_swap_byte_order_big_endian_32)
10571 end_32 = TNG_BIG_ENDIAN_32;
10573 else if(tng_data->output_endianness_swap_func_32 ==
10574 &tng_swap_byte_order_little_endian_32)
10576 end_32 = TNG_LITTLE_ENDIAN_32;
10580 return(TNG_FAILURE);
10585 end_32 = (tng_endianness_32)tng_data->endianness_32;
10588 if(tng_data->output_endianness_swap_func_64)
10590 /* If other endianness variants are added they must be added here as well */
10591 if(tng_data->output_endianness_swap_func_64 ==
10592 &tng_swap_byte_order_big_endian_64)
10594 end_64 = TNG_BIG_ENDIAN_64;
10596 else if(tng_data->output_endianness_swap_func_64 ==
10597 &tng_swap_byte_order_little_endian_64)
10599 end_64 = TNG_LITTLE_ENDIAN_64;
10603 return(TNG_FAILURE);
10608 end_64 = (tng_endianness_64)tng_data->endianness_64;
10611 if((int)end_32 != (int)end_64)
10613 return(TNG_FAILURE);
10616 if(end_32 == TNG_LITTLE_ENDIAN_32)
10618 *endianness = TNG_LITTLE_ENDIAN;
10621 else if(end_32 == TNG_BIG_ENDIAN_32)
10623 *endianness = TNG_BIG_ENDIAN;
10627 return(TNG_FAILURE);
10630 return(TNG_SUCCESS);
10633 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10634 (tng_trajectory_t tng_data,
10635 const tng_file_endianness endianness)
10637 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10639 /* Tne endianness cannot be changed if the data has already been written
10640 * to the output file. */
10641 if(ftello(tng_data->output_file) > 0)
10643 return(TNG_FAILURE);
10646 if(endianness == TNG_BIG_ENDIAN)
10648 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10650 tng_data->output_endianness_swap_func_32 = 0;
10654 tng_data->output_endianness_swap_func_32 =
10655 &tng_swap_byte_order_big_endian_32;
10657 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10659 tng_data->output_endianness_swap_func_64 = 0;
10663 tng_data->output_endianness_swap_func_64 =
10664 &tng_swap_byte_order_big_endian_64;
10666 return(TNG_SUCCESS);
10668 else if(endianness == TNG_LITTLE_ENDIAN)
10670 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10672 tng_data->output_endianness_swap_func_32 = 0;
10676 tng_data->output_endianness_swap_func_32 =
10677 &tng_swap_byte_order_little_endian_32;
10679 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10681 tng_data->output_endianness_swap_func_64 = 0;
10685 tng_data->output_endianness_swap_func_64 =
10686 &tng_swap_byte_order_little_endian_64;
10688 return(TNG_SUCCESS);
10691 /* If the specified endianness is neither big nor little endian return a
10693 return(TNG_FAILURE);
10696 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10697 (const tng_trajectory_t tng_data,
10698 char *name, const int max_len)
10700 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10701 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10703 strncpy(name, tng_data->first_program_name, max_len - 1);
10704 name[max_len - 1] = 0;
10706 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10708 return(TNG_FAILURE);
10710 return(TNG_SUCCESS);
10713 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10714 const char *new_name)
10718 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10719 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10721 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10723 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10725 free(tng_data->first_program_name);
10726 tng_data->first_program_name = 0;
10728 if(!tng_data->first_program_name)
10730 tng_data->first_program_name = malloc(len);
10731 if(!tng_data->first_program_name)
10733 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10734 __FILE__, __LINE__);
10735 return(TNG_CRITICAL);
10739 strncpy(tng_data->first_program_name, new_name, len);
10741 return(TNG_SUCCESS);
10744 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10745 (const tng_trajectory_t tng_data,
10746 char *name, const int max_len)
10748 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10749 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10751 strncpy(name, tng_data->last_program_name, max_len - 1);
10752 name[max_len - 1] = 0;
10754 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10756 return(TNG_FAILURE);
10758 return(TNG_SUCCESS);
10761 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10762 (tng_trajectory_t tng_data,
10763 const char *new_name)
10767 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10768 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10770 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10772 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10774 free(tng_data->last_program_name);
10775 tng_data->last_program_name = 0;
10777 if(!tng_data->last_program_name)
10779 tng_data->last_program_name = malloc(len);
10780 if(!tng_data->last_program_name)
10782 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10783 __FILE__, __LINE__);
10784 return(TNG_CRITICAL);
10788 strncpy(tng_data->last_program_name, new_name, len);
10790 return(TNG_SUCCESS);
10793 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10794 (const tng_trajectory_t tng_data,
10795 char *name, const int max_len)
10797 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10798 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10800 strncpy(name, tng_data->first_user_name, max_len - 1);
10801 name[max_len - 1] = 0;
10803 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10805 return(TNG_FAILURE);
10807 return(TNG_SUCCESS);
10810 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10811 (tng_trajectory_t tng_data,
10812 const char *new_name)
10816 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10817 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10819 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10821 /* If the currently stored string length is not enough to store the new
10822 * string it is freed and reallocated. */
10823 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10825 free(tng_data->first_user_name);
10826 tng_data->first_user_name = 0;
10828 if(!tng_data->first_user_name)
10830 tng_data->first_user_name = malloc(len);
10831 if(!tng_data->first_user_name)
10833 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10834 __FILE__, __LINE__);
10835 return(TNG_CRITICAL);
10839 strncpy(tng_data->first_user_name, new_name, len);
10841 return(TNG_SUCCESS);
10844 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10845 (const tng_trajectory_t tng_data,
10846 char *name, const int max_len)
10848 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10849 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10851 strncpy(name, tng_data->last_user_name, max_len - 1);
10852 name[max_len - 1] = 0;
10854 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10856 return(TNG_FAILURE);
10858 return(TNG_SUCCESS);
10861 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10862 (tng_trajectory_t tng_data,
10863 const char *new_name)
10867 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10868 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10870 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10872 /* If the currently stored string length is not enough to store the new
10873 * string it is freed and reallocated. */
10874 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10876 free(tng_data->last_user_name);
10877 tng_data->last_user_name = 0;
10879 if(!tng_data->last_user_name)
10881 tng_data->last_user_name = malloc(len);
10882 if(!tng_data->last_user_name)
10884 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10885 __FILE__, __LINE__);
10886 return(TNG_CRITICAL);
10890 strncpy(tng_data->last_user_name, new_name, len);
10892 return(TNG_SUCCESS);
10895 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10896 (const tng_trajectory_t tng_data,
10897 char *name, const int max_len)
10899 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10900 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10902 strncpy(name, tng_data->first_computer_name, max_len - 1);
10903 name[max_len - 1] = 0;
10905 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10907 return(TNG_FAILURE);
10909 return(TNG_SUCCESS);
10912 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10913 (tng_trajectory_t tng_data,
10914 const char *new_name)
10918 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10919 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10921 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10923 /* If the currently stored string length is not enough to store the new
10924 * string it is freed and reallocated. */
10925 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10927 free(tng_data->first_computer_name);
10928 tng_data->first_computer_name = 0;
10930 if(!tng_data->first_computer_name)
10932 tng_data->first_computer_name = malloc(len);
10933 if(!tng_data->first_computer_name)
10935 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10936 __FILE__, __LINE__);
10937 return(TNG_CRITICAL);
10941 strncpy(tng_data->first_computer_name, new_name, len);
10943 return(TNG_SUCCESS);
10946 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10947 (const tng_trajectory_t tng_data,
10948 char *name, const int max_len)
10950 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10951 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10953 strncpy(name, tng_data->last_computer_name, max_len - 1);
10954 name[max_len - 1] = 0;
10956 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10958 return(TNG_FAILURE);
10960 return(TNG_SUCCESS);
10963 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10964 (tng_trajectory_t tng_data,
10965 const char *new_name)
10969 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10970 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10972 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10974 /* If the currently stored string length is not enough to store the new
10975 * string it is freed and reallocated. */
10976 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10979 free(tng_data->last_computer_name);
10980 tng_data->last_computer_name = 0;
10982 if(!tng_data->last_computer_name)
10984 tng_data->last_computer_name = malloc(len);
10985 if(!tng_data->last_computer_name)
10987 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10988 __FILE__, __LINE__);
10989 return(TNG_CRITICAL);
10993 strncpy(tng_data->last_computer_name, new_name, len);
10995 return(TNG_SUCCESS);
10998 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10999 (const tng_trajectory_t tng_data,
11000 char *signature, const int max_len)
11002 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11003 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11005 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
11006 signature[max_len - 1] = 0;
11008 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
11010 return(TNG_FAILURE);
11012 return(TNG_SUCCESS);
11015 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
11016 (tng_trajectory_t tng_data,
11017 const char *signature)
11021 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11022 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11024 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11026 /* If the currently stored string length is not enough to store the new
11027 * string it is freed and reallocated. */
11028 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
11031 free(tng_data->first_pgp_signature);
11032 tng_data->first_pgp_signature = 0;
11034 if(!tng_data->first_pgp_signature)
11036 tng_data->first_pgp_signature = malloc(len);
11037 if(!tng_data->first_pgp_signature)
11039 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11040 __FILE__, __LINE__);
11041 return(TNG_CRITICAL);
11045 strncpy(tng_data->first_pgp_signature, signature, len);
11047 return(TNG_SUCCESS);
11050 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11051 (const tng_trajectory_t tng_data,
11052 char *signature, const int max_len)
11054 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11055 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11057 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
11058 signature[max_len - 1] = 0;
11060 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
11062 return(TNG_FAILURE);
11064 return(TNG_SUCCESS);
11067 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11068 (tng_trajectory_t tng_data,
11069 const char *signature)
11073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11074 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11076 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11078 /* If the currently stored string length is not enough to store the new
11079 * string it is freed and reallocated. */
11080 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
11083 free(tng_data->last_pgp_signature);
11084 tng_data->last_pgp_signature = 0;
11086 if(!tng_data->last_pgp_signature)
11088 tng_data->last_pgp_signature = malloc(len);
11089 if(!tng_data->last_pgp_signature)
11091 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11092 __FILE__, __LINE__);
11093 return(TNG_CRITICAL);
11097 strncpy(tng_data->last_pgp_signature, signature, len);
11099 return(TNG_SUCCESS);
11102 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11103 (const tng_trajectory_t tng_data,
11104 char *name, const int max_len)
11106 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11107 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11109 strncpy(name, tng_data->forcefield_name, max_len - 1);
11110 name[max_len - 1] = 0;
11112 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11114 return(TNG_FAILURE);
11116 return(TNG_SUCCESS);
11119 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11120 (tng_trajectory_t tng_data,
11121 const char *new_name)
11125 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11126 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11128 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11130 /* If the currently stored string length is not enough to store the new
11131 * string it is freed and reallocated. */
11132 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11134 free(tng_data->forcefield_name);
11135 tng_data->forcefield_name = 0;
11137 if(!tng_data->forcefield_name)
11139 tng_data->forcefield_name = malloc(len);
11140 if(!tng_data->forcefield_name)
11142 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11143 __FILE__, __LINE__);
11144 return(TNG_CRITICAL);
11148 strncpy(tng_data->forcefield_name, new_name, len);
11150 return(TNG_SUCCESS);
11153 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11154 (const tng_trajectory_t tng_data,
11157 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11158 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11160 *len = tng_data->medium_stride_length;
11162 return(TNG_SUCCESS);
11165 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11166 (tng_trajectory_t tng_data,
11169 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11171 if(len >= tng_data->long_stride_length)
11173 return(TNG_FAILURE);
11175 tng_data->medium_stride_length = len;
11177 return(TNG_SUCCESS);
11180 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11181 (const tng_trajectory_t tng_data,
11184 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11185 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11187 *len = tng_data->long_stride_length;
11189 return(TNG_SUCCESS);
11192 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11193 (tng_trajectory_t tng_data,
11196 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11198 if(len <= tng_data->medium_stride_length)
11200 return(TNG_FAILURE);
11202 tng_data->long_stride_length = len;
11204 return(TNG_SUCCESS);
11207 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11208 (const tng_trajectory_t tng_data,
11211 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11212 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11214 *time = tng_data->time_per_frame;
11216 return(TNG_SUCCESS);
11219 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11220 (tng_trajectory_t tng_data,
11223 tng_trajectory_frame_set_t frame_set;
11225 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11226 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11228 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11230 return(TNG_SUCCESS);
11233 frame_set = &tng_data->current_trajectory_frame_set;
11235 /* If the current frame set is not finished write it to disk before
11236 changing time per frame. */
11237 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11239 frame_set->n_frames = frame_set->n_unwritten_frames;
11240 tng_frame_set_write(tng_data, TNG_USE_HASH);
11242 tng_data->time_per_frame = time;
11244 return(TNG_SUCCESS);
11247 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11248 (const tng_trajectory_t tng_data,
11251 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11252 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11254 *len = tng_data->input_file_len;
11256 return(TNG_SUCCESS);
11259 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11260 (const tng_trajectory_t tng_data,
11263 tng_gen_block_t block;
11264 tng_function_status stat;
11265 int64_t file_pos, last_file_pos, first_frame, n_frames;
11267 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11268 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11269 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11271 file_pos = ftello(tng_data->input_file);
11272 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11274 if(last_file_pos <= 0)
11276 return(TNG_FAILURE);
11279 tng_block_init(&block);
11280 fseeko(tng_data->input_file,
11283 /* Read block headers first to see that a frame set block is found. */
11284 stat = tng_block_header_read(tng_data, block);
11285 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11287 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11288 __FILE__, __LINE__);
11289 tng_block_destroy(&block);
11290 return(TNG_FAILURE);
11292 tng_block_destroy(&block);
11294 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11296 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11297 __FILE__, __LINE__);
11298 return(TNG_CRITICAL);
11300 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11302 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11303 __FILE__, __LINE__);
11304 return(TNG_CRITICAL);
11306 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11308 *n = first_frame + n_frames;
11310 return(TNG_SUCCESS);
11313 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11314 (const tng_trajectory_t tng_data,
11317 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11319 *precision = tng_data->compression_precision;
11321 return(TNG_SUCCESS);
11324 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11325 (tng_trajectory_t tng_data,
11326 const double precision)
11328 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11330 tng_data->compression_precision = precision;
11332 return(TNG_SUCCESS);
11335 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11336 (tng_trajectory_t tng_data,
11339 tng_molecule_t mol;
11343 tng_function_status stat;
11344 int64_t diff, n_mod, n_impl;
11346 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11348 diff = n - tng_data->n_particles;
11350 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11351 if(stat == TNG_SUCCESS)
11353 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11355 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11356 __FILE__, __LINE__);
11357 return(TNG_FAILURE);
11359 diff -= n_impl * mol->n_atoms;
11364 if(stat == TNG_SUCCESS)
11366 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11369 return(TNG_SUCCESS);
11373 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11374 fprintf(stderr, "particle count.\n");
11375 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11376 __FILE__, __LINE__);
11377 /* FIXME: Should we set the count of all other molecules to 0 and add
11378 * implicit molecules? */
11379 return(TNG_FAILURE);
11381 if(stat != TNG_SUCCESS)
11383 stat = tng_molecule_add(tng_data,
11384 "TNG_IMPLICIT_MOL",
11386 if(stat != TNG_SUCCESS)
11390 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11391 if(stat != TNG_SUCCESS)
11395 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11396 if(stat != TNG_SUCCESS)
11400 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11401 if(stat != TNG_SUCCESS)
11408 if(mol->n_atoms > 1)
11410 n_mod = diff % mol->n_atoms;
11413 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11414 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11415 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11416 __FILE__, __LINE__);
11417 return(TNG_FAILURE);
11419 diff /= mol->n_atoms;
11422 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11427 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11428 (const tng_trajectory_t tng_data,
11431 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11432 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11434 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11436 *n = tng_data->n_particles;
11440 *n = tng_data->current_trajectory_frame_set.n_particles;
11443 return(TNG_SUCCESS);
11446 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11447 (const tng_trajectory_t tng_data,
11450 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11451 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11453 *variable = tng_data->var_num_atoms_flag;
11455 return(TNG_SUCCESS);
11458 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11459 (const tng_trajectory_t tng_data,
11462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11463 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11465 *n = tng_data->n_molecules;
11467 return(TNG_SUCCESS);
11470 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11471 (const tng_trajectory_t tng_data,
11474 int64_t *cnt_list = 0, cnt = 0, i;
11476 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11477 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11479 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11483 return(TNG_FAILURE);
11486 for(i = 0; i < tng_data->n_molecules; i++)
11488 cnt += cnt_list[i];
11493 return(TNG_SUCCESS);
11496 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11497 (const tng_trajectory_t tng_data,
11498 int64_t **mol_cnt_list)
11500 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11502 if(tng_data->var_num_atoms_flag)
11504 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11509 *mol_cnt_list = tng_data->molecule_cnt_list;
11511 if(*mol_cnt_list == 0)
11513 return(TNG_FAILURE);
11515 return(TNG_SUCCESS);
11518 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11519 (const tng_trajectory_t tng_data,
11522 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11523 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11525 *exp = tng_data->distance_unit_exponential;
11527 return(TNG_SUCCESS);
11530 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11531 (const tng_trajectory_t tng_data,
11534 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11536 tng_data->distance_unit_exponential = exp;
11538 return(TNG_SUCCESS);
11541 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11542 (const tng_trajectory_t tng_data,
11545 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11546 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11548 *n = tng_data->frame_set_n_frames;
11550 return(TNG_SUCCESS);
11553 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11554 (const tng_trajectory_t tng_data,
11557 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11559 tng_data->frame_set_n_frames = n;
11561 return(TNG_SUCCESS);
11564 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11565 (const tng_trajectory_t tng_data,
11568 int64_t long_stride_length, medium_stride_length;
11569 int64_t file_pos, orig_frame_set_file_pos;
11570 tng_trajectory_frame_set_t frame_set;
11571 struct tng_trajectory_frame_set orig_frame_set;
11572 tng_gen_block_t block;
11573 tng_function_status stat;
11576 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11577 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11579 orig_frame_set = tng_data->current_trajectory_frame_set;
11581 frame_set = &tng_data->current_trajectory_frame_set;
11583 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11584 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11588 *n = tng_data->n_trajectory_frame_sets = cnt;
11589 return(TNG_SUCCESS);
11592 tng_block_init(&block);
11593 fseeko(tng_data->input_file,
11596 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11597 /* Read block headers first to see what block is found. */
11598 stat = tng_block_header_read(tng_data, block);
11599 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11601 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11602 __FILE__, __LINE__);
11603 tng_block_destroy(&block);
11604 return(TNG_CRITICAL);
11607 if(tng_block_read_next(tng_data, block,
11608 TNG_SKIP_HASH) != TNG_SUCCESS)
11610 tng_block_destroy(&block);
11611 return(TNG_CRITICAL);
11616 long_stride_length = tng_data->long_stride_length;
11617 medium_stride_length = tng_data->medium_stride_length;
11619 /* Take long steps forward until a long step forward would be too long or
11620 * the last frame set is found */
11621 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11622 while(file_pos > 0)
11626 cnt += long_stride_length;
11627 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11628 /* Read block headers first to see what block is found. */
11629 stat = tng_block_header_read(tng_data, block);
11630 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11632 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11633 file_pos, __FILE__, __LINE__);
11634 tng_block_destroy(&block);
11635 return(TNG_CRITICAL);
11638 if(tng_block_read_next(tng_data, block,
11639 TNG_SKIP_HASH) != TNG_SUCCESS)
11641 tng_block_destroy(&block);
11642 return(TNG_CRITICAL);
11645 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11648 /* Take medium steps forward until a medium step forward would be too long
11649 * or the last frame set is found */
11650 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11651 while(file_pos > 0)
11655 cnt += medium_stride_length;
11656 fseeko(tng_data->input_file,
11659 /* Read block headers first to see what block is found. */
11660 stat = tng_block_header_read(tng_data, block);
11661 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11663 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11664 file_pos, __FILE__, __LINE__);
11665 tng_block_destroy(&block);
11666 return(TNG_CRITICAL);
11669 if(tng_block_read_next(tng_data, block,
11670 TNG_SKIP_HASH) != TNG_SUCCESS)
11672 tng_block_destroy(&block);
11673 return(TNG_CRITICAL);
11676 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11679 /* Take one step forward until the last frame set is found */
11680 file_pos = frame_set->next_frame_set_file_pos;
11681 while(file_pos > 0)
11686 fseeko(tng_data->input_file,
11689 /* Read block headers first to see what block is found. */
11690 stat = tng_block_header_read(tng_data, block);
11691 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11693 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11694 file_pos, __FILE__, __LINE__);
11695 tng_block_destroy(&block);
11696 return(TNG_CRITICAL);
11699 if(tng_block_read_next(tng_data, block,
11700 TNG_SKIP_HASH) != TNG_SUCCESS)
11702 tng_block_destroy(&block);
11703 return(TNG_CRITICAL);
11706 file_pos = frame_set->next_frame_set_file_pos;
11709 tng_block_destroy(&block);
11711 *n = tng_data->n_trajectory_frame_sets = cnt;
11713 *frame_set = orig_frame_set;
11714 /* The mapping block in the original frame set has been freed when reading
11715 * other frame sets. */
11716 frame_set->mappings = 0;
11717 frame_set->n_mapping_blocks = 0;
11719 fseeko(tng_data->input_file,
11720 tng_data->first_trajectory_frame_set_input_file_pos,
11723 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11725 return(TNG_SUCCESS);
11728 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11729 (const tng_trajectory_t tng_data,
11730 tng_trajectory_frame_set_t *frame_set_p)
11732 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11734 *frame_set_p = &tng_data->current_trajectory_frame_set;
11736 return(TNG_SUCCESS);
11739 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11740 (tng_trajectory_t tng_data,
11743 int64_t long_stride_length, medium_stride_length;
11744 int64_t file_pos, curr_nr = 0, n_frame_sets;
11745 tng_trajectory_frame_set_t frame_set;
11746 tng_gen_block_t block;
11747 tng_function_status stat;
11749 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11750 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11752 frame_set = &tng_data->current_trajectory_frame_set;
11754 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11756 if(stat != TNG_SUCCESS)
11761 if(nr >= n_frame_sets)
11763 return(TNG_FAILURE);
11766 long_stride_length = tng_data->long_stride_length;
11767 medium_stride_length = tng_data->medium_stride_length;
11769 /* FIXME: The frame set number of the current frame set is not stored */
11771 if(nr < n_frame_sets - 1 - nr)
11773 /* Start from the beginning */
11774 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11778 /* Start from the end */
11779 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11780 curr_nr = n_frame_sets - 1;
11784 return(TNG_FAILURE);
11787 tng_block_init(&block);
11788 fseeko(tng_data->input_file,
11791 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11792 /* Read block headers first to see what block is found. */
11793 stat = tng_block_header_read(tng_data, block);
11794 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11796 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11797 __FILE__, __LINE__);
11798 tng_block_destroy(&block);
11799 return(TNG_CRITICAL);
11802 if(tng_block_read_next(tng_data, block,
11803 TNG_SKIP_HASH) != TNG_SUCCESS)
11805 tng_block_destroy(&block);
11806 return(TNG_CRITICAL);
11811 tng_block_destroy(&block);
11812 return(TNG_SUCCESS);
11815 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11817 /* Take long steps forward until a long step forward would be too long or
11818 * the right frame set is found */
11819 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11821 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11824 curr_nr += long_stride_length;
11825 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11826 /* Read block headers first to see what block is found. */
11827 stat = tng_block_header_read(tng_data, block);
11828 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11830 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11831 file_pos, __FILE__, __LINE__);
11832 tng_block_destroy(&block);
11833 return(TNG_CRITICAL);
11836 if(tng_block_read_next(tng_data, block,
11837 TNG_SKIP_HASH) != TNG_SUCCESS)
11839 tng_block_destroy(&block);
11840 return(TNG_CRITICAL);
11844 tng_block_destroy(&block);
11845 return(TNG_SUCCESS);
11850 /* Take medium steps forward until a medium step forward would be too long
11851 * or the right frame set is found */
11852 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11854 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11857 curr_nr += medium_stride_length;
11858 fseeko(tng_data->input_file,
11861 /* Read block headers first to see what block is found. */
11862 stat = tng_block_header_read(tng_data, block);
11863 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11865 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11866 file_pos, __FILE__, __LINE__);
11867 tng_block_destroy(&block);
11868 return(TNG_CRITICAL);
11871 if(tng_block_read_next(tng_data, block,
11872 TNG_SKIP_HASH) != TNG_SUCCESS)
11874 tng_block_destroy(&block);
11875 return(TNG_CRITICAL);
11879 tng_block_destroy(&block);
11880 return(TNG_SUCCESS);
11885 /* Take one step forward until the right frame set is found */
11886 while(file_pos > 0 && curr_nr < nr)
11888 file_pos = frame_set->next_frame_set_file_pos;
11893 fseeko(tng_data->input_file,
11896 /* Read block headers first to see what block is found. */
11897 stat = tng_block_header_read(tng_data, block);
11898 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11900 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11901 file_pos, __FILE__, __LINE__);
11902 tng_block_destroy(&block);
11903 return(TNG_CRITICAL);
11906 if(tng_block_read_next(tng_data, block,
11907 TNG_SKIP_HASH) != TNG_SUCCESS)
11909 tng_block_destroy(&block);
11910 return(TNG_CRITICAL);
11914 tng_block_destroy(&block);
11915 return(TNG_SUCCESS);
11920 /* Take long steps backward until a long step backward would be too long
11921 * or the right frame set is found */
11922 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11924 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11927 curr_nr -= long_stride_length;
11928 fseeko(tng_data->input_file,
11931 /* Read block headers first to see what block is found. */
11932 stat = tng_block_header_read(tng_data, block);
11933 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11935 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11936 file_pos, __FILE__, __LINE__);
11937 tng_block_destroy(&block);
11938 return(TNG_CRITICAL);
11941 if(tng_block_read_next(tng_data, block,
11942 TNG_SKIP_HASH) != TNG_SUCCESS)
11944 tng_block_destroy(&block);
11945 return(TNG_CRITICAL);
11949 tng_block_destroy(&block);
11950 return(TNG_SUCCESS);
11955 /* Take medium steps backward until a medium step backward would be too long
11956 * or the right frame set is found */
11957 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11959 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11962 curr_nr -= medium_stride_length;
11963 fseeko(tng_data->input_file,
11966 /* Read block headers first to see what block is found. */
11967 stat = tng_block_header_read(tng_data, block);
11968 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11970 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11971 file_pos, __FILE__, __LINE__);
11972 tng_block_destroy(&block);
11973 return(TNG_CRITICAL);
11976 if(tng_block_read_next(tng_data, block,
11977 TNG_SKIP_HASH) != TNG_SUCCESS)
11979 tng_block_destroy(&block);
11980 return(TNG_CRITICAL);
11984 tng_block_destroy(&block);
11985 return(TNG_SUCCESS);
11990 /* Take one step backward until the right frame set is found */
11991 while(file_pos > 0 && curr_nr > nr)
11993 file_pos = frame_set->prev_frame_set_file_pos;
11997 fseeko(tng_data->input_file,
12000 /* Read block headers first to see what block is found. */
12001 stat = tng_block_header_read(tng_data, block);
12002 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12004 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12005 file_pos, __FILE__, __LINE__);
12006 tng_block_destroy(&block);
12007 return(TNG_CRITICAL);
12010 if(tng_block_read_next(tng_data, block,
12011 TNG_SKIP_HASH) != TNG_SUCCESS)
12013 tng_block_destroy(&block);
12014 return(TNG_CRITICAL);
12018 tng_block_destroy(&block);
12019 return(TNG_SUCCESS);
12024 /* If for some reason the current frame set is not yet found,
12025 * take one step forward until the right frame set is found */
12026 while(file_pos > 0 && curr_nr < nr)
12028 file_pos = frame_set->next_frame_set_file_pos;
12032 fseeko(tng_data->input_file,
12035 /* Read block headers first to see what block is found. */
12036 stat = tng_block_header_read(tng_data, block);
12037 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12039 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12040 file_pos, __FILE__, __LINE__);
12041 tng_block_destroy(&block);
12042 return(TNG_CRITICAL);
12045 if(tng_block_read_next(tng_data, block,
12046 TNG_SKIP_HASH) != TNG_SUCCESS)
12048 tng_block_destroy(&block);
12049 return(TNG_CRITICAL);
12053 tng_block_destroy(&block);
12054 return(TNG_SUCCESS);
12059 tng_block_destroy(&block);
12060 return(TNG_FAILURE);
12063 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12064 (tng_trajectory_t tng_data,
12065 const int64_t frame)
12067 int64_t first_frame, last_frame, n_frames_per_frame_set;
12068 int64_t long_stride_length, medium_stride_length;
12069 int64_t file_pos, temp_frame, n_frames;
12070 tng_trajectory_frame_set_t frame_set;
12071 tng_gen_block_t block;
12072 tng_function_status stat;
12074 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12075 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
12077 frame_set = &tng_data->current_trajectory_frame_set;
12079 tng_block_init(&block);
12081 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
12083 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12084 fseeko(tng_data->input_file,
12087 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12088 /* Read block headers first to see what block is found. */
12089 stat = tng_block_header_read(tng_data, block);
12090 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12092 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12093 file_pos, __FILE__, __LINE__);
12094 tng_block_destroy(&block);
12095 return(TNG_CRITICAL);
12098 if(tng_block_read_next(tng_data, block,
12099 TNG_SKIP_HASH) != TNG_SUCCESS)
12101 tng_block_destroy(&block);
12102 return(TNG_CRITICAL);
12106 first_frame = tng_max_i64(frame_set->first_frame, 0);
12107 last_frame = first_frame + frame_set->n_frames - 1;
12108 /* Is this the right frame set? */
12109 if(first_frame <= frame && frame <= last_frame)
12111 tng_block_destroy(&block);
12112 return(TNG_SUCCESS);
12115 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12116 long_stride_length = tng_data->long_stride_length;
12117 medium_stride_length = tng_data->medium_stride_length;
12119 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12122 if(temp_frame - first_frame > n_frames_per_frame_set)
12124 n_frames_per_frame_set = temp_frame - first_frame;
12128 tng_num_frames_get(tng_data, &n_frames);
12130 if(frame >= n_frames)
12132 tng_block_destroy(&block);
12133 return(TNG_FAILURE);
12136 if(first_frame - frame >= frame ||
12137 frame - last_frame >
12138 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12140 /* Start from the beginning */
12141 if(first_frame - frame >= frame)
12143 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12147 tng_block_destroy(&block);
12148 return(TNG_FAILURE);
12151 /* Start from the end */
12152 else if(frame - first_frame > (n_frames - 1) - frame)
12154 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12156 /* If the last frame set position is not set start from the current
12157 * frame set, since it will be closer than the first frame set. */
12159 /* Start from current */
12162 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12167 fseeko(tng_data->input_file,
12170 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12171 /* Read block headers first to see what block is found. */
12172 stat = tng_block_header_read(tng_data, block);
12173 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12175 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12176 file_pos, __FILE__, __LINE__);
12177 tng_block_destroy(&block);
12178 return(TNG_CRITICAL);
12181 if(tng_block_read_next(tng_data, block,
12182 TNG_SKIP_HASH) != TNG_SUCCESS)
12184 tng_block_destroy(&block);
12185 return(TNG_CRITICAL);
12190 first_frame = tng_max_i64(frame_set->first_frame, 0);
12191 last_frame = first_frame + frame_set->n_frames - 1;
12193 if(frame >= first_frame && frame <= last_frame)
12195 tng_block_destroy(&block);
12196 return(TNG_SUCCESS);
12199 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12201 /* Take long steps forward until a long step forward would be too long or
12202 * the right frame set is found */
12203 while(file_pos > 0 && first_frame + long_stride_length *
12204 n_frames_per_frame_set <= frame)
12206 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12209 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12210 /* Read block headers first to see what block is found. */
12211 stat = tng_block_header_read(tng_data, block);
12212 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12214 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12215 file_pos, __FILE__, __LINE__);
12216 tng_block_destroy(&block);
12217 return(TNG_CRITICAL);
12220 if(tng_block_read_next(tng_data, block,
12221 TNG_SKIP_HASH) != TNG_SUCCESS)
12223 tng_block_destroy(&block);
12224 return(TNG_CRITICAL);
12227 first_frame = tng_max_i64(frame_set->first_frame, 0);
12228 last_frame = first_frame + frame_set->n_frames - 1;
12229 if(frame >= first_frame && frame <= last_frame)
12231 tng_block_destroy(&block);
12232 return(TNG_SUCCESS);
12236 /* Take medium steps forward until a medium step forward would be too long
12237 * or the right frame set is found */
12238 while(file_pos > 0 && first_frame + medium_stride_length *
12239 n_frames_per_frame_set <= frame)
12241 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12244 fseeko(tng_data->input_file,
12247 /* Read block headers first to see what block is found. */
12248 stat = tng_block_header_read(tng_data, block);
12249 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12251 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12252 file_pos, __FILE__, __LINE__);
12253 tng_block_destroy(&block);
12254 return(TNG_CRITICAL);
12257 if(tng_block_read_next(tng_data, block,
12258 TNG_SKIP_HASH) != TNG_SUCCESS)
12260 tng_block_destroy(&block);
12261 return(TNG_CRITICAL);
12264 first_frame = tng_max_i64(frame_set->first_frame, 0);
12265 last_frame = first_frame + frame_set->n_frames - 1;
12266 if(frame >= first_frame && frame <= last_frame)
12268 tng_block_destroy(&block);
12269 return(TNG_SUCCESS);
12273 /* Take one step forward until the right frame set is found */
12274 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12276 file_pos = frame_set->next_frame_set_file_pos;
12279 fseeko(tng_data->input_file,
12282 /* Read block headers first to see what block is found. */
12283 stat = tng_block_header_read(tng_data, block);
12284 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12286 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12287 file_pos, __FILE__, __LINE__);
12288 tng_block_destroy(&block);
12289 return(TNG_CRITICAL);
12292 if(tng_block_read_next(tng_data, block,
12293 TNG_SKIP_HASH) != TNG_SUCCESS)
12295 tng_block_destroy(&block);
12296 return(TNG_CRITICAL);
12299 first_frame = tng_max_i64(frame_set->first_frame, 0);
12300 last_frame = first_frame + frame_set->n_frames - 1;
12301 if(frame >= first_frame && frame <= last_frame)
12303 tng_block_destroy(&block);
12304 return(TNG_SUCCESS);
12308 /* Take long steps backward until a long step backward would be too long
12309 * or the right frame set is found */
12310 while(file_pos > 0 && first_frame - long_stride_length *
12311 n_frames_per_frame_set >= frame)
12313 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12316 fseeko(tng_data->input_file,
12319 /* Read block headers first to see what block is found. */
12320 stat = tng_block_header_read(tng_data, block);
12321 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12323 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12324 file_pos, __FILE__, __LINE__);
12325 tng_block_destroy(&block);
12326 return(TNG_CRITICAL);
12329 if(tng_block_read_next(tng_data, block,
12330 TNG_SKIP_HASH) != TNG_SUCCESS)
12332 tng_block_destroy(&block);
12333 return(TNG_CRITICAL);
12336 first_frame = tng_max_i64(frame_set->first_frame, 0);
12337 last_frame = first_frame + frame_set->n_frames - 1;
12338 if(frame >= first_frame && frame <= last_frame)
12340 tng_block_destroy(&block);
12341 return(TNG_SUCCESS);
12345 /* Take medium steps backward until a medium step backward would be too long
12346 * or the right frame set is found */
12347 while(file_pos > 0 && first_frame - medium_stride_length *
12348 n_frames_per_frame_set >= frame)
12350 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12353 fseeko(tng_data->input_file,
12356 /* Read block headers first to see what block is found. */
12357 stat = tng_block_header_read(tng_data, block);
12358 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12360 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12361 file_pos, __FILE__, __LINE__);
12362 tng_block_destroy(&block);
12363 return(TNG_CRITICAL);
12366 if(tng_block_read_next(tng_data, block,
12367 TNG_SKIP_HASH) != TNG_SUCCESS)
12369 tng_block_destroy(&block);
12370 return(TNG_CRITICAL);
12373 first_frame = tng_max_i64(frame_set->first_frame, 0);
12374 last_frame = first_frame + frame_set->n_frames - 1;
12375 if(frame >= first_frame && frame <= last_frame)
12377 tng_block_destroy(&block);
12378 return(TNG_SUCCESS);
12382 /* Take one step backward until the right frame set is found */
12383 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12385 file_pos = frame_set->prev_frame_set_file_pos;
12388 fseeko(tng_data->input_file,
12391 /* Read block headers first to see what block is found. */
12392 stat = tng_block_header_read(tng_data, block);
12393 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12395 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12396 file_pos, __FILE__, __LINE__);
12397 tng_block_destroy(&block);
12398 return(TNG_CRITICAL);
12401 if(tng_block_read_next(tng_data, block,
12402 TNG_SKIP_HASH) != TNG_SUCCESS)
12404 tng_block_destroy(&block);
12405 return(TNG_CRITICAL);
12408 first_frame = tng_max_i64(frame_set->first_frame, 0);
12409 last_frame = first_frame + frame_set->n_frames - 1;
12410 if(frame >= first_frame && frame <= last_frame)
12412 tng_block_destroy(&block);
12413 return(TNG_SUCCESS);
12417 /* If for some reason the current frame set is not yet found,
12418 * take one step forward until the right frame set is found */
12419 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12421 file_pos = frame_set->next_frame_set_file_pos;
12424 fseeko(tng_data->input_file,
12427 /* Read block headers first to see what block is found. */
12428 stat = tng_block_header_read(tng_data, block);
12429 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12431 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12432 file_pos, __FILE__, __LINE__);
12433 tng_block_destroy(&block);
12434 return(TNG_CRITICAL);
12437 if(tng_block_read_next(tng_data, block,
12438 TNG_SKIP_HASH) != TNG_SUCCESS)
12440 tng_block_destroy(&block);
12441 return(TNG_CRITICAL);
12444 first_frame = tng_max_i64(frame_set->first_frame, 0);
12445 last_frame = first_frame + frame_set->n_frames - 1;
12446 if(frame >= first_frame && frame <= last_frame)
12448 tng_block_destroy(&block);
12449 return(TNG_SUCCESS);
12453 tng_block_destroy(&block);
12454 return(TNG_FAILURE);
12457 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12458 (const tng_trajectory_t tng_data,
12459 const tng_trajectory_frame_set_t frame_set,
12464 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12465 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12467 *pos = frame_set->next_frame_set_file_pos;
12469 return(TNG_SUCCESS);
12472 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12473 (const tng_trajectory_t tng_data,
12474 const tng_trajectory_frame_set_t frame_set,
12479 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12480 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12482 *pos = frame_set->prev_frame_set_file_pos;
12484 return(TNG_SUCCESS);
12487 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12488 (const tng_trajectory_t tng_data,
12489 const tng_trajectory_frame_set_t frame_set,
12490 int64_t *first_frame,
12491 int64_t *last_frame)
12495 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12496 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12497 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12499 *first_frame = frame_set->first_frame;
12500 *last_frame = *first_frame + frame_set->n_frames - 1;
12502 return(TNG_SUCCESS);
12505 /** Translate from the particle numbering used in a frame set to the real
12506 * particle numbering - used in the molecule description.
12507 * @param frame_set is the frame_set containing the mappings to use.
12508 * @param local is the index number of the atom in this frame set
12509 * @param real is set to the index of the atom in the molecular system.
12510 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12513 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12514 (const tng_trajectory_frame_set_t frame_set,
12515 const int64_t local,
12518 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12519 tng_particle_mapping_t mapping;
12523 return(TNG_SUCCESS);
12525 for(i = 0; i < n_blocks; i++)
12527 mapping = &frame_set->mappings[i];
12528 first = mapping->num_first_particle;
12529 if(local < first ||
12530 local >= first + mapping->n_particles)
12534 *real = mapping->real_particle_numbers[local-first];
12535 return(TNG_SUCCESS);
12538 return(TNG_FAILURE);
12541 /** Translate from the real particle numbering to the particle numbering
12542 * used in a frame set.
12543 * @param frame_set is the frame_set containing the mappings to use.
12544 * @param real is the index number of the atom in the molecular system.
12545 * @param local is set to the index of the atom in this frame set.
12546 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12549 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12550 (const tng_trajectory_frame_set_t frame_set,
12551 const int64_t real,
12554 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12555 tng_particle_mapping_t mapping;
12559 return(TNG_SUCCESS);
12561 for(i = 0; i < n_blocks; i++)
12563 mapping = &frame_set->mappings[i];
12564 for(j = mapping->n_particles; j--;)
12566 if(mapping->real_particle_numbers[j] == real)
12569 return(TNG_SUCCESS);
12573 return(TNG_FAILURE);
12577 static tng_function_status tng_file_headers_len_get
12578 (tng_trajectory_t tng_data,
12582 tng_gen_block_t block;
12584 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12586 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12588 return(TNG_CRITICAL);
12593 orig_pos = ftello(tng_data->input_file);
12595 if(!tng_data->input_file_len)
12597 fseeko(tng_data->input_file, 0, SEEK_END);
12598 tng_data->input_file_len = ftello(tng_data->input_file);
12600 fseeko(tng_data->input_file, 0, SEEK_SET);
12602 tng_block_init(&block);
12603 /* Read through the headers of non-trajectory blocks (they come before the
12604 * trajectory blocks in the file) */
12605 while (*len < tng_data->input_file_len &&
12606 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12608 block->id != TNG_TRAJECTORY_FRAME_SET)
12610 *len += block->header_contents_size + block->block_contents_size;
12611 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12614 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
12616 tng_block_destroy(&block);
12618 return(TNG_SUCCESS);
12621 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12622 (tng_trajectory_t tng_data,
12623 const char hash_mode)
12625 int64_t prev_pos = 0;
12626 tng_gen_block_t block;
12628 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12630 tng_data->n_trajectory_frame_sets = 0;
12632 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12634 return(TNG_CRITICAL);
12637 if(!tng_data->input_file_len)
12639 fseeko(tng_data->input_file, 0, SEEK_END);
12640 tng_data->input_file_len = ftello(tng_data->input_file);
12642 fseeko(tng_data->input_file, 0, SEEK_SET);
12644 tng_block_init(&block);
12645 /* Non trajectory blocks (they come before the trajectory
12646 * blocks in the file) */
12647 while (prev_pos < tng_data->input_file_len &&
12648 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12650 block->id != TNG_TRAJECTORY_FRAME_SET)
12652 tng_block_read_next(tng_data, block, hash_mode);
12653 prev_pos = ftello(tng_data->input_file);
12656 /* Go back if a trajectory block was encountered */
12657 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12659 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
12662 tng_block_destroy(&block);
12664 return(TNG_SUCCESS);
12667 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12668 (tng_trajectory_t tng_data,
12669 const char hash_mode)
12672 int64_t len, orig_len, tot_len = 0, data_start_pos;
12673 tng_function_status stat;
12674 tng_gen_block_t block;
12676 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12678 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12680 return(TNG_CRITICAL);
12683 if(tng_data->n_trajectory_frame_sets > 0)
12685 stat = tng_file_headers_len_get(tng_data, &orig_len);
12686 if(stat != TNG_SUCCESS)
12691 tng_block_init(&block);
12692 block->name = malloc(TNG_MAX_STR_LEN);
12695 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12696 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12697 tng_block_destroy(&block);
12698 return(TNG_CRITICAL);
12700 strcpy(block->name, "GENERAL INFO");
12701 tng_block_header_len_calculate(tng_data, block, &len);
12703 tng_general_info_block_len_calculate(tng_data, &len);
12705 strcpy(block->name, "MOLECULES");
12706 tng_block_header_len_calculate(tng_data, block, &len);
12708 tng_molecules_block_len_calculate(tng_data, &len);
12711 for(i = 0; i < tng_data->n_data_blocks; i++)
12713 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12714 tng_block_header_len_calculate(tng_data, block, &len);
12716 tng_data_block_len_calculate(tng_data,
12717 (tng_particle_data_t)&tng_data->non_tr_data[i],
12718 TNG_FALSE, 1, 1, 1, 0,
12719 1, 0, &data_start_pos,
12723 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12725 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12726 tng_block_header_len_calculate(tng_data, block, &len);
12728 tng_data_block_len_calculate(tng_data,
12729 &tng_data->non_tr_particle_data[i],
12730 TNG_TRUE, 1, 1, 1, 0,
12731 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12736 tng_block_destroy(&block);
12738 if(tot_len > orig_len)
12740 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12743 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12746 /* TODO: If there is already frame set data written to this file (e.g. when
12747 * appending to an already existing file we might need to move frame sets to
12748 * the end of the file. */
12750 if(tng_general_info_block_write(tng_data, hash_mode)
12753 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12754 tng_data->input_file_path, __FILE__, __LINE__);
12755 return(TNG_CRITICAL);
12758 if(tng_molecules_block_write(tng_data, hash_mode)
12761 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12762 tng_data->input_file_path, __FILE__, __LINE__);
12763 return(TNG_CRITICAL);
12766 /* FIXME: Currently writing non-trajectory data blocks here.
12767 * Should perhaps be moved. */
12768 tng_block_init(&block);
12769 for(i = 0; i < tng_data->n_data_blocks; i++)
12771 block->id = tng_data->non_tr_data[i].block_id;
12772 tng_data_block_write(tng_data, block,
12776 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12778 block->id = tng_data->non_tr_particle_data[i].block_id;
12779 tng_particle_data_block_write(tng_data, block,
12783 tng_block_destroy(&block);
12785 return(TNG_SUCCESS);
12788 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12789 tng_gen_block_t block,
12790 const char hash_mode)
12792 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12793 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12797 case TNG_TRAJECTORY_FRAME_SET:
12798 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12799 case TNG_PARTICLE_MAPPING:
12800 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12801 case TNG_GENERAL_INFO:
12802 return(tng_general_info_block_read(tng_data, block, hash_mode));
12803 case TNG_MOLECULES:
12804 return(tng_molecules_block_read(tng_data, block, hash_mode));
12806 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12808 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12812 /* Skip to the next block */
12813 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12814 return(TNG_FAILURE);
12819 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12820 (tng_trajectory_t tng_data,
12821 const char hash_mode)
12824 tng_gen_block_t block;
12825 tng_function_status stat;
12827 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12829 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12831 return(TNG_CRITICAL);
12834 file_pos = ftello(tng_data->input_file);
12836 tng_block_init(&block);
12838 if(!tng_data->input_file_len)
12840 fseeko(tng_data->input_file, 0, SEEK_END);
12841 tng_data->input_file_len = ftello(tng_data->input_file);
12842 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12845 /* Read block headers first to see what block is found. */
12846 stat = tng_block_header_read(tng_data, block);
12847 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12850 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12851 file_pos, __FILE__, __LINE__);
12852 tng_block_destroy(&block);
12853 return(TNG_CRITICAL);
12856 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12858 if(tng_block_read_next(tng_data, block,
12859 hash_mode) == TNG_SUCCESS)
12861 tng_data->n_trajectory_frame_sets++;
12862 file_pos = ftello(tng_data->input_file);
12863 /* Read all blocks until next frame set block */
12864 stat = tng_block_header_read(tng_data, block);
12865 while(file_pos < tng_data->input_file_len &&
12866 stat != TNG_CRITICAL &&
12867 block->id != TNG_TRAJECTORY_FRAME_SET &&
12870 stat = tng_block_read_next(tng_data, block,
12872 if(stat != TNG_CRITICAL)
12874 file_pos = ftello(tng_data->input_file);
12875 if(file_pos < tng_data->input_file_len)
12877 stat = tng_block_header_read(tng_data, block);
12881 if(stat == TNG_CRITICAL)
12883 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12884 file_pos, __FILE__, __LINE__);
12885 tng_block_destroy(&block);
12889 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12891 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12895 tng_block_destroy(&block);
12897 return(TNG_SUCCESS);
12901 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12902 (tng_trajectory_t tng_data,
12903 const char hash_mode,
12904 const int64_t block_id)
12907 tng_gen_block_t block;
12908 tng_function_status stat;
12909 int found_flag = 1;
12911 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12913 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12915 return(TNG_CRITICAL);
12918 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12922 /* No current frame set. This means that the first frame set must be
12925 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12930 fseeko(tng_data->input_file,
12936 return(TNG_FAILURE);
12939 tng_block_init(&block);
12941 if(!tng_data->input_file_len)
12943 fseeko(tng_data->input_file, 0, SEEK_END);
12944 tng_data->input_file_len = ftello(tng_data->input_file);
12945 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12948 /* Read block headers first to see what block is found. */
12949 stat = tng_block_header_read(tng_data, block);
12950 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12952 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12953 file_pos, __FILE__, __LINE__);
12954 tng_block_destroy(&block);
12955 return(TNG_CRITICAL);
12957 /* If the current frame set had already been read skip its block contents */
12960 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12962 /* Otherwiese read the frame set block */
12965 stat = tng_block_read_next(tng_data, block,
12967 if(stat != TNG_SUCCESS)
12969 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12970 tng_block_destroy(&block);
12974 file_pos = ftello(tng_data->input_file);
12978 /* Read only blocks of the requested ID
12979 * until next frame set block */
12980 stat = tng_block_header_read(tng_data, block);
12981 while(file_pos < tng_data->input_file_len &&
12982 stat != TNG_CRITICAL &&
12983 block->id != TNG_TRAJECTORY_FRAME_SET &&
12986 if(block->id == block_id)
12988 stat = tng_block_read_next(tng_data, block,
12990 if(stat != TNG_CRITICAL)
12992 file_pos = ftello(tng_data->input_file);
12994 if(file_pos < tng_data->input_file_len)
12996 stat = tng_block_header_read(tng_data, block);
13002 file_pos += (block->block_contents_size + block->header_contents_size);
13003 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13004 if(file_pos < tng_data->input_file_len)
13006 stat = tng_block_header_read(tng_data, block);
13010 if(stat == TNG_CRITICAL)
13012 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13013 file_pos, __FILE__, __LINE__);
13014 tng_block_destroy(&block);
13018 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13020 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13023 tng_block_destroy(&block);
13027 return(TNG_SUCCESS);
13031 return(TNG_FAILURE);
13035 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
13036 (tng_trajectory_t tng_data,
13037 const char hash_mode)
13041 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13043 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13045 return(TNG_CRITICAL);
13048 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13050 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13052 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13057 fseeko(tng_data->input_file,
13063 return(TNG_FAILURE);
13066 return(tng_frame_set_read(tng_data, hash_mode));
13069 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13070 (tng_trajectory_t tng_data,
13071 const char hash_mode,
13072 const int64_t block_id)
13075 tng_gen_block_t block;
13076 tng_function_status stat;
13078 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13080 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13082 return(TNG_CRITICAL);
13085 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13087 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13089 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13094 fseeko(tng_data->input_file,
13100 return(TNG_FAILURE);
13103 tng_block_init(&block);
13105 if(!tng_data->input_file_len)
13107 fseeko(tng_data->input_file, 0, SEEK_END);
13108 tng_data->input_file_len = ftello(tng_data->input_file);
13109 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13112 /* Read block headers first to see what block is found. */
13113 stat = tng_block_header_read(tng_data, block);
13114 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13116 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13117 file_pos, __FILE__, __LINE__);
13118 tng_block_destroy(&block);
13119 return(TNG_CRITICAL);
13122 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13124 if(tng_block_read_next(tng_data, block,
13125 hash_mode) == TNG_SUCCESS)
13127 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13130 tng_block_destroy(&block);
13135 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13136 const char hash_mode)
13139 tng_gen_block_t block;
13140 tng_trajectory_frame_set_t frame_set;
13141 tng_function_status stat;
13143 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13145 frame_set = &tng_data->current_trajectory_frame_set;
13147 if(frame_set->n_written_frames == frame_set->n_frames)
13149 return(TNG_SUCCESS);
13152 tng_data->current_trajectory_frame_set_output_file_pos =
13153 ftello(tng_data->output_file);
13154 tng_data->last_trajectory_frame_set_output_file_pos =
13155 tng_data->current_trajectory_frame_set_output_file_pos;
13157 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13159 return(TNG_FAILURE);
13162 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13164 tng_data->first_trajectory_frame_set_output_file_pos =
13165 tng_data->current_trajectory_frame_set_output_file_pos;
13168 tng_block_init(&block);
13170 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13172 tng_block_destroy(&block);
13173 return(TNG_FAILURE);
13176 /* Write non-particle data blocks */
13177 for(i = 0; i<frame_set->n_data_blocks; i++)
13179 block->id = frame_set->tr_data[i].block_id;
13180 tng_data_block_write(tng_data, block, i, hash_mode);
13182 /* Write the mapping blocks and particle data blocks*/
13183 if(frame_set->n_mapping_blocks)
13185 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13187 block->id = TNG_PARTICLE_MAPPING;
13188 if(frame_set->mappings[i].n_particles > 0)
13190 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13191 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13193 block->id = frame_set->tr_particle_data[j].block_id;
13194 tng_particle_data_block_write(tng_data, block,
13195 j, &frame_set->mappings[i],
13203 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13205 block->id = frame_set->tr_particle_data[i].block_id;
13206 tng_particle_data_block_write(tng_data, block,
13212 /* Update pointers in the general info block */
13213 stat = tng_header_pointers_update(tng_data, hash_mode);
13215 if(stat == TNG_SUCCESS)
13217 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13220 tng_block_destroy(&block);
13222 frame_set->n_unwritten_frames = 0;
13224 fflush(tng_data->output_file);
13229 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13230 (tng_trajectory_t tng_data,
13231 const char hash_mode)
13233 tng_trajectory_frame_set_t frame_set;
13235 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13237 frame_set = &tng_data->current_trajectory_frame_set;
13239 if(frame_set->n_unwritten_frames == 0)
13241 return(TNG_SUCCESS);
13243 frame_set->n_frames = frame_set->n_unwritten_frames;
13245 return(tng_frame_set_write(tng_data, hash_mode));
13248 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13249 (tng_trajectory_t tng_data,
13250 const int64_t first_frame,
13251 const int64_t n_frames)
13253 tng_gen_block_t block;
13254 tng_trajectory_frame_set_t frame_set;
13255 FILE *temp = tng_data->input_file;
13258 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13259 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13260 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13262 frame_set = &tng_data->current_trajectory_frame_set;
13264 curr_pos = ftello(tng_data->output_file);
13268 tng_file_headers_write(tng_data, TNG_USE_HASH);
13271 /* Set pointer to previous frame set to the one that was loaded
13273 * FIXME: This is a bit risky. If they are not added in order
13274 * it will be wrong. */
13275 if(tng_data->n_trajectory_frame_sets)
13277 frame_set->prev_frame_set_file_pos =
13278 tng_data->current_trajectory_frame_set_output_file_pos;
13281 tng_data->current_trajectory_frame_set_output_file_pos =
13282 ftello(tng_data->output_file);
13284 tng_data->n_trajectory_frame_sets++;
13286 /* Set the medium range pointers */
13287 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13289 frame_set->medium_stride_prev_frame_set_file_pos =
13290 tng_data->first_trajectory_frame_set_output_file_pos;
13292 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13294 /* FIXME: Currently only working if the previous frame set has its
13295 * medium stride pointer already set. This might need some fixing. */
13296 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13297 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13299 tng_block_init(&block);
13300 tng_data->input_file = tng_data->output_file;
13302 curr_pos = ftello(tng_data->output_file);
13303 fseeko(tng_data->output_file,
13304 frame_set->medium_stride_prev_frame_set_file_pos,
13307 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13309 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13310 __FILE__, __LINE__);
13311 tng_data->input_file = temp;
13312 tng_block_destroy(&block);
13313 return(TNG_CRITICAL);
13316 /* Read the next frame set from the previous frame set and one
13317 * medium stride step back */
13318 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13319 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13320 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13321 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13322 1, tng_data->output_file) == 0)
13324 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13325 tng_data->input_file = temp;
13326 tng_block_destroy(&block);
13327 return(TNG_CRITICAL);
13330 if(tng_data->input_endianness_swap_func_64)
13332 if(tng_data->input_endianness_swap_func_64(tng_data,
13333 &frame_set->medium_stride_prev_frame_set_file_pos)
13336 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13337 __FILE__, __LINE__);
13341 tng_block_destroy(&block);
13343 /* Set the long range pointers */
13344 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13346 frame_set->long_stride_prev_frame_set_file_pos =
13347 tng_data->first_trajectory_frame_set_output_file_pos;
13349 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13351 /* FIXME: Currently only working if the previous frame set has its
13352 * long stride pointer already set. This might need some fixing. */
13353 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13354 frame_set->long_stride_prev_frame_set_file_pos != 0)
13356 tng_block_init(&block);
13357 tng_data->input_file = tng_data->output_file;
13359 fseeko(tng_data->output_file,
13360 frame_set->long_stride_prev_frame_set_file_pos,
13363 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13365 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13366 __FILE__, __LINE__);
13367 tng_data->input_file = temp;
13368 tng_block_destroy(&block);
13369 return(TNG_CRITICAL);
13372 /* Read the next frame set from the previous frame set and one
13373 * long stride step back */
13374 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13375 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13377 tng_block_destroy(&block);
13379 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13380 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13381 1, tng_data->output_file) == 0)
13383 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13384 tng_data->input_file = temp;
13385 return(TNG_CRITICAL);
13388 if(tng_data->input_endianness_swap_func_64)
13390 if(tng_data->input_endianness_swap_func_64(tng_data,
13391 &frame_set->long_stride_prev_frame_set_file_pos)
13394 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13395 __FILE__, __LINE__);
13402 tng_data->input_file = temp;
13403 fseeko(tng_data->output_file, curr_pos, SEEK_SET);
13407 frame_set->first_frame = first_frame;
13408 frame_set->n_frames = n_frames;
13409 frame_set->n_written_frames = 0;
13410 frame_set->n_unwritten_frames = 0;
13411 frame_set->first_frame_time = -1;
13413 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13414 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13416 tng_data->first_trajectory_frame_set_output_file_pos =
13417 tng_data->current_trajectory_frame_set_output_file_pos;
13419 /* FIXME: Should check the frame number instead of the file_pos,
13420 * in case frame sets are not in order */
13421 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13422 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13423 tng_data->last_trajectory_frame_set_output_file_pos <
13424 tng_data->current_trajectory_frame_set_output_file_pos)
13426 tng_data->last_trajectory_frame_set_output_file_pos =
13427 tng_data->current_trajectory_frame_set_output_file_pos;
13430 return(TNG_SUCCESS);
13433 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13434 (tng_trajectory_t tng_data,
13435 const int64_t first_frame,
13436 const int64_t n_frames,
13437 const double first_frame_time)
13439 tng_function_status stat;
13441 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13442 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13443 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13444 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13447 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13448 if(stat != TNG_SUCCESS)
13452 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13457 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13458 (tng_trajectory_t tng_data,
13459 const double first_frame_time)
13461 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13462 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13464 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13466 return(TNG_SUCCESS);
13469 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13470 (const tng_trajectory_t tng_data,
13473 int64_t file_pos, next_frame_set_file_pos;
13474 tng_gen_block_t block;
13475 tng_function_status stat;
13477 tng_trajectory_frame_set_t frame_set;
13479 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13480 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13481 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13483 file_pos = ftello(tng_data->input_file);
13485 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13487 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13491 frame_set = &tng_data->current_trajectory_frame_set;
13492 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
13495 if(next_frame_set_file_pos <= 0)
13497 return(TNG_FAILURE);
13500 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
13501 /* Read block headers first to see that a frame set block is found. */
13502 tng_block_init(&block);
13503 stat = tng_block_header_read(tng_data, block);
13504 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13506 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13507 file_pos, __FILE__, __LINE__);
13508 return(TNG_CRITICAL);
13510 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13512 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13514 tng_block_destroy(&block);
13516 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13518 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13519 __FILE__, __LINE__);
13520 return(TNG_CRITICAL);
13522 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13524 return(TNG_SUCCESS);
13527 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13528 (tng_trajectory_t tng_data,
13530 const char *block_name,
13531 const char datatype,
13532 const char block_type_flag,
13534 const int64_t n_values_per_frame,
13535 int64_t stride_length,
13536 const int64_t codec_id,
13539 int i, j, size, len;
13540 tng_trajectory_frame_set_t frame_set;
13541 tng_non_particle_data_t data;
13542 char **first_dim_values;
13543 char *new_data_c=new_data;
13544 int64_t n_frames_div;
13546 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13547 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13548 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13550 frame_set = &tng_data->current_trajectory_frame_set;
13552 if(stride_length <= 0)
13557 /* If the block does not exist, create it */
13558 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13560 if(tng_data_block_create(tng_data, block_type_flag) !=
13563 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13564 __FILE__, __LINE__);
13565 return(TNG_CRITICAL);
13567 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13569 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13573 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13575 data->block_id = id;
13577 data->block_name = malloc(strlen(block_name) + 1);
13578 if(!data->block_name)
13580 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13581 (int)strlen(block_name)+1, __FILE__, __LINE__);
13582 return(TNG_CRITICAL);
13584 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13587 /* FIXME: Memory leak from strings. */
13589 data->last_retrieved_frame = -1;
13592 data->datatype = datatype;
13593 data->stride_length = tng_max_i64(stride_length, 1);
13594 data->n_values_per_frame = n_values_per_frame;
13595 data->n_frames = n_frames;
13596 data->codec_id = codec_id;
13597 data->compression_multiplier = 1.0;
13598 /* FIXME: This can cause problems. */
13599 data->first_frame_with_data = frame_set->first_frame;
13603 case TNG_FLOAT_DATA:
13604 size = sizeof(float);
13607 size = sizeof(int64_t);
13609 case TNG_DOUBLE_DATA:
13611 size = sizeof(double);
13617 /* Allocate memory */
13618 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13619 n_values_per_frame) !=
13622 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13623 __FILE__, __LINE__);
13624 return(TNG_CRITICAL);
13627 if(n_frames > frame_set->n_unwritten_frames)
13629 frame_set->n_unwritten_frames = n_frames;
13632 n_frames_div = (n_frames % stride_length) ?
13633 n_frames / stride_length + 1:
13634 n_frames / stride_length;
13636 if(datatype == TNG_CHAR_DATA)
13638 for(i = 0; i < n_frames_div; i++)
13640 first_dim_values = data->strings[i];
13641 for(j = 0; j < n_values_per_frame; j++)
13643 len = tng_min_i((int)strlen(new_data_c) + 1,
13645 if(first_dim_values[j])
13647 free(first_dim_values[j]);
13649 first_dim_values[j] = malloc(len);
13650 if(!first_dim_values[j])
13652 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13653 len, __FILE__, __LINE__);
13654 return(TNG_CRITICAL);
13656 strncpy(first_dim_values[j],
13664 memcpy(data->values, new_data, size * n_frames_div *
13665 n_values_per_frame);
13669 return(TNG_SUCCESS);
13672 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13673 (tng_trajectory_t tng_data,
13675 const char *block_name,
13676 const char datatype,
13677 const char block_type_flag,
13679 const int64_t n_values_per_frame,
13680 int64_t stride_length,
13681 const int64_t num_first_particle,
13682 const int64_t n_particles,
13683 const int64_t codec_id,
13688 int64_t tot_n_particles, n_frames_div;
13689 char ***first_dim_values, **second_dim_values;
13690 tng_trajectory_frame_set_t frame_set;
13691 tng_particle_data_t data;
13692 char *new_data_c=new_data;
13694 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13695 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13696 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13697 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13698 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13701 frame_set = &tng_data->current_trajectory_frame_set;
13703 if(stride_length <= 0)
13708 /* If the block does not exist, create it */
13709 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13711 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13714 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13715 __FILE__, __LINE__);
13716 return(TNG_CRITICAL);
13718 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13720 data = &frame_set->tr_particle_data[frame_set->
13721 n_particle_data_blocks - 1];
13725 data = &tng_data->non_tr_particle_data[tng_data->
13726 n_particle_data_blocks - 1];
13728 data->block_id = id;
13730 data->block_name = malloc(strlen(block_name) + 1);
13731 if(!data->block_name)
13733 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13734 (int)strlen(block_name)+1, __FILE__, __LINE__);
13735 return(TNG_CRITICAL);
13737 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13739 data->datatype = datatype;
13742 /* FIXME: Memory leak from strings. */
13744 data->last_retrieved_frame = -1;
13747 data->stride_length = tng_max_i64(stride_length, 1);
13748 data->n_values_per_frame = n_values_per_frame;
13749 data->n_frames = n_frames;
13750 data->codec_id = codec_id;
13751 data->compression_multiplier = 1.0;
13752 /* FIXME: This can cause problems. */
13753 data->first_frame_with_data = frame_set->first_frame;
13755 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13757 tot_n_particles = frame_set->n_particles;
13761 tot_n_particles = tng_data->n_particles;
13764 /* If data values are supplied add that data to the data block. */
13767 /* Allocate memory */
13768 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13769 stride_length, tot_n_particles,
13770 n_values_per_frame) !=
13773 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13774 __FILE__, __LINE__);
13775 return(TNG_CRITICAL);
13778 if(n_frames > frame_set->n_unwritten_frames)
13780 frame_set->n_unwritten_frames = n_frames;
13783 n_frames_div = (n_frames % stride_length) ?
13784 n_frames / stride_length + 1:
13785 n_frames / stride_length;
13787 if(datatype == TNG_CHAR_DATA)
13789 for(i = 0; i < n_frames_div; i++)
13791 first_dim_values = data->strings[i];
13792 for(j = num_first_particle; j < num_first_particle + n_particles;
13795 second_dim_values = first_dim_values[j];
13796 for(k = 0; k < n_values_per_frame; k++)
13798 len = tng_min_i((int)strlen(new_data_c) + 1,
13800 if(second_dim_values[k])
13802 free(second_dim_values[k]);
13804 second_dim_values[k] = malloc(len);
13805 if(!second_dim_values[k])
13807 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13808 len, __FILE__, __LINE__);
13809 return(TNG_CRITICAL);
13811 strncpy(second_dim_values[k],
13823 size = sizeof(int64_t);
13825 case TNG_FLOAT_DATA:
13826 size = sizeof(float);
13828 case TNG_DOUBLE_DATA:
13830 size = sizeof(double);
13833 memcpy(data->values, new_data, size * n_frames_div *
13834 n_particles * n_values_per_frame);
13838 return(TNG_SUCCESS);
13841 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13842 (tng_trajectory_t tng_data,
13848 tng_trajectory_frame_set_t frame_set;
13849 tng_function_status stat;
13850 tng_particle_data_t p_data;
13851 tng_non_particle_data_t np_data;
13852 int block_type = -1;
13854 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13855 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13857 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13859 p_data = &tng_data->non_tr_particle_data[i];
13860 if(p_data->block_id == block_id)
13862 strncpy(name, p_data->block_name, max_len);
13863 name[max_len - 1] = '\0';
13864 return(TNG_SUCCESS);
13867 for(i = 0; i < tng_data->n_data_blocks; i++)
13869 np_data = &tng_data->non_tr_data[i];
13870 if(np_data->block_id == block_id)
13872 strncpy(name, np_data->block_name, max_len);
13873 name[max_len - 1] = '\0';
13874 return(TNG_SUCCESS);
13878 frame_set = &tng_data->current_trajectory_frame_set;
13880 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13881 if(stat == TNG_SUCCESS)
13883 block_type = TNG_PARTICLE_BLOCK_DATA;
13887 stat = tng_data_find(tng_data, block_id, &np_data);
13888 if(stat == TNG_SUCCESS)
13890 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13894 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13895 if(stat != TNG_SUCCESS)
13899 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13900 if(stat == TNG_SUCCESS)
13902 block_type = TNG_PARTICLE_BLOCK_DATA;
13906 stat = tng_data_find(tng_data, block_id, &np_data);
13907 if(stat == TNG_SUCCESS)
13909 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13914 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13916 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13918 p_data = &frame_set->tr_particle_data[i];
13919 if(p_data->block_id == block_id)
13921 strncpy(name, p_data->block_name, max_len);
13922 name[max_len - 1] = '\0';
13923 return(TNG_SUCCESS);
13927 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13929 for(i = 0; i < frame_set->n_data_blocks; i++)
13931 np_data = &frame_set->tr_data[i];
13932 if(np_data->block_id == block_id)
13934 strncpy(name, np_data->block_name, max_len);
13935 name[max_len - 1] = '\0';
13936 return(TNG_SUCCESS);
13941 return(TNG_FAILURE);
13944 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13945 (const tng_trajectory_t tng_data,
13947 int *block_dependency)
13950 tng_function_status stat;
13951 tng_particle_data_t p_data;
13952 tng_non_particle_data_t np_data;
13954 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13955 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13957 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13959 p_data = &tng_data->non_tr_particle_data[i];
13960 if(p_data->block_id == block_id)
13962 *block_dependency = TNG_PARTICLE_DEPENDENT;
13963 return(TNG_SUCCESS);
13966 for(i = 0; i < tng_data->n_data_blocks; i++)
13968 np_data = &tng_data->non_tr_data[i];
13969 if(np_data->block_id == block_id)
13971 *block_dependency = 0;
13972 return(TNG_SUCCESS);
13976 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13977 if(stat == TNG_SUCCESS)
13979 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13980 return(TNG_SUCCESS);
13984 stat = tng_data_find(tng_data, block_id, &np_data);
13985 if(stat == TNG_SUCCESS)
13987 *block_dependency = TNG_FRAME_DEPENDENT;
13988 return(TNG_SUCCESS);
13992 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13993 if(stat != TNG_SUCCESS)
13997 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13998 if(stat == TNG_SUCCESS)
14000 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
14001 return(TNG_SUCCESS);
14005 stat = tng_data_find(tng_data, block_id, &np_data);
14006 if(stat == TNG_SUCCESS)
14008 *block_dependency = TNG_FRAME_DEPENDENT;
14009 return(TNG_SUCCESS);
14015 return(TNG_FAILURE);
14018 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
14019 (const tng_trajectory_t tng_data,
14021 int64_t *n_values_per_frame)
14024 tng_function_status stat;
14025 tng_particle_data_t p_data;
14026 tng_non_particle_data_t np_data;
14028 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14029 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14031 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
14033 p_data = &tng_data->non_tr_particle_data[i];
14034 if(p_data->block_id == block_id)
14036 *n_values_per_frame = p_data->n_values_per_frame;
14037 return(TNG_SUCCESS);
14040 for(i = 0; i < tng_data->n_data_blocks; i++)
14042 np_data = &tng_data->non_tr_data[i];
14043 if(np_data->block_id == block_id)
14045 *n_values_per_frame = np_data->n_values_per_frame;
14046 return(TNG_SUCCESS);
14050 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14051 if(stat == TNG_SUCCESS)
14053 *n_values_per_frame = p_data->n_values_per_frame;
14054 return(TNG_SUCCESS);
14058 stat = tng_data_find(tng_data, block_id, &np_data);
14059 if(stat == TNG_SUCCESS)
14061 *n_values_per_frame = np_data->n_values_per_frame;
14062 return(TNG_SUCCESS);
14066 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14067 if(stat != TNG_SUCCESS)
14071 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14072 if(stat == TNG_SUCCESS)
14074 *n_values_per_frame = p_data->n_values_per_frame;
14075 return(TNG_SUCCESS);
14079 stat = tng_data_find(tng_data, block_id, &np_data);
14080 if(stat == TNG_SUCCESS)
14082 *n_values_per_frame = np_data->n_values_per_frame;
14083 return(TNG_SUCCESS);
14089 return(TNG_FAILURE);
14092 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14093 (tng_trajectory_t tng_data,
14094 const int64_t frame_nr,
14095 const int64_t block_id,
14096 const void *values,
14097 const char hash_mode)
14099 int64_t header_pos, file_pos;
14100 int64_t output_file_len, n_values_per_frame, size, contents_size;
14101 int64_t header_size, temp_first, temp_last;
14102 int64_t i, last_frame, temp_current;
14103 tng_gen_block_t block;
14104 tng_trajectory_frame_set_t frame_set;
14105 FILE *temp = tng_data->input_file;
14106 struct tng_non_particle_data data;
14107 tng_function_status stat;
14108 char dependency, sparse_data, datatype;
14111 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14112 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14113 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14115 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14117 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14118 __FILE__, __LINE__);
14119 return(TNG_CRITICAL);
14122 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14123 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14124 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14125 tng_data->first_trajectory_frame_set_input_file_pos =
14126 tng_data->first_trajectory_frame_set_output_file_pos;
14127 tng_data->last_trajectory_frame_set_input_file_pos =
14128 tng_data->last_trajectory_frame_set_output_file_pos;
14129 tng_data->current_trajectory_frame_set_input_file_pos =
14130 tng_data->current_trajectory_frame_set_output_file_pos;
14132 tng_data->input_file = tng_data->output_file;
14134 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14136 frame_set = &tng_data->current_trajectory_frame_set;
14138 if(stat != TNG_SUCCESS)
14140 last_frame = frame_set->first_frame +
14141 frame_set->n_frames - 1;
14142 /* If the wanted frame would be in the frame set after the last
14143 * frame set create a new frame set. */
14144 if(stat == TNG_FAILURE &&
14145 last_frame < frame_nr)
14146 /* (last_frame < frame_nr &&
14147 tng_data->current_trajectory_frame_set.first_frame +
14148 tng_data->frame_set_n_frames >= frame_nr))*/
14150 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14152 last_frame = frame_nr - 1;
14154 tng_frame_set_new(tng_data,
14156 tng_data->frame_set_n_frames);
14157 file_pos = ftello(tng_data->output_file);
14158 fseeko(tng_data->output_file, 0, SEEK_END);
14159 output_file_len = ftello(tng_data->output_file);
14160 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14162 /* Read mapping blocks from the last frame set */
14163 tng_block_init(&block);
14165 stat = tng_block_header_read(tng_data, block);
14166 while(file_pos < output_file_len &&
14167 stat != TNG_CRITICAL &&
14168 block->id != TNG_TRAJECTORY_FRAME_SET &&
14171 if(block->id == TNG_PARTICLE_MAPPING)
14173 tng_trajectory_mapping_block_read(tng_data, block,
14178 fseeko(tng_data->output_file, block->block_contents_size,
14181 file_pos = ftello(tng_data->output_file);
14182 if(file_pos < output_file_len)
14184 stat = tng_block_header_read(tng_data, block);
14188 tng_block_destroy(&block);
14189 /* Write the frame set to disk */
14190 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14192 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14193 return(TNG_CRITICAL);
14198 tng_data->input_file = temp;
14199 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14200 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14201 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14206 tng_block_init(&block);
14208 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14210 fseeko(tng_data->output_file, 0, SEEK_END);
14211 output_file_len = ftello(tng_data->output_file);
14212 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14214 /* Read past the frame set block first */
14215 stat = tng_block_header_read(tng_data, block);
14216 if(stat == TNG_CRITICAL)
14218 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14219 file_pos, __FILE__, __LINE__);
14220 tng_block_destroy(&block);
14221 tng_data->input_file = temp;
14223 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14224 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14225 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14228 fseeko(tng_data->output_file, block->block_contents_size,
14231 /* Read all block headers until next frame set block or
14232 * until the wanted block id is found */
14233 stat = tng_block_header_read(tng_data, block);
14234 while(file_pos < output_file_len &&
14235 stat != TNG_CRITICAL &&
14236 block->id != block_id &&
14237 block->id != TNG_TRAJECTORY_FRAME_SET &&
14240 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14241 file_pos = ftello(tng_data->output_file);
14242 if(file_pos < output_file_len)
14244 stat = tng_block_header_read(tng_data, block);
14247 if(stat == TNG_CRITICAL)
14249 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14250 file_pos, __FILE__, __LINE__);
14251 tng_block_destroy(&block);
14252 tng_data->input_file = temp;
14253 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14254 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14255 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14259 contents_size = block->block_contents_size;
14260 header_size = block->header_contents_size;
14262 header_pos = ftello(tng_data->output_file) - header_size;
14263 frame_set = &tng_data->current_trajectory_frame_set;
14265 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14267 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14268 tng_block_destroy(&block);
14269 return(TNG_CRITICAL);
14271 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14273 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14274 tng_block_destroy(&block);
14275 return(TNG_CRITICAL);
14277 data.datatype = datatype;
14279 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14280 (dependency & TNG_PARTICLE_DEPENDENT))
14282 tng_block_destroy(&block);
14283 tng_data->input_file = temp;
14285 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14286 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14287 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14288 return(TNG_FAILURE);
14291 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14293 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14294 tng_block_destroy(&block);
14295 return(TNG_CRITICAL);
14298 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14299 tng_data->input_file) == 0)
14301 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14302 tng_block_destroy(&block);
14303 return(TNG_CRITICAL);
14305 if(tng_data->output_endianness_swap_func_64)
14307 if(tng_data->output_endianness_swap_func_64(tng_data,
14308 &data.n_values_per_frame)
14311 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14312 __FILE__, __LINE__);
14316 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14317 tng_data->input_file) == 0)
14319 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14320 tng_block_destroy(&block);
14321 return(TNG_CRITICAL);
14323 if(tng_data->output_endianness_swap_func_64)
14325 if(tng_data->output_endianness_swap_func_64(tng_data,
14329 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14330 __FILE__, __LINE__);
14334 if(data.codec_id != TNG_UNCOMPRESSED)
14336 if(fread(&data.compression_multiplier,
14337 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14340 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14341 tng_block_destroy(&block);
14342 return(TNG_CRITICAL);
14344 if(tng_data->output_endianness_swap_func_64)
14346 if(tng_data->output_endianness_swap_func_64(tng_data,
14347 (int64_t *)&data.compression_multiplier)
14350 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14351 __FILE__, __LINE__);
14357 data.compression_multiplier = 1;
14362 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14363 1, tng_data->input_file) == 0)
14365 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14366 tng_block_destroy(&block);
14367 return(TNG_CRITICAL);
14369 if(tng_data->output_endianness_swap_func_64)
14371 if(tng_data->output_endianness_swap_func_64(tng_data,
14372 &data.first_frame_with_data)
14375 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14376 __FILE__, __LINE__);
14380 if(fread(&data.stride_length, sizeof(data.stride_length),
14381 1, tng_data->input_file) == 0)
14383 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14384 tng_block_destroy(&block);
14385 return(TNG_CRITICAL);
14387 if(tng_data->output_endianness_swap_func_64)
14389 if(tng_data->output_endianness_swap_func_64(tng_data,
14390 &data.stride_length)
14393 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14394 __FILE__, __LINE__);
14400 data.first_frame_with_data = 0;
14401 data.stride_length = 1;
14403 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14405 tng_data->input_file = temp;
14407 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14408 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14409 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14411 switch(data.datatype)
14413 case(TNG_INT_DATA):
14414 size = sizeof(int64_t);
14416 case(TNG_FLOAT_DATA):
14417 size = sizeof(float);
14419 case(TNG_DOUBLE_DATA):
14420 size = sizeof(double);
14423 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14425 tng_block_destroy(&block);
14426 return(TNG_FAILURE);
14429 n_values_per_frame = data.n_values_per_frame;
14431 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14432 data.first_frame_with_data)) /
14433 data.stride_length;
14434 file_pos *= size * n_values_per_frame;
14436 if(file_pos > contents_size)
14438 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14440 tng_block_destroy(&block);
14441 return(TNG_FAILURE);
14444 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
14446 /* If the endianness is not big endian the data needs to be swapped */
14447 if((data.datatype == TNG_INT_DATA ||
14448 data.datatype == TNG_DOUBLE_DATA) &&
14449 tng_data->output_endianness_swap_func_64)
14451 copy = malloc(n_values_per_frame * size);
14452 memcpy(copy, values, n_values_per_frame * size);
14453 for(i = 0; i < n_values_per_frame; i++)
14455 if(tng_data->output_endianness_swap_func_64(tng_data,
14459 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14460 __FILE__, __LINE__);
14463 fwrite(copy, n_values_per_frame, size,
14464 tng_data->output_file);
14467 else if(data.datatype == TNG_FLOAT_DATA &&
14468 tng_data->output_endianness_swap_func_32)
14470 copy = malloc(n_values_per_frame * size);
14471 memcpy(copy, values, n_values_per_frame * size);
14472 for(i = 0; i < n_values_per_frame; i++)
14474 if(tng_data->output_endianness_swap_func_32(tng_data,
14478 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14479 __FILE__, __LINE__);
14482 fwrite(copy, n_values_per_frame, size,
14483 tng_data->output_file);
14489 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14492 fflush(tng_data->output_file);
14494 /* Update the number of written frames in the frame set. */
14495 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14497 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14500 /* If the last frame has been written update the hash */
14501 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14502 data.first_frame_with_data) >=
14503 frame_set->n_frames)
14505 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14509 tng_block_destroy(&block);
14511 return(TNG_SUCCESS);
14514 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14515 (tng_trajectory_t tng_data,
14516 const int64_t frame_nr,
14517 const int64_t block_id,
14518 const int64_t val_first_particle,
14519 const int64_t val_n_particles,
14520 const void *values,
14521 const char hash_mode)
14523 int64_t header_pos, file_pos, tot_n_particles;
14524 int64_t output_file_len, n_values_per_frame, size, contents_size;
14525 int64_t header_size, temp_first, temp_last;
14526 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14527 int64_t i, last_frame, temp_current;
14528 tng_gen_block_t block;
14529 tng_trajectory_frame_set_t frame_set;
14530 FILE *temp = tng_data->input_file;
14531 struct tng_particle_data data;
14532 tng_function_status stat;
14533 tng_particle_mapping_t mapping;
14534 char dependency, sparse_data, datatype;
14537 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14538 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14539 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14540 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14541 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14543 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14545 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14546 __FILE__, __LINE__);
14547 return(TNG_CRITICAL);
14550 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14551 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14552 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14553 tng_data->first_trajectory_frame_set_input_file_pos =
14554 tng_data->first_trajectory_frame_set_output_file_pos;
14555 tng_data->last_trajectory_frame_set_input_file_pos =
14556 tng_data->last_trajectory_frame_set_output_file_pos;
14557 tng_data->current_trajectory_frame_set_input_file_pos =
14558 tng_data->current_trajectory_frame_set_output_file_pos;
14560 tng_data->input_file = tng_data->output_file;
14562 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14564 frame_set = &tng_data->current_trajectory_frame_set;
14566 if(stat != TNG_SUCCESS)
14568 last_frame = frame_set->first_frame +
14569 frame_set->n_frames - 1;
14570 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14572 /* If the wanted frame would be in the frame set after the last
14573 * frame set create a new frame set. */
14574 if(stat == TNG_FAILURE &&
14575 (last_frame < frame_nr &&
14576 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14578 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14580 last_frame = frame_nr - 1;
14582 tng_frame_set_new(tng_data,
14584 tng_data->frame_set_n_frames);
14586 file_pos = ftello(tng_data->output_file);
14587 fseeko(tng_data->output_file, 0, SEEK_END);
14588 output_file_len = ftello(tng_data->output_file);
14589 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14591 /* Read mapping blocks from the last frame set */
14592 tng_block_init(&block);
14594 stat = tng_block_header_read(tng_data, block);
14595 while(file_pos < output_file_len &&
14596 stat != TNG_CRITICAL &&
14597 block->id != TNG_TRAJECTORY_FRAME_SET &&
14600 if(block->id == TNG_PARTICLE_MAPPING)
14602 tng_trajectory_mapping_block_read(tng_data, block,
14607 fseeko(tng_data->output_file, block->block_contents_size,
14610 file_pos = ftello(tng_data->output_file);
14611 if(file_pos < output_file_len)
14613 stat = tng_block_header_read(tng_data, block);
14617 tng_block_destroy(&block);
14618 /* Write the frame set to disk */
14619 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14621 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14627 tng_data->input_file = temp;
14628 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14629 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14630 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14636 tng_block_init(&block);
14638 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14640 fseeko(tng_data->output_file, 0, SEEK_END);
14641 output_file_len = ftello(tng_data->output_file);
14642 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14644 /* Read past the frame set block first */
14645 stat = tng_block_header_read(tng_data, block);
14646 if(stat == TNG_CRITICAL)
14648 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14649 file_pos, __FILE__, __LINE__);
14650 tng_block_destroy(&block);
14651 tng_data->input_file = temp;
14653 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14654 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14655 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14658 fseeko(tng_data->output_file, block->block_contents_size,
14661 if(tng_data->var_num_atoms_flag)
14663 tot_n_particles = frame_set->n_particles;
14667 tot_n_particles = tng_data->n_particles;
14670 if(val_n_particles < tot_n_particles)
14672 mapping_block_end_pos = -1;
14673 /* Read all mapping blocks to find the right place to put the data */
14674 stat = tng_block_header_read(tng_data, block);
14675 while(file_pos < output_file_len &&
14676 stat != TNG_CRITICAL &&
14677 block->id != TNG_TRAJECTORY_FRAME_SET &&
14680 if(block->id == TNG_PARTICLE_MAPPING)
14682 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14686 fseeko(tng_data->output_file, block->block_contents_size,
14689 file_pos = ftello(tng_data->output_file);
14690 if(block->id == TNG_PARTICLE_MAPPING)
14692 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14693 if(val_first_particle >= mapping->num_first_particle &&
14694 val_first_particle < mapping->num_first_particle +
14695 mapping->n_particles &&
14696 val_first_particle + val_n_particles <=
14697 mapping->num_first_particle + mapping->n_particles)
14699 mapping_block_end_pos = file_pos;
14702 if(file_pos < output_file_len)
14704 stat = tng_block_header_read(tng_data, block);
14707 if(stat == TNG_CRITICAL)
14709 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14710 file_pos, __FILE__, __LINE__);
14711 tng_block_destroy(&block);
14712 tng_data->input_file = temp;
14714 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14715 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14716 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14719 if(mapping_block_end_pos < 0)
14721 tng_block_destroy(&block);
14722 tng_data->input_file = temp;
14724 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14725 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14726 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14727 return(TNG_FAILURE);
14729 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
14732 /* Read all block headers until next frame set block or
14733 * until the wanted block id is found */
14734 stat = tng_block_header_read(tng_data, block);
14735 while(file_pos < output_file_len &&
14736 stat != TNG_CRITICAL &&
14737 block->id != block_id &&
14738 block->id != TNG_PARTICLE_MAPPING &&
14739 block->id != TNG_TRAJECTORY_FRAME_SET &&
14742 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14743 file_pos = ftello(tng_data->output_file);
14744 if(file_pos < output_file_len)
14746 stat = tng_block_header_read(tng_data, block);
14749 if(stat == TNG_CRITICAL)
14751 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14752 file_pos, __FILE__, __LINE__);
14753 tng_block_destroy(&block);
14754 tng_data->input_file = temp;
14756 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14757 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14758 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14762 contents_size = block->block_contents_size;
14763 header_size = block->header_contents_size;
14765 header_pos = ftello(tng_data->output_file) - header_size;
14766 frame_set = &tng_data->current_trajectory_frame_set;
14768 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14770 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14771 tng_block_destroy(&block);
14772 return(TNG_CRITICAL);
14775 data.datatype = datatype;
14777 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14779 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14780 tng_block_destroy(&block);
14781 return(TNG_CRITICAL);
14784 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14785 !(dependency & TNG_PARTICLE_DEPENDENT))
14787 tng_block_destroy(&block);
14788 tng_data->input_file = temp;
14790 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14791 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14792 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14793 return(TNG_FAILURE);
14796 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14798 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14799 tng_block_destroy(&block);
14800 return(TNG_CRITICAL);
14803 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14804 tng_data->input_file) == 0)
14806 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14807 tng_block_destroy(&block);
14808 return(TNG_CRITICAL);
14810 if(tng_data->output_endianness_swap_func_64)
14812 if(tng_data->output_endianness_swap_func_64(tng_data,
14813 &data.n_values_per_frame)
14816 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14817 __FILE__, __LINE__);
14821 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14822 tng_data->input_file) == 0)
14824 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14825 tng_block_destroy(&block);
14826 return(TNG_CRITICAL);
14828 if(tng_data->output_endianness_swap_func_64)
14830 if(tng_data->output_endianness_swap_func_64(tng_data,
14834 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14835 __FILE__, __LINE__);
14839 if(data.codec_id != TNG_UNCOMPRESSED)
14841 if(fread(&data.compression_multiplier,
14842 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14845 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14846 tng_block_destroy(&block);
14847 return(TNG_CRITICAL);
14850 if(tng_data->output_endianness_swap_func_64)
14852 if(tng_data->output_endianness_swap_func_64(tng_data,
14853 (int64_t *)&data.compression_multiplier)
14856 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14857 __FILE__, __LINE__);
14863 data.compression_multiplier = 1;
14868 if(fread(&data.first_frame_with_data,
14869 sizeof(data.first_frame_with_data),
14870 1, tng_data->input_file) == 0)
14872 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14873 tng_block_destroy(&block);
14874 return(TNG_CRITICAL);
14876 if(tng_data->output_endianness_swap_func_64)
14878 if(tng_data->output_endianness_swap_func_64(tng_data,
14879 &data.first_frame_with_data)
14882 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14883 __FILE__, __LINE__);
14887 if(fread(&data.stride_length, sizeof(data.stride_length),
14888 1, tng_data->input_file) == 0)
14890 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14891 tng_block_destroy(&block);
14892 return(TNG_CRITICAL);
14894 if(tng_data->output_endianness_swap_func_64)
14896 if(tng_data->output_endianness_swap_func_64(tng_data,
14897 &data.stride_length)
14900 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14901 __FILE__, __LINE__);
14907 data.first_frame_with_data = 0;
14908 data.stride_length = 1;
14910 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14912 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14913 tng_data->input_file) == 0)
14915 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14916 tng_block_destroy(&block);
14917 return(TNG_CRITICAL);
14919 if(tng_data->output_endianness_swap_func_64)
14921 if(tng_data->output_endianness_swap_func_64(tng_data,
14922 &num_first_particle)
14925 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14926 __FILE__, __LINE__);
14930 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14931 tng_data->input_file) == 0)
14933 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14934 tng_block_destroy(&block);
14935 return(TNG_CRITICAL);
14937 if(tng_data->output_endianness_swap_func_64)
14939 if(tng_data->output_endianness_swap_func_64(tng_data,
14940 &block_n_particles)
14943 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14944 __FILE__, __LINE__);
14949 tng_data->input_file = temp;
14951 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14952 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14953 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14956 switch(data.datatype)
14958 case(TNG_INT_DATA):
14959 size = sizeof(int64_t);
14961 case(TNG_FLOAT_DATA):
14962 size = sizeof(float);
14964 case(TNG_DOUBLE_DATA):
14965 size = sizeof(double);
14968 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14970 tng_block_destroy(&block);
14971 return(TNG_FAILURE);
14974 n_values_per_frame = data.n_values_per_frame;
14976 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14977 data.first_frame_with_data)) /
14978 data.stride_length;
14979 file_pos *= block_n_particles * size * n_values_per_frame;
14981 if(file_pos > contents_size)
14983 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14985 tng_block_destroy(&block);
14986 return(TNG_FAILURE);
14989 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
14991 /* If the endianness is not big endian the data needs to be swapped */
14992 if((data.datatype == TNG_INT_DATA ||
14993 data.datatype == TNG_DOUBLE_DATA) &&
14994 tng_data->output_endianness_swap_func_64)
14996 copy = malloc(val_n_particles * n_values_per_frame * size);
14997 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14998 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15000 if(tng_data->output_endianness_swap_func_64(tng_data,
15001 (int64_t *) copy+i)
15004 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15005 __FILE__, __LINE__);
15008 fwrite(copy, val_n_particles * n_values_per_frame, size,
15009 tng_data->output_file);
15012 else if(data.datatype == TNG_FLOAT_DATA &&
15013 tng_data->output_endianness_swap_func_32)
15015 copy = malloc(val_n_particles * n_values_per_frame * size);
15016 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15017 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15019 if(tng_data->output_endianness_swap_func_32(tng_data,
15020 (int32_t *) copy+i)
15023 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15024 __FILE__, __LINE__);
15027 fwrite(copy, val_n_particles * n_values_per_frame, size,
15028 tng_data->output_file);
15034 fwrite(values, val_n_particles * n_values_per_frame, size,
15035 tng_data->output_file);
15037 fflush(tng_data->output_file);
15039 /* Update the number of written frames in the frame set. */
15040 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
15042 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
15045 /* If the last frame has been written update the hash */
15046 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
15047 data.first_frame_with_data) >=
15048 frame_set->n_frames)
15050 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
15054 tng_block_destroy(&block);
15055 return(TNG_SUCCESS);
15058 static tng_function_status tng_data_values_alloc
15059 (const tng_trajectory_t tng_data,
15060 union data_values ***values,
15061 const int64_t n_frames,
15062 const int64_t n_values_per_frame,
15066 tng_function_status stat;
15068 if(n_frames <= 0 || n_values_per_frame <= 0)
15070 return(TNG_FAILURE);
15075 stat = tng_data_values_free(tng_data, *values, n_frames,
15076 n_values_per_frame,
15078 if(stat != TNG_SUCCESS)
15080 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15081 __FILE__, __LINE__);
15085 *values = malloc(sizeof(union data_values *) * n_frames);
15088 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15089 sizeof(union data_values **) * n_frames,
15090 __FILE__, __LINE__);
15091 return(TNG_CRITICAL);
15095 for(i = 0; i < n_frames; i++)
15097 (*values)[i] = malloc(sizeof(union data_values) *
15098 n_values_per_frame);
15101 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15102 sizeof(union data_values) * n_values_per_frame,
15103 __FILE__, __LINE__);
15106 return(TNG_CRITICAL);
15109 return(TNG_SUCCESS);
15112 /* FIXME: This needs ***values */
15113 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15114 (const tng_trajectory_t tng_data,
15115 union data_values **values,
15116 const int64_t n_frames,
15117 const int64_t n_values_per_frame,
15125 for(i = 0; i < n_frames; i++)
15129 if(type == TNG_CHAR_DATA)
15131 for(j = 0; j < n_values_per_frame; j++)
15135 free(values[i][j].c);
15136 values[i][j].c = 0;
15148 return(TNG_SUCCESS);
15151 static tng_function_status tng_particle_data_values_alloc
15152 (const tng_trajectory_t tng_data,
15153 union data_values ****values,
15154 const int64_t n_frames,
15155 const int64_t n_particles,
15156 const int64_t n_values_per_frame,
15160 tng_function_status stat;
15162 if(n_particles == 0 || n_values_per_frame == 0)
15164 return(TNG_FAILURE);
15169 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15170 n_particles, n_values_per_frame,
15172 if(stat != TNG_SUCCESS)
15174 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15175 __FILE__, __LINE__);
15179 *values = malloc(sizeof(union data_values **) * n_frames);
15182 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15183 sizeof(union data_values **) * n_frames,
15184 __FILE__, __LINE__);
15185 return(TNG_CRITICAL);
15189 for(i = 0; i < n_frames; i++)
15191 (*values)[i] = malloc(sizeof(union data_values *) *
15195 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15196 sizeof(union data_values *) * n_particles,
15197 __FILE__, __LINE__);
15200 return(TNG_CRITICAL);
15202 for(j = 0; j < n_particles; j++)
15204 (*values)[i][j] = malloc(sizeof(union data_values) *
15205 n_values_per_frame);
15206 if(!(*values)[i][j])
15208 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15209 sizeof(union data_values *) * n_particles,
15210 __FILE__, __LINE__);
15211 tng_particle_data_values_free(tng_data, *values, n_frames,
15212 n_particles, n_values_per_frame,
15215 return(TNG_CRITICAL);
15219 return(TNG_SUCCESS);
15222 /* FIXME: This needs ****values */
15223 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15224 (const tng_trajectory_t tng_data,
15225 union data_values ***values,
15226 const int64_t n_frames,
15227 const int64_t n_particles,
15228 const int64_t n_values_per_frame,
15236 for(i = 0; i < n_frames; i++)
15240 for(j = 0; j < n_particles; j++)
15242 if(type == TNG_CHAR_DATA)
15244 for(k = 0; k < n_values_per_frame; k++)
15246 if(values[i][j][k].c)
15248 free(values[i][j][k].c);
15249 values[i][j][k].c = 0;
15253 free(values[i][j]);
15264 return(TNG_SUCCESS);
15268 tng_function_status DECLSPECDLLEXPORT tng_data_get
15269 (tng_trajectory_t tng_data,
15270 const int64_t block_id,
15271 union data_values ***values,
15273 int64_t *n_values_per_frame,
15276 int64_t i, j, file_pos, block_index;
15279 tng_non_particle_data_t data;
15280 tng_trajectory_frame_set_t frame_set;
15281 tng_gen_block_t block;
15282 tng_function_status stat;
15284 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15285 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15286 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15287 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15289 frame_set = &tng_data->current_trajectory_frame_set;
15294 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15296 tng_block_init(&block);
15297 file_pos = ftello(tng_data->input_file);
15298 /* Read all blocks until next frame set block */
15299 stat = tng_block_header_read(tng_data, block);
15300 while(file_pos < tng_data->input_file_len &&
15301 stat != TNG_CRITICAL &&
15302 block->id != TNG_TRAJECTORY_FRAME_SET &&
15305 /* Use hash by default */
15306 stat = tng_block_read_next(tng_data, block,
15308 if(stat != TNG_CRITICAL)
15310 file_pos = ftello(tng_data->input_file);
15311 if(file_pos < tng_data->input_file_len)
15313 stat = tng_block_header_read(tng_data, block);
15317 tng_block_destroy(&block);
15318 if(stat == TNG_CRITICAL)
15320 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15321 file_pos, __FILE__, __LINE__);
15325 for(i = 0; i < frame_set->n_data_blocks; i++)
15327 data = &frame_set->tr_data[i];
15328 if(data->block_id == block_id)
15334 if(block_index < 0)
15336 return(TNG_FAILURE);
15340 *n_frames = tng_max_i64(1, data->n_frames);
15341 *n_values_per_frame = data->n_values_per_frame;
15342 *type = data->datatype;
15346 if(tng_data_values_alloc(tng_data, values, *n_frames,
15347 *n_values_per_frame,
15351 return(TNG_CRITICAL);
15357 case TNG_CHAR_DATA:
15358 for(i = 0; i < *n_frames; i++)
15360 for(j = 0; j < *n_values_per_frame; j++)
15362 len = strlen(data->strings[i][j]) + 1;
15363 (*values)[i][j].c = malloc(len);
15364 strncpy((*values)[i][j].c, data->strings[i][j], len);
15369 size = sizeof(int);
15370 for(i = 0; i < *n_frames; i++)
15372 for(j = 0; j < *n_values_per_frame; j++)
15374 (*values)[i][j].i = *(int *)((char *)data->values + size *
15375 (i*(*n_values_per_frame) + j));
15379 case TNG_FLOAT_DATA:
15380 size = sizeof(float);
15381 for(i = 0; i < *n_frames; i++)
15383 for(j = 0; j < *n_values_per_frame; j++)
15385 (*values)[i][j].f = *(float *)((char *)data->values + size *
15386 (i*(*n_values_per_frame) + j));
15390 case TNG_DOUBLE_DATA:
15392 size = sizeof(double);
15393 for(i = 0; i < *n_frames; i++)
15395 for(j = 0; j < *n_values_per_frame; j++)
15397 (*values)[i][j].d = *(double *)((char *)data->values + size *
15398 (i*(*n_values_per_frame) + j));
15403 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15405 return(TNG_SUCCESS);
15408 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15409 const int64_t block_id,
15412 int64_t *stride_length,
15413 int64_t *n_values_per_frame,
15416 int64_t file_pos, data_size, n_frames_div, block_index;
15418 tng_non_particle_data_t data;
15419 tng_trajectory_frame_set_t frame_set;
15420 tng_gen_block_t block;
15422 tng_function_status stat;
15424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15425 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15426 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15427 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15428 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15430 frame_set = &tng_data->current_trajectory_frame_set;
15435 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15437 tng_block_init(&block);
15438 file_pos = ftello(tng_data->input_file);
15439 /* Read all blocks until next frame set block */
15440 stat = tng_block_header_read(tng_data, block);
15441 while(file_pos < tng_data->input_file_len &&
15442 stat != TNG_CRITICAL &&
15443 block->id != TNG_TRAJECTORY_FRAME_SET &&
15446 /* Use hash by default */
15447 stat = tng_block_read_next(tng_data, block,
15449 if(stat != TNG_CRITICAL)
15451 file_pos = ftello(tng_data->input_file);
15452 if(file_pos < tng_data->input_file_len)
15454 stat = tng_block_header_read(tng_data, block);
15458 tng_block_destroy(&block);
15459 if(stat == TNG_CRITICAL)
15461 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15462 file_pos, __FILE__, __LINE__);
15466 for(i = 0; i < frame_set->n_data_blocks; i++)
15468 data = &frame_set->tr_data[i];
15469 if(data->block_id == block_id)
15475 if(block_index < 0)
15477 return(TNG_FAILURE);
15481 *type = data->datatype;
15485 case TNG_CHAR_DATA:
15486 return(TNG_FAILURE);
15488 size = sizeof(int64_t);
15490 case TNG_FLOAT_DATA:
15491 size = sizeof(float);
15493 case TNG_DOUBLE_DATA:
15495 size = sizeof(double);
15498 *n_frames = data->n_frames;
15499 *n_values_per_frame = data->n_values_per_frame;
15500 *stride_length = data->stride_length;
15501 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15502 *n_frames / *stride_length;
15504 data_size = n_frames_div * size *
15505 *n_values_per_frame;
15507 temp = realloc(*values, data_size);
15510 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15511 data_size, __FILE__, __LINE__);
15514 return(TNG_CRITICAL);
15519 memcpy(*values, data->values, data_size);
15521 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15523 return(TNG_SUCCESS);
15526 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15527 (tng_trajectory_t tng_data,
15528 const int64_t block_id,
15529 const int64_t start_frame_nr,
15530 const int64_t end_frame_nr,
15531 const char hash_mode,
15532 union data_values ***values,
15533 int64_t *n_values_per_frame,
15536 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15537 int64_t block_index;
15540 tng_non_particle_data_t data;
15541 tng_trajectory_frame_set_t frame_set;
15542 tng_gen_block_t block;
15543 tng_function_status stat;
15545 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15546 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15547 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15548 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15552 frame_set = &tng_data->current_trajectory_frame_set;
15553 first_frame = frame_set->first_frame;
15555 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15556 if(stat != TNG_SUCCESS)
15562 /* Do not re-read the frame set. */
15563 if(first_frame != frame_set->first_frame ||
15564 frame_set->n_data_blocks <= 0)
15566 tng_block_init(&block);
15567 file_pos = ftello(tng_data->input_file);
15568 /* Read all blocks until next frame set block */
15569 stat = tng_block_header_read(tng_data, block);
15570 while(file_pos < tng_data->input_file_len &&
15571 stat != TNG_CRITICAL &&
15572 block->id != TNG_TRAJECTORY_FRAME_SET &&
15575 stat = tng_block_read_next(tng_data, block,
15577 if(stat != TNG_CRITICAL)
15579 file_pos = ftello(tng_data->input_file);
15580 if(file_pos < tng_data->input_file_len)
15582 stat = tng_block_header_read(tng_data, block);
15586 tng_block_destroy(&block);
15587 if(stat == TNG_CRITICAL)
15589 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15590 file_pos, __FILE__, __LINE__);
15596 /* See if there is a data block of this ID.
15597 * Start checking the last read frame set */
15598 for(i = 0; i < frame_set->n_data_blocks; i++)
15600 data = &frame_set->tr_data[i];
15601 if(data->block_id == block_id)
15608 if(block_index < 0)
15610 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15611 block_id, __FILE__, __LINE__);
15612 return(TNG_FAILURE);
15615 n_frames = end_frame_nr - start_frame_nr + 1;
15616 *n_values_per_frame = data->n_values_per_frame;
15617 *type = data->datatype;
15621 if(tng_data_values_alloc(tng_data, values, n_frames,
15622 *n_values_per_frame,
15623 *type) != TNG_SUCCESS)
15625 return(TNG_CRITICAL);
15629 current_frame_pos = start_frame_nr - frame_set->first_frame;
15630 /* It's not very elegant to reuse so much of the code in the different case
15631 * statements, but it's unnecessarily slow to have the switch-case block
15632 * inside the for loops. */
15635 case TNG_CHAR_DATA:
15636 for(i=0; i<n_frames; i++)
15638 if(current_frame_pos == frame_set->n_frames)
15640 stat = tng_frame_set_read_next(tng_data, hash_mode);
15641 if(stat != TNG_SUCCESS)
15645 current_frame_pos = 0;
15647 for(j = 0; j < *n_values_per_frame; j++)
15649 len = strlen(data->strings[current_frame_pos][j]) + 1;
15650 (*values)[i][j].c = malloc(len);
15651 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15653 current_frame_pos++;
15657 size = sizeof(int);
15658 for(i=0; i<n_frames; i++)
15660 if(current_frame_pos == frame_set->n_frames)
15662 stat = tng_frame_set_read_next(tng_data, hash_mode);
15663 if(stat != TNG_SUCCESS)
15667 current_frame_pos = 0;
15669 for(j = 0; j < *n_values_per_frame; j++)
15671 (*values)[i][j].i = *(int *)((char *)data->values + size *
15672 (current_frame_pos *
15673 (*n_values_per_frame) + j));
15675 current_frame_pos++;
15678 case TNG_FLOAT_DATA:
15679 size = sizeof(float);
15680 for(i=0; i<n_frames; i++)
15682 if(current_frame_pos == frame_set->n_frames)
15684 stat = tng_frame_set_read_next(tng_data, hash_mode);
15685 if(stat != TNG_SUCCESS)
15689 current_frame_pos = 0;
15691 for(j = 0; j < *n_values_per_frame; j++)
15693 (*values)[i][j].f = *(float *)((char *)data->values + size *
15694 (current_frame_pos *
15695 (*n_values_per_frame) + j));
15697 current_frame_pos++;
15700 case TNG_DOUBLE_DATA:
15702 size = sizeof(double);
15703 for(i=0; i<n_frames; i++)
15705 if(current_frame_pos == frame_set->n_frames)
15707 stat = tng_frame_set_read_next(tng_data, hash_mode);
15708 if(stat != TNG_SUCCESS)
15712 current_frame_pos = 0;
15714 for(j = 0; j < *n_values_per_frame; j++)
15716 (*values)[i][j].d = *(double *)((char *)data->values + size *
15717 (current_frame_pos *
15718 (*n_values_per_frame) + j));
15720 current_frame_pos++;
15724 data->last_retrieved_frame = end_frame_nr;
15726 return(TNG_SUCCESS);
15729 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15730 (tng_trajectory_t tng_data,
15731 const int64_t block_id,
15732 const int64_t start_frame_nr,
15733 const int64_t end_frame_nr,
15734 const char hash_mode,
15736 int64_t *stride_length,
15737 int64_t *n_values_per_frame,
15740 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15741 int64_t file_pos, current_frame_pos, data_size, frame_size;
15742 int64_t last_frame_pos;
15744 tng_trajectory_frame_set_t frame_set;
15745 tng_non_particle_data_t np_data;
15746 tng_gen_block_t block;
15747 void *current_values = 0, *temp;
15748 tng_function_status stat;
15750 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15751 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15752 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15753 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15754 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15756 frame_set = &tng_data->current_trajectory_frame_set;
15757 first_frame = frame_set->first_frame;
15759 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15760 if(stat != TNG_SUCCESS)
15765 /* Do not re-read the frame set and only need the requested block. */
15766 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15767 stat = tng_data_find(tng_data, block_id, &np_data);
15768 if(first_frame != frame_set->first_frame ||
15769 stat != TNG_SUCCESS)
15771 tng_block_init(&block);
15772 if(stat != TNG_SUCCESS)
15774 fseeko(tng_data->input_file,
15775 tng_data->current_trajectory_frame_set_input_file_pos,
15777 stat = tng_block_header_read(tng_data, block);
15778 if(stat != TNG_SUCCESS)
15780 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15781 __FILE__, __LINE__);
15785 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15787 file_pos = ftello(tng_data->input_file);
15788 /* Read until next frame set block */
15789 stat = tng_block_header_read(tng_data, block);
15790 while(file_pos < tng_data->input_file_len &&
15791 stat != TNG_CRITICAL &&
15792 block->id != TNG_TRAJECTORY_FRAME_SET &&
15795 if(block->id == block_id)
15797 stat = tng_block_read_next(tng_data, block,
15799 if(stat != TNG_CRITICAL)
15801 file_pos = ftello(tng_data->input_file);
15802 if(file_pos < tng_data->input_file_len)
15804 stat = tng_block_header_read(tng_data, block);
15810 file_pos += block->block_contents_size + block->header_contents_size;
15811 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15812 if(file_pos < tng_data->input_file_len)
15814 stat = tng_block_header_read(tng_data, block);
15818 tng_block_destroy(&block);
15819 if(stat == TNG_CRITICAL)
15821 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15822 file_pos, __FILE__, __LINE__);
15827 stat = tng_data_find(tng_data, block_id, &np_data);
15828 if(stat != TNG_SUCCESS)
15833 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15834 &n_frames, stride_length,
15835 n_values_per_frame, type);
15837 if(stat != TNG_SUCCESS)
15841 free(current_values);
15846 if(n_frames == 1 && n_frames < frame_set->n_frames)
15852 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15857 case TNG_CHAR_DATA:
15858 return(TNG_FAILURE);
15860 size = sizeof(int64_t);
15862 case TNG_FLOAT_DATA:
15863 size = sizeof(float);
15865 case TNG_DOUBLE_DATA:
15867 size = sizeof(double);
15870 n_frames_div = (tot_n_frames % *stride_length) ?
15871 tot_n_frames / *stride_length + 1:
15872 tot_n_frames / *stride_length;
15873 data_size = n_frames_div * size * (*n_values_per_frame);
15875 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15876 size, n_frames_div, data_size);
15878 temp = realloc(*values, data_size);
15881 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15882 data_size, __FILE__, __LINE__);
15885 return(TNG_CRITICAL);
15890 if( n_frames == 1 && n_frames < frame_set->n_frames)
15892 memcpy(*values, current_values, size * (*n_values_per_frame));
15896 current_frame_pos = start_frame_nr - frame_set->first_frame;
15898 frame_size = size * (*n_values_per_frame);
15900 last_frame_pos = tng_min_i64(n_frames,
15901 end_frame_nr - start_frame_nr);
15903 n_frames_div = current_frame_pos / *stride_length;
15904 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15905 last_frame_pos / *stride_length + 1:
15906 last_frame_pos / *stride_length;
15907 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15909 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15910 n_frames_div_2 * frame_size);
15912 current_frame_pos += n_frames - current_frame_pos;
15914 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15916 stat = tng_frame_set_read_next(tng_data, hash_mode);
15917 if(stat != TNG_SUCCESS)
15921 free(current_values);
15928 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15929 &n_frames, stride_length,
15930 n_values_per_frame, type);
15932 if(stat != TNG_SUCCESS)
15936 free(current_values);
15943 last_frame_pos = tng_min_i64(n_frames,
15944 end_frame_nr - current_frame_pos);
15946 n_frames_div = current_frame_pos / *stride_length;
15947 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15948 last_frame_pos / *stride_length + 1:
15949 last_frame_pos / *stride_length;
15950 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15952 memcpy(((char *)*values) + n_frames_div * frame_size,
15954 n_frames_div_2 * frame_size);
15956 current_frame_pos += n_frames;
15962 free(current_values);
15965 np_data->last_retrieved_frame = end_frame_nr;
15967 return(TNG_SUCCESS);
15970 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15971 (tng_trajectory_t tng_data,
15972 const int64_t block_id,
15973 union data_values ****values,
15975 int64_t *n_particles,
15976 int64_t *n_values_per_frame,
15979 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15982 tng_particle_data_t data;
15983 tng_trajectory_frame_set_t frame_set;
15984 tng_gen_block_t block;
15985 char block_type_flag;
15986 tng_function_status stat;
15988 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15989 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15990 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15991 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15992 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15994 frame_set = &tng_data->current_trajectory_frame_set;
15999 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16001 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16003 block_type_flag = TNG_TRAJECTORY_BLOCK;
16007 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16010 tng_block_init(&block);
16011 file_pos = ftello(tng_data->input_file);
16012 /* Read all blocks until next frame set block */
16013 stat = tng_block_header_read(tng_data, block);
16014 while(file_pos < tng_data->input_file_len &&
16015 stat != TNG_CRITICAL &&
16016 block->id != TNG_TRAJECTORY_FRAME_SET &&
16019 /* Use hash by default */
16020 stat = tng_block_read_next(tng_data, block,
16022 if(stat != TNG_CRITICAL)
16024 file_pos = ftello(tng_data->input_file);
16025 if(file_pos < tng_data->input_file_len)
16027 stat = tng_block_header_read(tng_data, block);
16031 tng_block_destroy(&block);
16032 if(stat == TNG_CRITICAL)
16034 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16035 file_pos, __FILE__, __LINE__);
16039 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16041 data = &frame_set->tr_particle_data[i];
16042 if(data->block_id == block_id)
16045 block_type_flag = TNG_TRAJECTORY_BLOCK;
16049 if(block_index < 0)
16051 return(TNG_FAILURE);
16056 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16058 block_type_flag = TNG_TRAJECTORY_BLOCK;
16062 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16066 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16067 tng_data->var_num_atoms_flag)
16069 *n_particles = frame_set->n_particles;
16073 *n_particles = tng_data->n_particles;
16076 *n_frames = tng_max_i64(1, data->n_frames);
16077 *n_values_per_frame = data->n_values_per_frame;
16078 *type = data->datatype;
16082 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16083 *n_particles, *n_values_per_frame,
16087 return(TNG_CRITICAL);
16091 /* It's not very elegant to reuse so much of the code in the different case
16092 * statements, but it's unnecessarily slow to have the switch-case block
16093 * inside the for loops. */
16096 case TNG_CHAR_DATA:
16097 for(i = 0; i < *n_frames; i++)
16099 for(j = 0; j < *n_particles; j++)
16101 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16102 for(k = 0; k < *n_values_per_frame; k++)
16104 len = strlen(data->strings[i][j][k]) + 1;
16105 (*values)[i][mapping][k].c = malloc(len);
16106 strncpy((*values)[i][mapping][k].c,
16107 data->strings[i][j][k], len);
16113 size = sizeof(int);
16114 i_step = (*n_particles) * (*n_values_per_frame);
16115 for(i = 0; i < *n_frames; i++)
16117 for(j = 0; j < *n_particles; j++)
16119 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16120 for(k = 0; k < *n_values_per_frame; k++)
16122 (*values)[i][mapping][k].i = *(int *)
16123 ((char *)data->values + size *
16125 (*n_values_per_frame) + k));
16130 case TNG_FLOAT_DATA:
16131 size = sizeof(float);
16132 i_step = (*n_particles) * (*n_values_per_frame);
16133 for(i = 0; i < *n_frames; i++)
16135 for(j = 0; j < *n_particles; j++)
16137 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16138 for(k = 0; k < *n_values_per_frame; k++)
16140 (*values)[i][mapping][k].f = *(float *)
16141 ((char *)data->values + size *
16143 (*n_values_per_frame) + k));
16148 case TNG_DOUBLE_DATA:
16150 size = sizeof(double);
16151 i_step = (*n_particles) * (*n_values_per_frame);
16152 for(i = 0; i < *n_frames; i++)
16154 for(j = 0; j < *n_particles; j++)
16156 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16157 for(k = 0; k < *n_values_per_frame; k++)
16159 (*values)[i][mapping][k].d = *(double *)
16160 ((char *)data->values + size *
16162 (*n_values_per_frame) + k));
16168 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16170 return(TNG_SUCCESS);
16173 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16174 (tng_trajectory_t tng_data,
16175 const int64_t block_id,
16178 int64_t *stride_length,
16179 int64_t *n_particles,
16180 int64_t *n_values_per_frame,
16183 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16184 int64_t block_index;
16186 tng_particle_data_t data;
16187 tng_trajectory_frame_set_t frame_set;
16188 tng_gen_block_t block;
16190 char block_type_flag;
16191 tng_function_status stat;
16193 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16194 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16195 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16196 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16197 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16199 frame_set = &tng_data->current_trajectory_frame_set;
16204 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16206 tng_block_init(&block);
16207 file_pos = ftello(tng_data->input_file);
16208 /* Read all blocks until next frame set block */
16209 stat = tng_block_header_read(tng_data, block);
16210 while(file_pos < tng_data->input_file_len &&
16211 stat != TNG_CRITICAL &&
16212 block->id != TNG_TRAJECTORY_FRAME_SET &&
16215 /* Use hash by default */
16216 stat = tng_block_read_next(tng_data, block,
16218 if(stat != TNG_CRITICAL)
16220 file_pos = ftello(tng_data->input_file);
16221 if(file_pos < tng_data->input_file_len)
16223 stat = tng_block_header_read(tng_data, block);
16227 tng_block_destroy(&block);
16228 if(stat == TNG_CRITICAL)
16230 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16231 file_pos, __FILE__, __LINE__);
16235 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16237 data = &frame_set->tr_particle_data[i];
16238 if(data->block_id == block_id)
16244 if(block_index < 0)
16246 return(TNG_FAILURE);
16250 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16252 block_type_flag = TNG_TRAJECTORY_BLOCK;
16256 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16259 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16260 tng_data->var_num_atoms_flag)
16262 *n_particles = frame_set->n_particles;
16266 *n_particles = tng_data->n_particles;
16269 *type = data->datatype;
16273 case TNG_CHAR_DATA:
16274 return(TNG_FAILURE);
16276 size = sizeof(int64_t);
16278 case TNG_FLOAT_DATA:
16279 size = sizeof(float);
16281 case TNG_DOUBLE_DATA:
16283 size = sizeof(double);
16286 *n_frames = tng_max_i64(1, data->n_frames);
16287 *n_values_per_frame = data->n_values_per_frame;
16288 *stride_length = data->stride_length;
16290 n_frames_div = (*n_frames % *stride_length) ?
16291 *n_frames / *stride_length + 1:
16292 *n_frames / *stride_length;
16294 data_size = n_frames_div * size * (*n_particles) *
16295 (*n_values_per_frame);
16297 temp = realloc(*values, data_size);
16300 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16301 data_size, __FILE__, __LINE__);
16304 return(TNG_CRITICAL);
16309 if(frame_set->n_mapping_blocks <= 0)
16311 memcpy(*values, data->values, data_size);
16315 i_step = (*n_particles) * (*n_values_per_frame);
16316 for(i = 0; i < *n_frames; i++)
16318 for(j = 0; j < *n_particles; j++)
16320 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16321 memcpy(((char *)*values) + size * (i * i_step + mapping *
16322 (*n_values_per_frame)),
16323 (char *)data->values + size *
16324 (i * i_step + j * (*n_values_per_frame)),
16325 size * (*n_values_per_frame));
16330 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16332 return(TNG_SUCCESS);
16335 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16336 (tng_trajectory_t tng_data,
16337 const int64_t block_id,
16338 const int64_t start_frame_nr,
16339 const int64_t end_frame_nr,
16340 const char hash_mode,
16341 union data_values ****values,
16342 int64_t *n_particles,
16343 int64_t *n_values_per_frame,
16346 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16347 int64_t first_frame, block_index;
16350 tng_particle_data_t data;
16351 tng_trajectory_frame_set_t frame_set;
16352 tng_gen_block_t block;
16353 char block_type_flag;
16354 tng_function_status stat;
16356 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16357 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16358 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16359 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16360 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16364 frame_set = &tng_data->current_trajectory_frame_set;
16365 first_frame = frame_set->first_frame;
16367 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16368 if(stat != TNG_SUCCESS)
16373 /* Do not re-read the frame set. */
16374 if(first_frame != frame_set->first_frame ||
16375 frame_set->n_particle_data_blocks <= 0)
16377 tng_block_init(&block);
16378 file_pos = ftello(tng_data->input_file);
16379 /* Read all blocks until next frame set block */
16380 stat = tng_block_header_read(tng_data, block);
16381 while(file_pos < tng_data->input_file_len &&
16382 stat != TNG_CRITICAL &&
16383 block->id != TNG_TRAJECTORY_FRAME_SET &&
16386 stat = tng_block_read_next(tng_data, block,
16388 if(stat != TNG_CRITICAL)
16390 file_pos = ftello(tng_data->input_file);
16391 if(file_pos < tng_data->input_file_len)
16393 stat = tng_block_header_read(tng_data, block);
16397 tng_block_destroy(&block);
16398 if(stat == TNG_CRITICAL)
16400 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16401 file_pos, __FILE__, __LINE__);
16406 /* See if there is already a data block of this ID.
16407 * Start checking the last read frame set */
16408 for(i = frame_set->n_particle_data_blocks; i-- ;)
16410 data = &frame_set->tr_particle_data[i];
16411 if(data->block_id == block_id)
16414 block_type_flag = TNG_TRAJECTORY_BLOCK;
16419 if(block_index < 0)
16421 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16422 block_id, __FILE__, __LINE__);
16423 return(TNG_FAILURE);
16426 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16427 tng_data->var_num_atoms_flag)
16429 *n_particles = frame_set->n_particles;
16433 *n_particles = tng_data->n_particles;
16436 n_frames = end_frame_nr - start_frame_nr + 1;
16437 *n_values_per_frame = data->n_values_per_frame;
16438 *type = data->datatype;
16442 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16443 *n_particles, *n_values_per_frame,
16447 return(TNG_CRITICAL);
16451 current_frame_pos = start_frame_nr - frame_set->first_frame;
16452 /* It's not very elegant to reuse so much of the code in the different case
16453 * statements, but it's unnecessarily slow to have the switch-case block
16454 * inside the for loops. */
16457 case TNG_CHAR_DATA:
16458 for(i=0; i<n_frames; i++)
16460 if(current_frame_pos == frame_set->n_frames)
16462 stat = tng_frame_set_read_next(tng_data, hash_mode);
16463 if(stat != TNG_SUCCESS)
16467 current_frame_pos = 0;
16469 for(j = 0; j < *n_particles; j++)
16471 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16472 for(k = 0; k < *n_values_per_frame; k++)
16474 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16475 (*values)[i][mapping][k].c = malloc(len);
16476 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16479 current_frame_pos++;
16483 size = sizeof(int);
16484 i_step = (*n_particles) * (*n_values_per_frame);
16485 for(i=0; i<n_frames; i++)
16487 if(current_frame_pos == frame_set->n_frames)
16489 stat = tng_frame_set_read_next(tng_data, hash_mode);
16490 if(stat != TNG_SUCCESS)
16494 current_frame_pos = 0;
16496 for(j = 0; j < *n_particles; j++)
16498 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16499 for(k = 0; k < *n_values_per_frame; k++)
16501 (*values)[i][mapping][k].i = *(int *)
16502 ((char *)data->values + size *
16503 (current_frame_pos *
16505 (*n_values_per_frame) + k));
16508 current_frame_pos++;
16511 case TNG_FLOAT_DATA:
16512 size = sizeof(float);
16513 i_step = (*n_particles) * (*n_values_per_frame);
16514 for(i=0; i<n_frames; i++)
16516 if(current_frame_pos == frame_set->n_frames)
16518 stat = tng_frame_set_read_next(tng_data, hash_mode);
16519 if(stat != TNG_SUCCESS)
16523 current_frame_pos = 0;
16525 for(j=0; j<*n_particles; j++)
16527 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16528 for(k=0; k<*n_values_per_frame; k++)
16530 (*values)[i][mapping][k].f = *(float *)
16531 ((char *)data->values + size *
16532 (current_frame_pos *
16534 (*n_values_per_frame) + k));
16537 current_frame_pos++;
16540 case TNG_DOUBLE_DATA:
16542 size = sizeof(double);
16543 i_step = (*n_particles) * (*n_values_per_frame);
16544 for(i=0; i<n_frames; i++)
16546 if(current_frame_pos == frame_set->n_frames)
16548 stat = tng_frame_set_read_next(tng_data, hash_mode);
16549 if(stat != TNG_SUCCESS)
16553 current_frame_pos = 0;
16555 for(j=0; j<*n_particles; j++)
16557 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16558 for(k=0; k<*n_values_per_frame; k++)
16560 (*values)[i][mapping][k].d = *(double *)
16561 ((char *)data->values + size *
16562 (current_frame_pos *
16564 (*n_values_per_frame) + k));
16567 current_frame_pos++;
16571 data->last_retrieved_frame = end_frame_nr;
16573 return(TNG_SUCCESS);
16576 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16577 (tng_trajectory_t tng_data,
16578 const int64_t block_id,
16579 const int64_t start_frame_nr,
16580 const int64_t end_frame_nr,
16581 const char hash_mode,
16583 int64_t *n_particles,
16584 int64_t *stride_length,
16585 int64_t *n_values_per_frame,
16588 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16589 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16591 tng_trajectory_frame_set_t frame_set;
16592 tng_particle_data_t p_data;
16593 tng_gen_block_t block;
16594 void *current_values = 0, *temp;
16595 tng_function_status stat;
16597 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16598 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16599 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16600 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16601 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16602 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16604 frame_set = &tng_data->current_trajectory_frame_set;
16605 first_frame = frame_set->first_frame;
16607 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16608 if(stat != TNG_SUCCESS)
16613 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16614 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16615 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16616 if(first_frame != frame_set->first_frame ||
16617 stat != TNG_SUCCESS)
16619 tng_block_init(&block);
16620 if(stat != TNG_SUCCESS)
16622 fseeko(tng_data->input_file,
16623 tng_data->current_trajectory_frame_set_input_file_pos,
16625 stat = tng_block_header_read(tng_data, block);
16626 if(stat != TNG_SUCCESS)
16628 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16629 __FILE__, __LINE__);
16633 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16635 file_pos = ftello(tng_data->input_file);
16636 /* Read until next frame set block */
16637 stat = tng_block_header_read(tng_data, block);
16638 while(file_pos < tng_data->input_file_len &&
16639 stat != TNG_CRITICAL &&
16640 block->id != TNG_TRAJECTORY_FRAME_SET &&
16643 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16645 stat = tng_block_read_next(tng_data, block,
16647 if(stat != TNG_CRITICAL)
16649 file_pos = ftello(tng_data->input_file);
16650 if(file_pos < tng_data->input_file_len)
16652 stat = tng_block_header_read(tng_data, block);
16658 file_pos += block->block_contents_size + block->header_contents_size;
16659 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16660 if(file_pos < tng_data->input_file_len)
16662 stat = tng_block_header_read(tng_data, block);
16666 tng_block_destroy(&block);
16667 if(stat == TNG_CRITICAL)
16669 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16670 file_pos, __FILE__, __LINE__);
16674 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16675 if(stat != TNG_SUCCESS)
16680 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16681 &n_frames, stride_length, n_particles,
16682 n_values_per_frame, type);
16684 if(stat != TNG_SUCCESS || *n_particles == 0)
16688 free(current_values);
16693 if(n_frames == 1 && n_frames < frame_set->n_frames)
16699 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16704 case TNG_CHAR_DATA:
16705 return(TNG_FAILURE);
16707 size = sizeof(int64_t);
16709 case TNG_FLOAT_DATA:
16710 size = sizeof(float);
16712 case TNG_DOUBLE_DATA:
16714 size = sizeof(double);
16717 n_frames_div = (tot_n_frames % *stride_length) ?
16718 tot_n_frames / *stride_length + 1:
16719 tot_n_frames / *stride_length;
16721 data_size = n_frames_div * size * (*n_particles) *
16722 (*n_values_per_frame);
16724 temp = realloc(*values, data_size);
16727 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16728 data_size, __FILE__, __LINE__);
16731 return(TNG_CRITICAL);
16736 if( n_frames == 1 && n_frames < frame_set->n_frames)
16738 memcpy(*values, current_values, size * (*n_particles) *
16739 (*n_values_per_frame));
16743 current_frame_pos = start_frame_nr - frame_set->first_frame;
16745 frame_size = size * (*n_particles) * (*n_values_per_frame);
16747 last_frame_pos = tng_min_i64(n_frames,
16748 end_frame_nr - start_frame_nr);
16750 n_frames_div = current_frame_pos / *stride_length;
16751 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16752 last_frame_pos / *stride_length + 1:
16753 last_frame_pos / *stride_length;
16754 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16756 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16757 n_frames_div_2 * frame_size);
16759 current_frame_pos += n_frames - current_frame_pos;
16761 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16763 stat = tng_frame_set_read_next(tng_data, hash_mode);
16764 if(stat != TNG_SUCCESS)
16768 free(current_values);
16775 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16776 &n_frames, stride_length, n_particles,
16777 n_values_per_frame, type);
16779 if(stat != TNG_SUCCESS)
16783 free(current_values);
16790 last_frame_pos = tng_min_i64(n_frames,
16791 end_frame_nr - current_frame_pos);
16793 n_frames_div = current_frame_pos / *stride_length;
16794 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16795 last_frame_pos / *stride_length + 1:
16796 last_frame_pos / *stride_length;
16797 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16799 memcpy(((char *)*values) + n_frames_div * frame_size,
16801 n_frames_div_2 * frame_size);
16803 current_frame_pos += n_frames;
16809 free(current_values);
16812 p_data->last_retrieved_frame = end_frame_nr;
16814 return(TNG_SUCCESS);
16817 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16818 (const tng_trajectory_t tng_data,
16819 const int64_t block_id,
16821 int64_t *stride_length)
16823 tng_function_status stat;
16824 tng_non_particle_data_t np_data;
16825 tng_particle_data_t p_data;
16826 int64_t orig_file_pos, file_pos;
16827 int is_particle_data;
16829 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16836 stat = tng_frame_set_of_frame_find(tng_data, frame);
16837 if(stat != TNG_SUCCESS)
16842 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16843 stat = tng_data_find(tng_data, block_id, &np_data);
16844 if(stat != TNG_SUCCESS)
16846 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16847 if(stat != TNG_SUCCESS)
16849 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16850 /* If no specific frame was required read until this data block is found */
16853 file_pos = ftello(tng_data->input_file);
16854 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16856 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16857 file_pos = ftello(tng_data->input_file);
16860 if(stat != TNG_SUCCESS)
16862 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16866 stat = tng_data_find(tng_data, block_id, &np_data);
16867 if(stat != TNG_SUCCESS)
16869 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16870 if(stat != TNG_SUCCESS)
16872 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16878 is_particle_data = 1;
16883 is_particle_data = 0;
16888 is_particle_data = 1;
16893 is_particle_data = 0;
16895 if(is_particle_data)
16897 *stride_length = p_data->stride_length;
16901 *stride_length = np_data->stride_length;
16903 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16905 return(TNG_SUCCESS);
16908 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16909 (const tng_trajectory_t tng_data,
16912 struct tm *time_data;
16915 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16916 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16918 secs = tng_data->time;
16920 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16921 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16922 "%4d-%02d-%02d %02d:%02d:%02d",
16923 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16924 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16926 return(TNG_SUCCESS);
16930 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16931 (const char *filename,
16933 tng_trajectory_t *tng_data_p)
16935 tng_function_status stat;
16937 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16939 if(mode != 'r' && mode != 'w' && mode != 'a')
16941 return(TNG_FAILURE);
16944 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16946 tng_trajectory_destroy(tng_data_p);
16947 return(TNG_CRITICAL);
16950 if(mode == 'r' || mode == 'a')
16952 tng_input_file_set(*tng_data_p, filename);
16954 /* Read the file headers */
16955 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16957 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16959 if(stat != TNG_SUCCESS)
16967 tng_output_file_set(*tng_data_p, filename);
16969 else if(mode == 'a')
16971 if((*tng_data_p)->output_file)
16973 fclose((*tng_data_p)->output_file);
16975 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
16976 fseeko((*tng_data_p)->input_file,
16977 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16980 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16981 if(stat != TNG_SUCCESS)
16983 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16984 __FILE__, __LINE__);
16986 (*tng_data_p)->output_file = 0;
16988 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16989 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16990 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16991 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16992 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16993 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16994 if((*tng_data_p)->input_file)
16996 fclose((*tng_data_p)->input_file);
16997 (*tng_data_p)->input_file = 0;
16999 if((*tng_data_p)->input_file_path)
17001 free((*tng_data_p)->input_file_path);
17002 (*tng_data_p)->input_file_path = 0;
17004 tng_output_append_file_set(*tng_data_p, filename);
17006 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
17009 return(TNG_SUCCESS);
17012 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
17013 (tng_trajectory_t *tng_data_p)
17015 tng_trajectory_frame_set_t frame_set;
17017 if(tng_data_p == 0)
17019 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
17020 __FILE__, __LINE__);
17021 return(TNG_FAILURE);
17024 if(*tng_data_p == 0)
17026 return(TNG_SUCCESS);
17029 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
17031 if(frame_set->n_unwritten_frames > 0)
17033 frame_set->n_frames = frame_set->n_unwritten_frames;
17034 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
17037 return(tng_trajectory_destroy(tng_data_p));
17040 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
17041 (tng_trajectory_t tng_data,
17042 const int64_t frame_nr,
17045 int64_t first_frame;
17046 tng_trajectory_frame_set_t frame_set;
17047 tng_function_status stat;
17049 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17050 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
17052 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
17053 if(stat != TNG_SUCCESS)
17055 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
17056 frame_nr, __FILE__, __LINE__);
17060 frame_set = &tng_data->current_trajectory_frame_set;
17061 first_frame = frame_set->first_frame;
17063 if(tng_data->time_per_frame <= 0)
17065 return(TNG_FAILURE);
17068 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
17070 return(TNG_SUCCESS);
17074 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17075 (tng_trajectory_t tng_data,
17077 int64_t **molecule_cnt_list,
17078 tng_molecule_t *mols)
17080 tng_trajectory_frame_set_t frame_set;
17082 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17083 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17085 *n_mols = tng_data->n_molecules;
17087 frame_set = &tng_data->current_trajectory_frame_set;
17088 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17090 *molecule_cnt_list = frame_set->molecule_cnt_list;
17094 *molecule_cnt_list = tng_data->molecule_cnt_list;
17097 *mols = tng_data->molecules;
17099 return(TNG_SUCCESS);
17103 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17104 (tng_trajectory_t tng_data,
17107 tng_molecule_t *mol)
17109 tng_function_status stat;
17111 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17112 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17114 stat = tng_molecule_add(tng_data, name, mol);
17115 if(stat != TNG_SUCCESS)
17119 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17124 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17125 (tng_trajectory_t tng_data,
17126 const tng_molecule_t mol,
17127 int64_t *n_particles,
17132 char ***chain_names,
17133 int64_t **chain_ids)
17141 *n_particles = mol->n_atoms;
17143 *names = malloc(sizeof(char *) * *n_particles);
17144 *types = malloc(sizeof(char *) * *n_particles);
17145 *res_names = malloc(sizeof(char *) * *n_particles);
17146 *chain_names = malloc(sizeof(char *) * *n_particles);
17147 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17148 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17150 for(i = 0; i < *n_particles; i++)
17152 atom = &mol->atoms[i];
17153 res = atom->residue;
17154 chain = res->chain;
17155 (*names)[i] = malloc(strlen(atom->name));
17156 strcpy(*names[i], atom->name);
17157 (*types)[i] = malloc(strlen(atom->atom_type));
17158 strcpy(*types[i], atom->atom_type);
17159 (*res_names)[i] = malloc(strlen(res->name));
17160 strcpy(*res_names[i], res->name);
17161 (*chain_names)[i] = malloc(strlen(chain->name));
17162 strcpy(*chain_names[i], chain->name);
17163 (*res_ids)[i] = res->id;
17164 (*chain_ids)[i] = chain->id;
17167 return(TNG_SUCCESS);
17170 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17171 (tng_trajectory_t tng_data,
17172 tng_molecule_t mol,
17173 const int64_t n_particles,
17174 const char **names,
17175 const char **types,
17176 const char **res_names,
17177 const int64_t *res_ids,
17178 const char **chain_names,
17179 const int64_t *chain_ids)
17183 tng_residue_t residue;
17185 tng_function_status stat;
17187 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17188 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17189 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17190 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17191 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17192 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17193 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17195 for(i = 0; i < n_particles; i++)
17197 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17198 &chain) == TNG_FAILURE)
17200 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17202 if(stat != TNG_SUCCESS)
17207 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17208 &residue) == TNG_FAILURE)
17210 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17212 if(stat != TNG_SUCCESS)
17217 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17218 if(stat != TNG_SUCCESS)
17223 return(TNG_SUCCESS);
17226 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17227 (tng_trajectory_t tng_data,
17228 float **positions, int64_t *stride_length)
17230 int64_t n_frames, n_particles, n_values_per_frame;
17232 tng_function_status stat;
17234 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17235 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17236 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17238 stat = tng_num_frames_get(tng_data, &n_frames);
17239 if(stat != TNG_SUCCESS)
17244 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17245 0, n_frames - 1, TNG_USE_HASH,
17246 (void **)positions,
17249 &n_values_per_frame,
17255 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17256 (tng_trajectory_t tng_data,
17257 float **velocities, int64_t *stride_length)
17259 int64_t n_frames, n_particles, n_values_per_frame;
17261 tng_function_status stat;
17263 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17264 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17265 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17267 stat = tng_num_frames_get(tng_data, &n_frames);
17268 if(stat != TNG_SUCCESS)
17273 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17274 0, n_frames - 1, TNG_USE_HASH,
17275 (void **)velocities,
17278 &n_values_per_frame,
17284 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17285 (tng_trajectory_t tng_data,
17286 float **forces, int64_t *stride_length)
17288 int64_t n_frames, n_particles, n_values_per_frame;
17290 tng_function_status stat;
17292 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17293 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17294 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17296 stat = tng_num_frames_get(tng_data, &n_frames);
17297 if(stat != TNG_SUCCESS)
17302 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17303 0, n_frames - 1, TNG_USE_HASH,
17307 &n_values_per_frame,
17313 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17314 (tng_trajectory_t tng_data,
17316 int64_t *stride_length)
17318 int64_t n_frames, n_values_per_frame;
17320 tng_function_status stat;
17322 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17323 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17324 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17326 stat = tng_num_frames_get(tng_data, &n_frames);
17327 if(stat != TNG_SUCCESS)
17332 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17333 0, n_frames - 1, TNG_USE_HASH,
17334 (void **)box_shape,
17336 &n_values_per_frame,
17342 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17343 (tng_trajectory_t tng_data,
17344 const int64_t block_id,
17347 int64_t *retrieved_frame_number,
17348 double *retrieved_time)
17350 tng_trajectory_frame_set_t frame_set;
17351 tng_particle_data_t data = 0;
17352 tng_function_status stat;
17354 int64_t i, data_size, n_particles, file_pos;
17357 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17358 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17359 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17360 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17361 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17363 frame_set = &tng_data->current_trajectory_frame_set;
17365 stat = tng_particle_data_find(tng_data, block_id, &data);
17366 if(stat != TNG_SUCCESS)
17368 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17369 file_pos = ftello(tng_data->input_file);
17370 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17372 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17373 file_pos = ftello(tng_data->input_file);
17375 if(stat != TNG_SUCCESS)
17379 stat = tng_particle_data_find(tng_data, block_id, &data);
17380 if(stat != TNG_SUCCESS)
17385 if(data->last_retrieved_frame < 0)
17387 fseeko(tng_data->input_file,
17388 tng_data->first_trajectory_frame_set_input_file_pos,
17390 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17391 if(stat != TNG_SUCCESS)
17395 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17396 if(stat != TNG_SUCCESS)
17401 i = data->first_frame_with_data;
17405 if(data->n_frames == 1)
17407 i = data->last_retrieved_frame + 1;
17411 i = data->last_retrieved_frame + data->stride_length;
17413 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17415 stat = tng_frame_set_of_frame_find(tng_data, i);
17416 if(stat != TNG_SUCCESS)
17418 /* If the frame set search found the frame set after the starting
17419 * frame set there is a gap in the frame sets. So, even if the frame
17420 * was not found the next frame with data is still in the found
17422 if(stat == TNG_CRITICAL)
17426 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17428 return(TNG_FAILURE);
17430 i = frame_set->first_frame;
17433 if(data->last_retrieved_frame < frame_set->first_frame)
17435 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17436 if(stat != TNG_SUCCESS)
17442 data->last_retrieved_frame = i;
17443 *retrieved_frame_number = i;
17444 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17446 *retrieved_time = frame_set->first_frame_time +
17447 (i - frame_set->first_frame) *
17448 tng_data->time_per_frame;
17452 *retrieved_time = 0;
17455 if(data->stride_length > 1)
17457 i = (i - data->first_frame_with_data) / data->stride_length;
17461 i = (i - frame_set->first_frame);
17464 tng_num_particles_get(tng_data, &n_particles);
17466 *data_type = data->datatype;
17470 case TNG_CHAR_DATA:
17471 return(TNG_FAILURE);
17473 size = sizeof(int64_t);
17475 case TNG_FLOAT_DATA:
17476 size = sizeof(float);
17478 case TNG_DOUBLE_DATA:
17480 size = sizeof(double);
17483 data_size = size * n_particles * data->n_values_per_frame;
17485 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17486 // i, data_size, size, n_particles, data->n_values_per_frame);
17488 temp = realloc(*values, data_size);
17491 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17492 data_size, __FILE__, __LINE__);
17495 return(TNG_CRITICAL);
17500 memcpy(*values, (char *)data->values + i * data_size, data_size);
17502 return(TNG_SUCCESS);
17505 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17506 (tng_trajectory_t tng_data,
17507 const int64_t block_id,
17510 int64_t *retrieved_frame_number,
17511 double *retrieved_time)
17513 tng_trajectory_frame_set_t frame_set;
17514 tng_non_particle_data_t data = 0;
17515 tng_function_status stat;
17517 int64_t i, data_size, file_pos;
17520 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17521 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17522 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17523 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17524 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17526 frame_set = &tng_data->current_trajectory_frame_set;
17528 stat = tng_data_find(tng_data, block_id, &data);
17529 if(stat != TNG_SUCCESS)
17531 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17532 file_pos = ftello(tng_data->input_file);
17533 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17535 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17536 file_pos = ftello(tng_data->input_file);
17538 if(stat != TNG_SUCCESS)
17542 stat = tng_data_find(tng_data, block_id, &data);
17543 if(stat != TNG_SUCCESS)
17548 if(data->last_retrieved_frame < 0)
17550 fseeko(tng_data->input_file,
17551 tng_data->first_trajectory_frame_set_input_file_pos,
17553 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17554 if(stat != TNG_SUCCESS)
17558 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17559 if(stat != TNG_SUCCESS)
17564 i = data->first_frame_with_data;
17568 if(data->n_frames == 1)
17570 i = data->last_retrieved_frame + 1;
17574 i = data->last_retrieved_frame + data->stride_length;
17576 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17578 stat = tng_frame_set_of_frame_find(tng_data, i);
17579 if(stat != TNG_SUCCESS)
17581 /* If the frame set search found the frame set after the starting
17582 * frame set there is a gap in the frame sets. So, even if the frame
17583 * was not found the next frame with data is still in the found
17585 if(stat == TNG_CRITICAL)
17589 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17591 return(TNG_FAILURE);
17593 i = frame_set->first_frame;
17596 if(data->last_retrieved_frame < frame_set->first_frame)
17598 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17599 if(stat != TNG_SUCCESS)
17605 data->last_retrieved_frame = i;
17606 *retrieved_frame_number = i;
17607 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17609 *retrieved_time = frame_set->first_frame_time +
17610 (i - frame_set->first_frame) *
17611 tng_data->time_per_frame;
17615 *retrieved_time = 0;
17618 if(data->stride_length > 1)
17620 i = (i - data->first_frame_with_data) / data->stride_length;
17624 i = (i - frame_set->first_frame);
17627 *data_type = data->datatype;
17631 case TNG_CHAR_DATA:
17632 return(TNG_FAILURE);
17634 size = sizeof(int64_t);
17636 case TNG_FLOAT_DATA:
17637 size = sizeof(float);
17639 case TNG_DOUBLE_DATA:
17641 size = sizeof(double);
17644 data_size = size * data->n_values_per_frame;
17646 temp = realloc(*values, data_size);
17649 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17650 data_size, __FILE__, __LINE__);
17653 return(TNG_CRITICAL);
17658 memcpy(*values, (char *)data->values + i * data_size, data_size);
17660 return(TNG_SUCCESS);
17663 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17664 (tng_trajectory_t tng_data,
17665 const int64_t first_frame,
17666 const int64_t last_frame,
17668 int64_t *stride_length)
17670 int64_t n_particles, n_values_per_frame;
17672 tng_function_status stat;
17674 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17675 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17676 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17677 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17679 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17680 first_frame, last_frame,
17682 (void **)positions,
17685 &n_values_per_frame,
17691 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17692 (tng_trajectory_t tng_data,
17693 const int64_t first_frame,
17694 const int64_t last_frame,
17695 float **velocities,
17696 int64_t *stride_length)
17698 int64_t n_particles, n_values_per_frame;
17700 tng_function_status stat;
17702 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17703 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17704 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17705 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17707 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17708 first_frame, last_frame,
17710 (void **)velocities,
17713 &n_values_per_frame,
17719 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17720 (tng_trajectory_t tng_data,
17721 const int64_t first_frame,
17722 const int64_t last_frame,
17724 int64_t *stride_length)
17726 int64_t n_particles, n_values_per_frame;
17728 tng_function_status stat;
17730 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17731 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17732 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17733 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17735 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17736 first_frame, last_frame,
17741 &n_values_per_frame,
17747 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17748 (tng_trajectory_t tng_data,
17749 const int64_t first_frame,
17750 const int64_t last_frame,
17752 int64_t *stride_length)
17754 int64_t n_values_per_frame;
17756 tng_function_status stat;
17758 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17759 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17760 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17761 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17763 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17764 first_frame, last_frame,
17766 (void **)box_shape,
17768 &n_values_per_frame,
17774 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17775 (tng_trajectory_t tng_data,
17777 const int64_t n_values_per_frame,
17778 const int64_t block_id,
17779 const char *block_name,
17780 const char particle_dependency,
17781 const char compression)
17783 tng_trajectory_frame_set_t frame_set;
17784 tng_particle_data_t p_data;
17785 tng_non_particle_data_t np_data;
17786 int64_t n_particles, n_frames;
17787 tng_function_status stat;
17789 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17790 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17794 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17795 i, __FILE__, __LINE__);
17796 return(TNG_FAILURE);
17799 frame_set = &tng_data->current_trajectory_frame_set;
17801 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17803 n_frames = tng_data->frame_set_n_frames;
17805 stat = tng_frame_set_new(tng_data, 0, n_frames);
17806 if(stat != TNG_SUCCESS)
17808 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17815 n_frames = frame_set->n_frames;
17818 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17820 tng_num_particles_get(tng_data, &n_particles);
17821 if(n_particles <= 0)
17823 return(TNG_FAILURE);
17826 if(tng_particle_data_find(tng_data, block_id, &p_data)
17829 stat = tng_particle_data_block_add(tng_data, block_id,
17832 TNG_TRAJECTORY_BLOCK,
17833 n_frames, n_values_per_frame, i,
17836 if(stat != TNG_SUCCESS)
17838 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17839 __FILE__, __LINE__);
17842 p_data = &frame_set->tr_particle_data[frame_set->
17843 n_particle_data_blocks - 1];
17844 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17846 n_values_per_frame);
17847 if(stat != TNG_SUCCESS)
17849 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17850 __FILE__, __LINE__);
17856 if(p_data->stride_length != i)
17858 p_data->stride_length = i;
17859 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17861 n_values_per_frame);
17862 if(stat != TNG_SUCCESS)
17864 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17865 __FILE__, __LINE__);
17873 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17875 stat = tng_data_block_add(tng_data, block_id, block_name,
17876 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17877 n_frames, n_values_per_frame,
17878 i, compression, 0);
17879 if(stat != TNG_SUCCESS)
17881 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17882 __FILE__, __LINE__);
17885 np_data = &frame_set->tr_data[frame_set->
17886 n_data_blocks - 1];
17887 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17888 i, n_values_per_frame);
17889 if(stat != TNG_SUCCESS)
17891 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17892 __FILE__, __LINE__);
17898 if(np_data->stride_length != i)
17900 np_data->stride_length = i;
17901 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17902 i, n_values_per_frame);
17903 if(stat != TNG_SUCCESS)
17905 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17906 __FILE__, __LINE__);
17913 return(TNG_SUCCESS);
17916 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17917 (tng_trajectory_t tng_data,
17919 const int64_t n_values_per_frame,
17920 const int64_t block_id,
17921 const char *block_name,
17922 const char particle_dependency,
17923 const char compression)
17925 tng_trajectory_frame_set_t frame_set;
17926 tng_particle_data_t p_data;
17927 tng_non_particle_data_t np_data;
17928 int64_t n_particles, n_frames;
17929 tng_function_status stat;
17931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17932 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17936 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17937 i, __FILE__, __LINE__);
17938 return(TNG_FAILURE);
17941 frame_set = &tng_data->current_trajectory_frame_set;
17943 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17945 n_frames = tng_data->frame_set_n_frames;
17947 stat = tng_frame_set_new(tng_data, 0, n_frames);
17948 if(stat != TNG_SUCCESS)
17950 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17957 n_frames = frame_set->n_frames;
17960 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17962 tng_num_particles_get(tng_data, &n_particles);
17964 if(n_particles <= 0)
17966 return(TNG_FAILURE);
17969 if(tng_particle_data_find(tng_data, block_id, &p_data)
17972 stat = tng_particle_data_block_add(tng_data, block_id,
17975 TNG_TRAJECTORY_BLOCK,
17976 n_frames, n_values_per_frame, i,
17979 if(stat != TNG_SUCCESS)
17981 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17982 __FILE__, __LINE__);
17985 p_data = &frame_set->tr_particle_data[frame_set->
17986 n_particle_data_blocks - 1];
17987 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17989 n_values_per_frame);
17990 if(stat != TNG_SUCCESS)
17992 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17993 __FILE__, __LINE__);
17999 p_data->stride_length = i;
18004 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18006 stat = tng_data_block_add(tng_data, block_id, block_name,
18007 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
18008 n_frames, n_values_per_frame,
18009 i, compression, 0);
18010 if(stat != TNG_SUCCESS)
18012 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18013 __FILE__, __LINE__);
18016 np_data = &frame_set->tr_data[frame_set->
18017 n_data_blocks - 1];
18018 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18019 i, n_values_per_frame);
18020 if(stat != TNG_SUCCESS)
18022 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18023 __FILE__, __LINE__);
18029 np_data->stride_length = i;
18033 return(TNG_SUCCESS);
18036 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
18037 (tng_trajectory_t tng_data,
18039 const int64_t n_values_per_frame,
18040 const int64_t block_id,
18041 const char *block_name,
18042 const char particle_dependency,
18043 const char compression)
18045 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
18046 "See documentation. %s: %d", __FILE__, __LINE__);
18047 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
18048 block_id, block_name,
18049 particle_dependency,
18052 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18053 (tng_trajectory_t tng_data,
18056 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18057 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18059 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18060 TNG_TRAJ_POSITIONS,
18062 TNG_PARTICLE_BLOCK_DATA,
18063 TNG_TNG_COMPRESSION));
18066 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18067 (tng_trajectory_t tng_data,
18070 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18071 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18073 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18074 TNG_TRAJ_POSITIONS,
18076 TNG_PARTICLE_BLOCK_DATA,
18077 TNG_TNG_COMPRESSION));
18080 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18081 (tng_trajectory_t tng_data,
18084 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18085 "See documentation. %s: %d", __FILE__, __LINE__);
18086 return(tng_util_pos_write_interval_set(tng_data, i));
18089 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18090 (tng_trajectory_t tng_data,
18093 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18094 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18096 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18097 TNG_TRAJ_VELOCITIES,
18099 TNG_PARTICLE_BLOCK_DATA,
18100 TNG_TNG_COMPRESSION));
18103 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18104 (tng_trajectory_t tng_data,
18107 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18108 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18110 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18111 TNG_TRAJ_VELOCITIES,
18113 TNG_PARTICLE_BLOCK_DATA,
18114 TNG_TNG_COMPRESSION));
18117 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18118 (tng_trajectory_t tng_data,
18121 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18122 "See documentation. %s: %d", __FILE__, __LINE__);
18123 return(tng_util_vel_write_interval_set(tng_data, i));
18126 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18127 (tng_trajectory_t tng_data,
18130 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18131 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18133 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18136 TNG_PARTICLE_BLOCK_DATA,
18137 TNG_GZIP_COMPRESSION));
18140 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18141 (tng_trajectory_t tng_data,
18144 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18145 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18147 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18150 TNG_PARTICLE_BLOCK_DATA,
18151 TNG_GZIP_COMPRESSION));
18154 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18155 (tng_trajectory_t tng_data,
18158 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18159 "See documentation. %s: %d", __FILE__, __LINE__);
18160 return(tng_util_force_write_interval_set(tng_data, i));
18163 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18164 (tng_trajectory_t tng_data,
18167 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18168 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18170 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18171 TNG_TRAJ_BOX_SHAPE,
18173 TNG_NON_PARTICLE_BLOCK_DATA,
18174 TNG_GZIP_COMPRESSION));
18177 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18178 (tng_trajectory_t tng_data,
18181 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18182 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18184 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18185 TNG_TRAJ_BOX_SHAPE,
18187 TNG_NON_PARTICLE_BLOCK_DATA,
18188 TNG_GZIP_COMPRESSION));
18191 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18192 (tng_trajectory_t tng_data,
18195 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18196 "See documentation. %s: %d", __FILE__, __LINE__);
18197 return(tng_util_box_shape_write_interval_set(tng_data, i));
18200 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18201 (tng_trajectory_t tng_data,
18202 const int64_t frame_nr,
18203 const float *values,
18204 const int64_t n_values_per_frame,
18205 const int64_t block_id,
18206 const char *block_name,
18207 const char particle_dependency,
18208 const char compression)
18210 tng_trajectory_frame_set_t frame_set;
18211 tng_particle_data_t p_data;
18212 tng_non_particle_data_t np_data;
18213 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18214 int64_t last_frame;
18215 int is_first_frame_flag = 0;
18216 char block_type_flag;
18217 tng_function_status stat;
18219 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18220 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18221 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18223 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18225 tng_num_particles_get(tng_data, &n_particles);
18226 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18231 return(TNG_FAILURE);
18234 frame_set = &tng_data->current_trajectory_frame_set;
18238 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18239 n_frames = stride_length = 1;
18243 block_type_flag = TNG_TRAJECTORY_BLOCK;
18245 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18247 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18248 if(stat != TNG_SUCCESS)
18250 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18255 last_frame = frame_set->first_frame +
18256 frame_set->n_frames - 1;
18257 if(frame_nr > last_frame)
18259 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18260 if(stat != TNG_SUCCESS)
18262 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18266 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18268 last_frame = frame_nr - 1;
18270 stat = tng_frame_set_new(tng_data, last_frame + 1,
18271 tng_data->frame_set_n_frames);
18272 if(stat != TNG_SUCCESS)
18274 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18279 if(frame_set->n_unwritten_frames == 0)
18281 is_first_frame_flag = 1;
18283 frame_set->n_unwritten_frames = frame_nr -
18284 frame_set->first_frame + 1;
18286 n_frames = frame_set->n_frames;
18289 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18291 if(tng_particle_data_find(tng_data, block_id, &p_data)
18294 stat = tng_particle_data_block_add(tng_data, block_id,
18298 n_frames, n_values_per_frame,
18302 if(stat != TNG_SUCCESS)
18304 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18305 __FILE__, __LINE__);
18308 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18310 p_data = &frame_set->tr_particle_data[frame_set->
18311 n_particle_data_blocks - 1];
18315 p_data = &tng_data->non_tr_particle_data[tng_data->
18316 n_particle_data_blocks - 1];
18318 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18319 stride_length, n_particles,
18320 n_values_per_frame);
18321 if(stat != TNG_SUCCESS)
18323 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18324 __FILE__, __LINE__);
18329 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18331 stride_length = p_data->stride_length;
18333 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18335 p_data->first_frame_with_data = frame_nr;
18340 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18343 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18344 n_values_per_frame, values, sizeof(float) *
18345 n_particles * n_values_per_frame);
18349 memcpy(p_data->values, values, sizeof(float) * n_particles *
18350 n_values_per_frame);
18355 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18357 stat = tng_data_block_add(tng_data, block_id, block_name,
18358 TNG_FLOAT_DATA, block_type_flag,
18359 n_frames, n_values_per_frame,
18360 stride_length, compression, 0);
18361 if(stat != TNG_SUCCESS)
18363 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18364 __FILE__, __LINE__);
18367 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18369 np_data = &frame_set->tr_data[frame_set->
18370 n_data_blocks - 1];
18374 np_data = &tng_data->non_tr_data[tng_data->
18375 n_data_blocks - 1];
18377 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18378 stride_length, n_values_per_frame);
18379 if(stat != TNG_SUCCESS)
18381 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18382 __FILE__, __LINE__);
18387 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18389 stride_length = np_data->stride_length;
18391 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18393 np_data->first_frame_with_data = frame_nr;
18398 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18401 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18402 n_values_per_frame, values, sizeof(float) *
18403 n_values_per_frame);
18407 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18411 return(TNG_SUCCESS);
18414 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18415 (tng_trajectory_t tng_data,
18416 const int64_t frame_nr,
18417 const double *values,
18418 const int64_t n_values_per_frame,
18419 const int64_t block_id,
18420 const char *block_name,
18421 const char particle_dependency,
18422 const char compression)
18424 tng_trajectory_frame_set_t frame_set;
18425 tng_particle_data_t p_data;
18426 tng_non_particle_data_t np_data;
18427 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18428 int64_t last_frame;
18429 int is_first_frame_flag = 0;
18430 char block_type_flag;
18431 tng_function_status stat;
18433 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18434 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18435 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18437 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18439 tng_num_particles_get(tng_data, &n_particles);
18440 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18445 return(TNG_FAILURE);
18448 frame_set = &tng_data->current_trajectory_frame_set;
18452 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18453 n_frames = stride_length = 1;
18457 block_type_flag = TNG_TRAJECTORY_BLOCK;
18459 n_frames = tng_data->frame_set_n_frames;
18461 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18463 stat = tng_frame_set_new(tng_data, 0, n_frames);
18464 if(stat != TNG_SUCCESS)
18466 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18473 n_frames = frame_set->n_frames;
18475 last_frame = frame_set->first_frame +
18476 frame_set->n_frames - 1;
18477 if(frame_nr > last_frame)
18479 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18480 if(stat != TNG_SUCCESS)
18482 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18486 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18488 last_frame = frame_nr - 1;
18490 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18491 if(stat != TNG_SUCCESS)
18493 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18498 if(frame_set->n_unwritten_frames == 0)
18500 is_first_frame_flag = 1;
18502 frame_set->n_unwritten_frames = frame_nr -
18503 frame_set->first_frame + 1;
18506 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18508 if(tng_particle_data_find(tng_data, block_id, &p_data)
18511 stat = tng_particle_data_block_add(tng_data, block_id,
18515 n_frames, n_values_per_frame,
18519 if(stat != TNG_SUCCESS)
18521 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18522 __FILE__, __LINE__);
18525 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18527 p_data = &frame_set->tr_particle_data[frame_set->
18528 n_particle_data_blocks - 1];
18532 p_data = &tng_data->non_tr_particle_data[tng_data->
18533 n_particle_data_blocks - 1];
18535 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18536 stride_length, n_particles,
18537 n_values_per_frame);
18538 if(stat != TNG_SUCCESS)
18540 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18541 __FILE__, __LINE__);
18546 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18548 stride_length = p_data->stride_length;
18550 if(is_first_frame_flag)
18552 p_data->first_frame_with_data = frame_nr;
18557 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18560 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18561 n_values_per_frame, values, sizeof(double) *
18562 n_particles * n_values_per_frame);
18566 memcpy(p_data->values, values, sizeof(double) * n_particles *
18567 n_values_per_frame);
18572 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18574 stat = tng_data_block_add(tng_data, block_id, block_name,
18575 TNG_DOUBLE_DATA, block_type_flag,
18576 n_frames, n_values_per_frame,
18577 stride_length, compression, 0);
18578 if(stat != TNG_SUCCESS)
18580 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18581 __FILE__, __LINE__);
18584 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18586 np_data = &frame_set->tr_data[frame_set->
18587 n_data_blocks - 1];
18591 np_data = &tng_data->non_tr_data[tng_data->
18592 n_data_blocks - 1];
18594 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18595 stride_length, n_values_per_frame);
18596 if(stat != TNG_SUCCESS)
18598 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18599 __FILE__, __LINE__);
18604 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18606 stride_length = np_data->stride_length;
18608 if(is_first_frame_flag)
18610 np_data->first_frame_with_data = frame_nr;
18615 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18618 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18619 n_values_per_frame, values, sizeof(double) *
18620 n_values_per_frame);
18624 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18628 return(TNG_SUCCESS);
18631 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18632 (tng_trajectory_t tng_data,
18633 const int64_t frame_nr,
18634 const float *positions)
18636 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18637 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18638 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18640 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18641 TNG_TRAJ_POSITIONS, "POSITIONS",
18642 TNG_PARTICLE_BLOCK_DATA,
18643 TNG_TNG_COMPRESSION));
18646 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18647 (tng_trajectory_t tng_data,
18648 const int64_t frame_nr,
18649 const double *positions)
18651 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18652 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18653 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18655 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18656 TNG_TRAJ_POSITIONS, "POSITIONS",
18657 TNG_PARTICLE_BLOCK_DATA,
18658 TNG_TNG_COMPRESSION));
18661 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18662 (tng_trajectory_t tng_data,
18663 const int64_t frame_nr,
18664 const float *velocities)
18666 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18667 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18668 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18670 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18671 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18672 TNG_PARTICLE_BLOCK_DATA,
18673 TNG_TNG_COMPRESSION));
18676 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18677 (tng_trajectory_t tng_data,
18678 const int64_t frame_nr,
18679 const double *velocities)
18681 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18682 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18683 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18685 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18686 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18687 TNG_PARTICLE_BLOCK_DATA,
18688 TNG_TNG_COMPRESSION));
18691 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18692 (tng_trajectory_t tng_data,
18693 const int64_t frame_nr,
18694 const float *forces)
18696 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18697 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18698 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18700 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18701 TNG_TRAJ_FORCES, "FORCES",
18702 TNG_PARTICLE_BLOCK_DATA,
18703 TNG_GZIP_COMPRESSION));
18706 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18707 (tng_trajectory_t tng_data,
18708 const int64_t frame_nr,
18709 const double *forces)
18711 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18712 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18713 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18715 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18716 TNG_TRAJ_FORCES, "FORCES",
18717 TNG_PARTICLE_BLOCK_DATA,
18718 TNG_GZIP_COMPRESSION));
18721 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18722 (tng_trajectory_t tng_data,
18723 const int64_t frame_nr,
18724 const float *box_shape)
18726 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18727 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18728 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18730 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18731 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18732 TNG_NON_PARTICLE_BLOCK_DATA,
18733 TNG_GZIP_COMPRESSION));
18736 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18737 (tng_trajectory_t tng_data,
18738 const int64_t frame_nr,
18739 const double *box_shape)
18741 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18742 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18743 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18745 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18746 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18747 TNG_NON_PARTICLE_BLOCK_DATA,
18748 TNG_GZIP_COMPRESSION));
18751 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18752 (tng_trajectory_t tng_data,
18753 const int64_t frame_nr,
18755 const float *values,
18756 const int64_t n_values_per_frame,
18757 const int64_t block_id,
18758 const char *block_name,
18759 const char particle_dependency,
18760 const char compression)
18762 tng_trajectory_frame_set_t frame_set;
18763 tng_function_status stat;
18765 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18766 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18767 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18768 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18770 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18771 block_id, block_name,
18772 particle_dependency,
18775 if(stat != TNG_SUCCESS)
18780 frame_set = &tng_data->current_trajectory_frame_set;
18782 /* first_frame_time is -1 when it is not yet set. */
18783 if(frame_set->first_frame_time < -0.1)
18785 if(frame_nr > frame_set->first_frame)
18787 stat = tng_frame_set_first_frame_time_set(tng_data,
18790 frame_set->first_frame) *
18791 tng_data->time_per_frame);
18795 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18801 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18802 (tng_trajectory_t tng_data,
18803 const int64_t frame_nr,
18805 const double *values,
18806 const int64_t n_values_per_frame,
18807 const int64_t block_id,
18808 const char *block_name,
18809 const char particle_dependency,
18810 const char compression)
18812 tng_trajectory_frame_set_t frame_set;
18813 tng_function_status stat;
18815 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18816 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18817 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18818 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18820 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18821 block_id, block_name,
18822 particle_dependency,
18825 if(stat != TNG_SUCCESS)
18830 frame_set = &tng_data->current_trajectory_frame_set;
18832 /* first_frame_time is -1 when it is not yet set. */
18833 if(frame_set->first_frame_time < -0.1)
18835 if(frame_nr > frame_set->first_frame)
18837 stat = tng_frame_set_first_frame_time_set(tng_data,
18840 frame_set->first_frame) *
18841 tng_data->time_per_frame);
18845 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18851 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18852 (tng_trajectory_t tng_data,
18853 const int64_t frame_nr,
18855 const float *positions)
18857 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18858 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18859 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18860 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18862 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18863 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18864 TNG_PARTICLE_BLOCK_DATA,
18865 TNG_TNG_COMPRESSION));
18868 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18869 (tng_trajectory_t tng_data,
18870 const int64_t frame_nr,
18872 const double *positions)
18874 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18875 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18876 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18877 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18879 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18881 TNG_TRAJ_POSITIONS,
18883 TNG_PARTICLE_BLOCK_DATA,
18884 TNG_TNG_COMPRESSION));
18887 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18888 (tng_trajectory_t tng_data,
18889 const int64_t frame_nr,
18891 const float *velocities)
18893 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18894 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18895 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18896 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18898 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18900 TNG_TRAJ_VELOCITIES,
18902 TNG_PARTICLE_BLOCK_DATA,
18903 TNG_TNG_COMPRESSION));
18906 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18907 (tng_trajectory_t tng_data,
18908 const int64_t frame_nr,
18910 const double *velocities)
18912 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18913 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18914 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18915 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18917 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18919 TNG_TRAJ_VELOCITIES,
18921 TNG_PARTICLE_BLOCK_DATA,
18922 TNG_TNG_COMPRESSION));
18925 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18926 (tng_trajectory_t tng_data,
18927 const int64_t frame_nr,
18929 const float *forces)
18931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18932 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18933 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18934 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18936 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18937 3, TNG_TRAJ_FORCES, "FORCES",
18938 TNG_PARTICLE_BLOCK_DATA,
18939 TNG_GZIP_COMPRESSION));
18942 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18943 (tng_trajectory_t tng_data,
18944 const int64_t frame_nr,
18946 const double *forces)
18948 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18949 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18950 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18951 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18953 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18955 TNG_TRAJ_FORCES, "FORCES",
18956 TNG_PARTICLE_BLOCK_DATA,
18957 TNG_GZIP_COMPRESSION));
18960 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18961 (tng_trajectory_t tng_data,
18962 const int64_t frame_nr,
18964 const float *box_shape)
18966 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18967 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18968 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18969 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18971 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18972 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18973 TNG_NON_PARTICLE_BLOCK_DATA,
18974 TNG_GZIP_COMPRESSION));
18977 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18978 (tng_trajectory_t tng_data,
18979 const int64_t frame_nr,
18981 const double *box_shape)
18983 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18984 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18985 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18986 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18988 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18989 time, box_shape, 9,
18990 TNG_TRAJ_BOX_SHAPE,
18992 TNG_NON_PARTICLE_BLOCK_DATA,
18993 TNG_GZIP_COMPRESSION));
18996 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18997 (tng_trajectory_t tng_data,
18998 const int64_t block_id,
19002 tng_trajectory_frame_set_t frame_set;
19003 tng_particle_data_t p_data = 0;
19004 tng_non_particle_data_t np_data = 0;
19005 tng_function_status stat;
19007 int block_type = -1;
19009 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19010 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
19011 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
19013 frame_set = &tng_data->current_trajectory_frame_set;
19015 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19016 if(stat == TNG_SUCCESS)
19018 block_type = TNG_PARTICLE_BLOCK_DATA;
19022 stat = tng_data_find(tng_data, block_id, &np_data);
19023 if(stat == TNG_SUCCESS)
19025 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19029 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19030 if(stat != TNG_SUCCESS)
19034 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19035 if(stat == TNG_SUCCESS)
19037 block_type = TNG_PARTICLE_BLOCK_DATA;
19041 stat = tng_data_find(tng_data, block_id, &np_data);
19042 if(stat == TNG_SUCCESS)
19044 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19053 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19055 if(p_data->last_retrieved_frame < 0)
19057 i = p_data->first_frame_with_data;
19061 i = p_data->last_retrieved_frame;
19064 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19066 if(np_data->last_retrieved_frame < 0)
19068 i = np_data->first_frame_with_data;
19072 i = np_data->last_retrieved_frame;
19077 return(TNG_FAILURE);
19079 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
19081 stat = tng_frame_set_of_frame_find(tng_data, i);
19082 if(stat != TNG_SUCCESS)
19086 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19087 if(stat != TNG_SUCCESS)
19089 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19090 __FILE__, __LINE__);
19094 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19096 *codec_id = p_data->codec_id;
19097 *factor = p_data->compression_multiplier;
19099 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19101 *codec_id = np_data->codec_id;
19102 *factor = np_data->compression_multiplier;
19104 return(TNG_SUCCESS);
19107 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19108 (tng_trajectory_t tng_data,
19109 int64_t current_frame,
19110 const int64_t n_requested_data_block_ids,
19111 const int64_t *requested_data_block_ids,
19112 int64_t *next_frame,
19113 int64_t *n_data_blocks_in_next_frame,
19114 int64_t **data_block_ids_in_next_frame)
19116 tng_trajectory_frame_set_t frame_set;
19117 tng_function_status stat;
19118 tng_particle_data_t p_data;
19119 tng_non_particle_data_t np_data;
19120 tng_gen_block_t block;
19121 int64_t i, j, block_id, *temp;
19122 int64_t data_frame, frame_diff, min_diff;
19123 int64_t size, frame_set_file_pos, file_pos;
19124 int found, read_all = 0;
19126 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19127 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19128 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19129 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19131 if(n_requested_data_block_ids)
19133 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.");
19134 size = sizeof(int64_t) * n_requested_data_block_ids;
19135 temp = realloc(*data_block_ids_in_next_frame, size);
19138 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19139 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19140 __FILE__, __LINE__);
19141 free(*data_block_ids_in_next_frame);
19142 *data_block_ids_in_next_frame = 0;
19143 return(TNG_CRITICAL);
19145 *data_block_ids_in_next_frame = temp;
19148 frame_set = &tng_data->current_trajectory_frame_set;
19150 current_frame += 1;
19152 if(current_frame < frame_set->first_frame ||
19153 current_frame >= frame_set->first_frame + frame_set->n_frames)
19155 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19156 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19157 if(stat != TNG_SUCCESS)
19159 /* If the frame set search found the frame set after the starting
19160 * frame set there is a gap in the frame sets. So, even if the frame
19161 * was not found the next frame with data is still in the found
19163 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19164 frame_set_file_pos)
19168 current_frame = frame_set->first_frame;
19172 /* Check for data blocks only if they have not already been found. */
19173 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19175 file_pos = ftello(tng_data->input_file);
19176 if(file_pos < tng_data->input_file_len)
19178 tng_block_init(&block);
19179 stat = tng_block_header_read(tng_data, block);
19180 while(file_pos < tng_data->input_file_len &&
19181 stat != TNG_CRITICAL &&
19182 block->id != TNG_TRAJECTORY_FRAME_SET &&
19185 stat = tng_block_read_next(tng_data, block,
19187 if(stat != TNG_CRITICAL)
19189 file_pos = ftello(tng_data->input_file);
19190 if(file_pos < tng_data->input_file_len)
19192 stat = tng_block_header_read(tng_data, block);
19196 tng_block_destroy(&block);
19197 if(stat == TNG_CRITICAL)
19199 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
19200 file_pos, __FILE__, __LINE__);
19209 *n_data_blocks_in_next_frame = 0;
19211 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19213 p_data = &frame_set->tr_particle_data[i];
19214 block_id = p_data->block_id;
19216 if(n_requested_data_block_ids > 0)
19219 for(j = 0; j < n_requested_data_block_ids; j++)
19221 if(block_id == requested_data_block_ids[j])
19233 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19234 p_data->last_retrieved_frame >=
19235 frame_set->first_frame + frame_set->n_frames))
19237 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19238 TNG_USE_HASH, block_id);
19239 if(stat == TNG_CRITICAL)
19241 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19242 __FILE__, __LINE__);
19245 if(stat == TNG_FAILURE)
19250 if(frame_set->first_frame != current_frame &&
19251 p_data->last_retrieved_frame >= 0)
19253 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19257 data_frame = p_data->first_frame_with_data;
19259 frame_diff = data_frame - current_frame;
19264 if(min_diff == -1 || frame_diff <= min_diff)
19266 if(frame_diff < min_diff)
19268 *n_data_blocks_in_next_frame = 1;
19272 *n_data_blocks_in_next_frame += 1;
19274 if(n_requested_data_block_ids <= 0)
19276 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19277 temp = realloc(*data_block_ids_in_next_frame, size);
19280 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19281 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19282 __FILE__, __LINE__);
19283 free(*data_block_ids_in_next_frame);
19284 *data_block_ids_in_next_frame = 0;
19285 return(TNG_CRITICAL);
19287 *data_block_ids_in_next_frame = temp;
19291 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19293 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19295 min_diff = frame_diff;
19298 for(i = 0; i < frame_set->n_data_blocks; i++)
19300 np_data = &frame_set->tr_data[i];
19301 block_id = np_data->block_id;
19303 if(n_requested_data_block_ids > 0)
19306 for(j = 0; j < n_requested_data_block_ids; j++)
19308 if(block_id == requested_data_block_ids[j])
19320 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19321 np_data->last_retrieved_frame >=
19322 frame_set->first_frame + frame_set->n_frames))
19324 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19325 TNG_USE_HASH, block_id);
19326 if(stat == TNG_CRITICAL)
19328 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19329 __FILE__, __LINE__);
19332 if(stat == TNG_FAILURE)
19337 if(frame_set->first_frame != current_frame &&
19338 np_data->last_retrieved_frame >= 0)
19340 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19344 data_frame = np_data->first_frame_with_data;
19346 frame_diff = data_frame - current_frame;
19351 if(min_diff == -1 || frame_diff <= min_diff)
19353 if(frame_diff < min_diff)
19355 *n_data_blocks_in_next_frame = 1;
19359 *n_data_blocks_in_next_frame += 1;
19361 if(n_requested_data_block_ids <= 0)
19363 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19364 temp = realloc(*data_block_ids_in_next_frame, size);
19367 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19368 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19369 __FILE__, __LINE__);
19370 free(*data_block_ids_in_next_frame);
19371 *data_block_ids_in_next_frame = 0;
19372 return(TNG_CRITICAL);
19374 *data_block_ids_in_next_frame = temp;
19378 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19380 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19382 min_diff = frame_diff;
19387 return(TNG_FAILURE);
19389 *next_frame = current_frame + min_diff;
19391 return(TNG_SUCCESS);
19395 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19396 (tng_trajectory_t tng_data,
19397 int64_t *n_data_blocks,
19398 int64_t **data_block_ids,
19399 char ***data_block_names,
19400 int64_t **stride_lengths,
19401 int64_t **n_values_per_frame,
19402 char **block_types,
19403 char **dependencies,
19404 char **compressions)
19406 tng_gen_block_t block;
19407 int64_t orig_file_pos, file_pos;
19409 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19410 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19411 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19412 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19413 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19415 orig_file_pos = ftello(tng_data->input_file);
19417 if(!tng_data->input_file_len)
19419 fseeko(tng_data->input_file, 0, SEEK_END);
19420 tng_data->input_file_len = ftello(tng_data->input_file);
19423 fseeko(tng_data->input_file, 0, SEEK_SET);
19426 *n_data_blocks = 0;
19428 tng_block_init(&block);
19430 while(file_pos < tng_data->input_file_len &&
19431 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19433 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19437 file_pos += (block->block_contents_size + block->header_contents_size);
19438 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
19441 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
19443 return(TNG_SUCCESS);
19446 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19447 (tng_trajectory_t tng_data,
19448 const int64_t prev_frame)
19450 tng_function_status stat;
19451 FILE *temp = tng_data->input_file;
19453 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19454 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19456 tng_data->input_file = tng_data->output_file;
19458 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19459 if(stat != TNG_SUCCESS)
19464 tng_data->current_trajectory_frame_set_output_file_pos =
19465 tng_data->current_trajectory_frame_set_input_file_pos;
19467 tng_data->input_file = temp;
19469 return(TNG_SUCCESS);