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_vel);
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.");
5686 /* This must be caught early to avoid creating a data block if not necessary. */
5688 if(codec_id == TNG_GZIP_COMPRESSION)
5690 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
5692 return(TNG_FAILURE);
5702 size = sizeof(int64_t);
5704 case TNG_FLOAT_DATA:
5705 size = sizeof(float);
5707 case TNG_DOUBLE_DATA:
5709 size = sizeof(double);
5712 /* If the block does not exist, create it */
5713 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5715 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5717 block_type_flag = TNG_TRAJECTORY_BLOCK;
5721 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5724 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5727 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5728 __FILE__, __LINE__);
5729 return(TNG_CRITICAL);
5731 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5733 data = &frame_set->tr_particle_data[frame_set->
5734 n_particle_data_blocks - 1];
5738 data = &tng_data->non_tr_particle_data[tng_data->
5739 n_particle_data_blocks - 1];
5741 data->block_id = block->id;
5743 data->block_name = malloc(strlen(block->name) + 1);
5744 if(!data->block_name)
5746 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5747 (int)strlen(block->name)+1, __FILE__, __LINE__);
5748 return(TNG_CRITICAL);
5750 strcpy(data->block_name, block->name);
5752 data->datatype = datatype;
5755 /* FIXME: Memory leak from strings. */
5758 data->codec_id = codec_id;
5759 data->compression_multiplier = multiplier;
5760 data->last_retrieved_frame = -1;
5763 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5764 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5765 tng_data->var_num_atoms_flag)
5767 tot_n_particles = frame_set->n_particles;
5771 tot_n_particles = tng_data->n_particles;
5774 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5776 if(codec_id != TNG_UNCOMPRESSED)
5778 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5781 case TNG_XTC_COMPRESSION:
5782 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5784 case TNG_TNG_COMPRESSION:
5785 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5786 if(tng_uncompress(tng_data, block, datatype,
5787 block->block_contents + *offset,
5788 data_size) != TNG_SUCCESS)
5790 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5791 __FILE__, __LINE__);
5792 return(TNG_CRITICAL);
5794 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5797 case TNG_GZIP_COMPRESSION:
5798 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5799 if(tng_gzip_uncompress(tng_data, block,
5800 block->block_contents + *offset,
5801 data_size) != TNG_SUCCESS)
5803 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5805 return(TNG_CRITICAL);
5807 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5812 /* Allocate memory */
5813 if(!data->values || data->n_frames != n_frames ||
5814 data->n_values_per_frame != n_values)
5816 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5818 tot_n_particles, n_values) !=
5821 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5822 __FILE__, __LINE__);
5823 return(TNG_CRITICAL);
5827 data->first_frame_with_data = first_frame_with_data;
5829 if(datatype == TNG_CHAR_DATA)
5831 for(i = 0; i < n_frames_div; i++)
5833 first_dim_values = data->strings[i];
5834 for(j = num_first_particle; j < num_first_particle + n_particles;
5837 second_dim_values = first_dim_values[j];
5838 for(k = 0; k < n_values; k++)
5840 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5842 if(second_dim_values[k])
5844 free(second_dim_values[k]);
5846 second_dim_values[k] = malloc(len);
5847 if(!second_dim_values[k])
5849 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5850 len, __FILE__, __LINE__);
5851 return(TNG_CRITICAL);
5853 strncpy(second_dim_values[k],
5854 block->block_contents+*offset, len);
5862 memcpy((char *)data->values + n_frames_div * size * n_values *
5864 block->block_contents + *offset,
5865 block->block_contents_size - *offset);
5868 case TNG_FLOAT_DATA:
5869 if(tng_data->input_endianness_swap_func_32)
5871 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5873 if(tng_data->input_endianness_swap_func_32(tng_data,
5874 (int32_t *)((char *)data->values + i))
5877 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5878 __FILE__, __LINE__);
5884 case TNG_DOUBLE_DATA:
5885 if(tng_data->input_endianness_swap_func_64)
5887 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5889 if(tng_data->input_endianness_swap_func_64(tng_data,
5890 (int64_t *)((char *)data->values + i))
5893 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5894 __FILE__, __LINE__);
5903 return(TNG_SUCCESS);
5906 /** Write a particle data block
5907 * @param tng_data is a trajectory data container.
5908 * @param block is the block to store the data (should already contain
5909 * the block headers and the block contents).
5910 * @param block_index is the index number of the data block in the frame set.
5911 * @param mapping is the particle mapping that is relevant for the data block.
5912 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5913 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5914 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5915 * error has occured.
5917 static tng_function_status tng_particle_data_block_write
5918 (tng_trajectory_t tng_data,
5919 tng_gen_block_t block,
5920 const int64_t block_index,
5921 const tng_particle_mapping_t mapping,
5922 const char hash_mode)
5924 int64_t n_particles, num_first_particle, n_frames, stride_length;
5925 int64_t frame_step, data_start_pos;
5928 size_t len, offset = 0;
5929 char dependency, temp, *temp_name;
5931 char ***first_dim_values, **second_dim_values;
5932 tng_trajectory_frame_set_t frame_set;
5933 tng_function_status stat;
5935 tng_particle_data_t data;
5936 char block_type_flag;
5938 frame_set = &tng_data->current_trajectory_frame_set;
5940 /* If we have already started writing frame sets it is too late to write
5941 * non-trajectory data blocks */
5942 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5944 block_type_flag = TNG_TRAJECTORY_BLOCK;
5948 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5951 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5953 return(TNG_CRITICAL);
5956 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5958 data = &frame_set->tr_particle_data[block_index];
5960 /* If this data block has not had any data added in this frame set
5961 * do not write it. */
5962 if(data->first_frame_with_data < frame_set->first_frame)
5964 return(TNG_SUCCESS);
5967 stride_length = tng_max_i64(1, data->stride_length);
5971 data = &tng_data->non_tr_particle_data[block_index];
5975 switch(data->datatype)
5981 size = sizeof(int64_t);
5983 case TNG_FLOAT_DATA:
5984 size = sizeof(float);
5986 case TNG_DOUBLE_DATA:
5988 size = sizeof(double);
5991 len = strlen(data->block_name) + 1;
5993 if(!block->name || strlen(block->name) < len)
5995 temp_name = realloc(block->name, len);
5998 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5999 __FILE__, __LINE__);
6002 return(TNG_CRITICAL);
6004 block->name = temp_name;
6006 strncpy(block->name, data->block_name, len);
6007 block->id = data->block_id;
6009 /* If writing frame independent data data->n_frames is 0, but n_frames
6010 is used for the loop writing the data (and reserving memory) and needs
6012 n_frames = tng_max_i64(1, data->n_frames);
6014 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6016 /* If the frame set is finished before writing the full number of frames
6017 make sure the data block is not longer than the frame set. */
6018 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6020 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6023 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6024 n_frames / stride_length;
6026 /* TNG compression will use compression precision to get integers from
6027 * floating point data. The compression multiplier stores that information
6028 * to be able to return the precision of the compressed data. */
6029 if(data->codec_id == TNG_TNG_COMPRESSION)
6031 data->compression_multiplier = tng_data->compression_precision;
6033 /* Uncompressed data blocks do not use compression multipliers at all.
6034 * GZip compression does not need it either. */
6035 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6037 data->compression_multiplier = 1.0;
6040 if(mapping && mapping->n_particles != 0)
6042 n_particles = mapping->n_particles;
6043 num_first_particle = mapping->num_first_particle;
6047 num_first_particle = 0;
6048 if(tng_data->var_num_atoms_flag)
6050 n_particles = frame_set->n_particles;
6054 n_particles = tng_data->n_particles;
6058 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6060 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6064 dependency = TNG_PARTICLE_DEPENDENT;
6067 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6068 frame_step, stride_length, num_first_particle,
6069 n_particles, dependency, &data_start_pos,
6070 &block->block_contents_size) != TNG_SUCCESS)
6072 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6073 __FILE__, __LINE__);
6074 return(TNG_CRITICAL);
6077 if(block->block_contents)
6079 free(block->block_contents);
6081 block->block_contents = malloc(block->block_contents_size);
6082 if(!block->block_contents)
6084 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6085 block->block_contents_size, __FILE__, __LINE__);
6086 return(TNG_CRITICAL);
6090 memcpy(block->block_contents, &data->datatype, sizeof(char));
6091 offset += sizeof(char);
6093 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6094 offset += sizeof(char);
6096 if(dependency & TNG_FRAME_DEPENDENT)
6098 if(stride_length > 1)
6106 memcpy(block->block_contents+offset, &temp, sizeof(char));
6107 offset += sizeof(char);
6110 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6111 sizeof(data->n_values_per_frame));
6112 if(tng_data->output_endianness_swap_func_64)
6114 if(tng_data->output_endianness_swap_func_64(tng_data,
6115 (int64_t *)block->header_contents+offset)
6118 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6119 __FILE__, __LINE__);
6122 offset += sizeof(data->n_values_per_frame);
6124 memcpy(block->block_contents+offset, &data->codec_id,
6125 sizeof(data->codec_id));
6126 if(tng_data->output_endianness_swap_func_64)
6128 if(tng_data->output_endianness_swap_func_64(tng_data,
6129 (int64_t *)block->header_contents+offset)
6132 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6133 __FILE__, __LINE__);
6136 offset += sizeof(data->codec_id);
6138 if(data->codec_id != TNG_UNCOMPRESSED)
6140 memcpy(block->block_contents+offset, &data->compression_multiplier,
6141 sizeof(data->compression_multiplier));
6142 if(tng_data->output_endianness_swap_func_64)
6144 if(tng_data->output_endianness_swap_func_64(tng_data,
6145 (int64_t *)block->header_contents+offset)
6148 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6149 __FILE__, __LINE__);
6152 offset += sizeof(data->compression_multiplier);
6155 if(data->n_frames > 0 && stride_length > 1)
6157 /* FIXME: first_frame_with_data is not reliably set */
6158 if(data->first_frame_with_data == 0)
6160 data->first_frame_with_data = frame_set->first_frame;
6162 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6163 sizeof(data->first_frame_with_data));
6164 if(tng_data->output_endianness_swap_func_64)
6166 if(tng_data->output_endianness_swap_func_64(tng_data,
6167 (int64_t *)block->header_contents+offset)
6170 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6171 __FILE__, __LINE__);
6174 offset += sizeof(data->first_frame_with_data);
6176 memcpy(block->block_contents+offset, &stride_length,
6177 sizeof(stride_length));
6178 if(tng_data->output_endianness_swap_func_64)
6180 if(tng_data->output_endianness_swap_func_64(tng_data,
6181 (int64_t *)block->header_contents+offset)
6184 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6185 __FILE__, __LINE__);
6188 offset += sizeof(stride_length);
6192 memcpy(block->block_contents+offset, &num_first_particle,
6193 sizeof(num_first_particle));
6194 if(tng_data->output_endianness_swap_func_64)
6196 if(tng_data->output_endianness_swap_func_64(tng_data,
6197 (int64_t *)block->header_contents+offset)
6200 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6201 __FILE__, __LINE__);
6204 offset += sizeof(num_first_particle);
6206 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
6207 if(tng_data->output_endianness_swap_func_64)
6209 if(tng_data->output_endianness_swap_func_64(tng_data,
6210 (int64_t *)block->header_contents+offset)
6213 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6214 __FILE__, __LINE__);
6217 offset += sizeof(n_particles);
6219 if(data->datatype == TNG_CHAR_DATA)
6223 for(i = 0; i < frame_step; i++)
6225 first_dim_values = data->strings[i];
6226 for(j = num_first_particle; j < num_first_particle + n_particles;
6229 second_dim_values = first_dim_values[j];
6230 for(k = 0; k < data->n_values_per_frame; k++)
6232 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6233 strncpy(block->block_contents+offset,
6234 second_dim_values[k], len);
6241 else if(data->values)
6243 memcpy(block->block_contents + offset, data->values,
6244 block->block_contents_size - offset);
6246 switch(data->datatype)
6248 case TNG_FLOAT_DATA:
6249 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6250 data->codec_id == TNG_TNG_COMPRESSION)
6252 if(tng_data->input_endianness_swap_func_32)
6254 for(i = offset; i < block->block_contents_size; i+=size)
6256 if(tng_data->input_endianness_swap_func_32(tng_data,
6257 (int32_t *)(block->block_contents + i))
6260 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6261 __FILE__, __LINE__);
6268 multiplier = data->compression_multiplier;
6269 if(fabs(multiplier - 1.0) > 0.00001 ||
6270 tng_data->input_endianness_swap_func_32)
6272 for(i = offset; i < block->block_contents_size; i+=size)
6274 *(float *)(block->block_contents + i) *= (float)multiplier;
6275 if(tng_data->input_endianness_swap_func_32 &&
6276 tng_data->input_endianness_swap_func_32(tng_data,
6277 (int32_t *)(block->block_contents + i))
6280 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6281 __FILE__, __LINE__);
6288 if(tng_data->input_endianness_swap_func_64)
6290 for(i = offset; i < block->block_contents_size; i+=size)
6292 if(tng_data->input_endianness_swap_func_64(tng_data,
6293 (int64_t *)(block->block_contents + i))
6296 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6297 __FILE__, __LINE__);
6302 case TNG_DOUBLE_DATA:
6303 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6304 data->codec_id == TNG_TNG_COMPRESSION)
6306 if(tng_data->input_endianness_swap_func_64)
6308 for(i = offset; i < block->block_contents_size; i+=size)
6310 if(tng_data->input_endianness_swap_func_64(tng_data,
6311 (int64_t *)(block->block_contents + i))
6314 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6315 __FILE__, __LINE__);
6322 multiplier = data->compression_multiplier;
6323 if(fabs(multiplier - 1.0) > 0.00001 ||
6324 tng_data->input_endianness_swap_func_64)
6326 for(i = offset; i < block->block_contents_size; i+=size)
6328 *(double *)(block->block_contents + i) *= multiplier;
6329 if(tng_data->input_endianness_swap_func_64 &&
6330 tng_data->input_endianness_swap_func_64(tng_data,
6331 (int64_t *)(block->block_contents + i))
6334 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6335 __FILE__, __LINE__);
6347 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6350 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6351 frame_set->n_unwritten_frames = 0;
6353 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6355 switch(data->codec_id)
6357 case TNG_XTC_COMPRESSION:
6358 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6359 data->codec_id = TNG_UNCOMPRESSED;
6361 case TNG_TNG_COMPRESSION:
6362 stat = tng_compress(tng_data, block, frame_step,
6363 n_particles, data->datatype,
6364 block->block_contents + data_start_pos);
6365 if(stat != TNG_SUCCESS)
6367 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6368 __FILE__, __LINE__);
6369 if(stat == TNG_CRITICAL)
6371 return(TNG_CRITICAL);
6373 /* Set the data again, but with no compression (to write only
6374 * the relevant data) */
6375 data->codec_id = TNG_UNCOMPRESSED;
6376 stat = tng_particle_data_block_write(tng_data, block,
6377 block_index, mapping,
6383 case TNG_GZIP_COMPRESSION:
6384 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6385 stat = tng_gzip_compress(tng_data, block,
6386 block->block_contents + data_start_pos,
6387 block->block_contents_size - data_start_pos);
6388 if(stat != TNG_SUCCESS)
6390 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6392 if(stat == TNG_CRITICAL)
6394 return(TNG_CRITICAL);
6396 /* Set the data again, but with no compression (to write only
6397 * the relevant data) */
6398 data->codec_id = TNG_UNCOMPRESSED;
6399 stat = tng_particle_data_block_write(tng_data, block,
6400 block_index, mapping,
6404 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6410 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6412 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6413 tng_data->output_file_path, __FILE__, __LINE__);
6414 return(TNG_CRITICAL);
6417 if(fwrite(block->block_contents, block->block_contents_size, 1,
6418 tng_data->output_file) != 1)
6420 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6422 return(TNG_CRITICAL);
6425 return(TNG_SUCCESS);
6429 /** Create a non-particle data block
6430 * @param tng_data is a trajectory data container.
6431 * @param block_type_flag specifies if this is a trajectory block or a
6432 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6433 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6434 * error has occured.
6436 static tng_function_status tng_data_block_create
6437 (tng_trajectory_t tng_data,
6438 const char block_type_flag)
6440 tng_trajectory_frame_set_t frame_set =
6441 &tng_data->current_trajectory_frame_set;
6443 tng_non_particle_data_t data;
6445 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6447 frame_set->n_data_blocks++;
6448 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6449 frame_set->n_data_blocks);
6452 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6453 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6454 __FILE__, __LINE__);
6455 free(frame_set->tr_data);
6456 frame_set->tr_data = 0;
6457 return(TNG_CRITICAL);
6459 frame_set->tr_data = data;
6463 tng_data->n_data_blocks++;
6464 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6465 tng_data->n_data_blocks);
6468 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6469 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6470 __FILE__, __LINE__);
6471 free(tng_data->non_tr_data);
6472 tng_data->non_tr_data = 0;
6473 return(TNG_CRITICAL);
6475 tng_data->non_tr_data = data;
6478 return(TNG_SUCCESS);
6482 /** Allocate memory for storing non-particle data.
6483 * The allocated block will be refered to by data->values.
6484 * @param tng_data is a trajectory data container.
6485 * @param data is the data struct, which will contain the allocated memory in
6487 * @param n_frames is the number of frames of data to store.
6488 * @param n_values_per_frame is the number of data values per frame.
6489 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6490 * error has occured.
6492 static tng_function_status tng_allocate_data_mem
6493 (tng_trajectory_t tng_data,
6494 tng_non_particle_data_t data,
6496 int64_t stride_length,
6497 const int64_t n_values_per_frame)
6500 int64_t i, j, size, frame_alloc;
6503 if(n_values_per_frame == 0)
6505 return(TNG_FAILURE);
6508 if(data->strings && data->datatype == TNG_CHAR_DATA)
6510 for(i = 0; i < data->n_frames; i++)
6512 for(j = 0; j < data->n_values_per_frame; j++)
6514 if(data->strings[i][j])
6516 free(data->strings[i][j]);
6517 data->strings[i][j] = 0;
6520 free(data->strings[i]);
6521 data->strings[i] = 0;
6523 free(data->strings);
6525 data->n_frames = n_frames;
6526 data->stride_length = tng_max_i64(1, stride_length);
6527 n_frames = tng_max_i64(1, n_frames);
6528 data->n_values_per_frame = n_values_per_frame;
6529 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6531 if(data->datatype == TNG_CHAR_DATA)
6533 data->strings = malloc(sizeof(char **) * frame_alloc);
6534 for(i = 0; i < frame_alloc; i++)
6536 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6537 if(!data->strings[i])
6539 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6541 __FILE__, __LINE__);
6542 return(TNG_CRITICAL);
6544 for(j = 0; j < n_values_per_frame; j++)
6546 data->strings[i][j] = 0;
6552 switch(data->datatype)
6555 size = sizeof(int64_t);
6557 case TNG_FLOAT_DATA:
6558 size = sizeof(float);
6560 case TNG_DOUBLE_DATA:
6562 size = sizeof(double);
6565 values = realloc(data->values,
6566 size * frame_alloc *
6567 n_values_per_frame);
6570 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6571 size * frame_alloc *
6573 __FILE__, __LINE__);
6576 return(TNG_CRITICAL);
6578 data->values = values;
6581 return(TNG_SUCCESS);
6584 /** Read the values of a non-particle data block
6585 * @param tng_data is a trajectory data container.
6586 * @param block is the block to store the data (should already contain
6587 * the block headers and the block contents).
6588 * @param offset is the reading offset to point at the place where the actual
6589 * values are stored, starting from the beginning of the block_contents. The
6590 * offset is changed during the reading.
6591 * @param datatype is the type of data of the data block (char, int, float or
6593 * @param first_frame_with_data is the frame number of the first frame with data
6594 * in this data block.
6595 * @param stride_length is the number of frames between each data entry.
6596 * @param n_frames is the number of frames in this data block.
6597 * @param n_values is the number of values per frame stored in this data block.
6598 * @param codec_id is the ID of the codec to compress the data.
6599 * @param multiplier is the multiplication factor applied to each data value
6600 * before compression. This factor is applied since some compression algorithms
6601 * work only on integers.
6602 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6603 * error has occured.
6605 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6606 tng_gen_block_t block,
6608 const char datatype,
6609 const int64_t first_frame_with_data,
6610 const int64_t stride_length,
6612 const int64_t n_values,
6613 const int64_t codec_id,
6614 const double multiplier)
6616 int64_t i, j, n_frames_div;
6621 tng_non_particle_data_t data;
6622 tng_trajectory_frame_set_t frame_set =
6623 &tng_data->current_trajectory_frame_set;
6624 char block_type_flag;
6626 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6628 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6630 /* This must be caught early to avoid creating a data block if not necessary. */
6632 if(codec_id == TNG_GZIP_COMPRESSION)
6634 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
6636 return(TNG_FAILURE);
6646 size = sizeof(int64_t);
6648 case TNG_FLOAT_DATA:
6649 size = sizeof(float);
6651 case TNG_DOUBLE_DATA:
6653 size = sizeof(double);
6656 /* If the block does not exist, create it */
6657 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6659 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6661 block_type_flag = TNG_TRAJECTORY_BLOCK;
6665 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6668 if(tng_data_block_create(tng_data, block_type_flag) !=
6671 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6672 __FILE__, __LINE__);
6673 return(TNG_CRITICAL);
6675 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6677 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6681 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6683 data->block_id = block->id;
6685 data->block_name = malloc(strlen(block->name) + 1);
6686 if(!data->block_name)
6688 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6689 (int)strlen(block->name)+1, __FILE__, __LINE__);
6690 return(TNG_CRITICAL);
6692 strcpy(data->block_name, block->name);
6694 data->datatype = datatype;
6697 /* FIXME: Memory leak from strings. */
6700 data->codec_id = codec_id;
6701 data->compression_multiplier = multiplier;
6702 data->last_retrieved_frame = -1;
6705 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6707 if(codec_id != TNG_UNCOMPRESSED)
6712 case TNG_GZIP_COMPRESSION:
6713 data_size = n_frames_div * size * n_values;
6714 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6715 if(tng_gzip_uncompress(tng_data, block,
6716 block->block_contents + *offset,
6717 data_size) != TNG_SUCCESS)
6719 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6721 return(TNG_CRITICAL);
6723 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6729 /* Allocate memory */
6730 if(!data->values || data->n_frames != n_frames ||
6731 data->n_values_per_frame != n_values)
6733 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6737 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6738 __FILE__, __LINE__);
6739 return(TNG_CRITICAL);
6743 data->first_frame_with_data = first_frame_with_data;
6745 if(datatype == TNG_CHAR_DATA)
6747 for(i = 0; i < n_frames_div; i++)
6749 for(j = 0; j < n_values; j++)
6751 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6753 if(data->strings[i][j])
6755 free(data->strings[i][j]);
6757 data->strings[i][j] = malloc(len);
6758 if(!data->strings[i][j])
6760 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6761 len, __FILE__, __LINE__);
6762 return(TNG_CRITICAL);
6764 strncpy(data->strings[i][j], block->block_contents+*offset,
6772 memcpy(data->values, block->block_contents + *offset,
6773 block->block_contents_size - *offset);
6776 case TNG_FLOAT_DATA:
6777 if(tng_data->input_endianness_swap_func_32)
6779 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6781 if(tng_data->input_endianness_swap_func_32(tng_data,
6782 (int32_t *)((char *)data->values + i))
6785 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6786 __FILE__, __LINE__);
6792 case TNG_DOUBLE_DATA:
6793 if(tng_data->input_endianness_swap_func_64)
6795 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6797 if(tng_data->input_endianness_swap_func_64(tng_data,
6798 (int64_t *)((char *)data->values + i))
6801 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6802 __FILE__, __LINE__);
6811 return(TNG_SUCCESS);
6814 /** Write a non-particle data block
6815 * @param tng_data is a trajectory data container.
6816 * @param block is the block to store the data (should already contain
6817 * the block headers and the block contents).
6818 * @param block_index is the index number of the data block in the frame set.
6819 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6820 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6821 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6822 * error has occured.
6824 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6825 tng_gen_block_t block,
6826 const int64_t block_index,
6827 const char hash_mode)
6829 int64_t n_frames, stride_length, frame_step, data_start_pos;
6831 int offset = 0, size;
6834 tng_function_status stat;
6836 char temp, dependency, *temp_name;
6838 tng_trajectory_frame_set_t frame_set =
6839 &tng_data->current_trajectory_frame_set;
6841 tng_non_particle_data_t data;
6842 char block_type_flag;
6844 /* If we have already started writing frame sets it is too late to write
6845 * non-trajectory data blocks */
6846 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6848 block_type_flag = TNG_TRAJECTORY_BLOCK;
6852 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6855 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6857 return(TNG_CRITICAL);
6860 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6862 data = &frame_set->tr_data[block_index];
6864 /* If this data block has not had any data added in this frame set
6865 * do not write it. */
6866 if(data->first_frame_with_data < frame_set->first_frame)
6868 return(TNG_SUCCESS);
6871 stride_length = tng_max_i64(1, data->stride_length);
6875 data = &tng_data->non_tr_data[block_index];
6879 switch(data->datatype)
6885 size = sizeof(int64_t);
6887 case TNG_FLOAT_DATA:
6888 size = sizeof(float);
6890 case TNG_DOUBLE_DATA:
6892 size = sizeof(double);
6895 len = (unsigned int)strlen(data->block_name) + 1;
6897 if(!block->name || strlen(block->name) < len)
6899 temp_name = realloc(block->name, len);
6902 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6903 __FILE__, __LINE__);
6906 return(TNG_CRITICAL);
6908 block->name = temp_name;
6910 strncpy(block->name, data->block_name, len);
6911 block->id = data->block_id;
6913 /* If writing frame independent data data->n_frames is 0, but n_frames
6914 is used for the loop writing the data (and reserving memory) and needs
6916 n_frames = tng_max_i64(1, data->n_frames);
6918 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6920 /* If the frame set is finished before writing the full number of frames
6921 make sure the data block is not longer than the frame set. */
6922 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6924 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6927 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6928 n_frames / stride_length;
6930 /* TNG compression will use compression precision to get integers from
6931 * floating point data. The compression multiplier stores that information
6932 * to be able to return the precision of the compressed data. */
6933 if(data->codec_id == TNG_TNG_COMPRESSION)
6935 data->compression_multiplier = tng_data->compression_precision;
6937 /* Uncompressed data blocks do not use compression multipliers at all.
6938 * GZip compression does not need it either. */
6939 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6941 data->compression_multiplier = 1.0;
6944 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6946 dependency = TNG_FRAME_DEPENDENT;
6953 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6954 frame_step, stride_length, 0,
6955 1, dependency, &data_start_pos,
6956 &block->block_contents_size) != TNG_SUCCESS)
6958 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6959 __FILE__, __LINE__);
6960 return(TNG_CRITICAL);
6963 if(block->block_contents)
6965 free(block->block_contents);
6967 block->block_contents = malloc(block->block_contents_size);
6968 if(!block->block_contents)
6970 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6971 block->block_contents_size, __FILE__, __LINE__);
6972 return(TNG_CRITICAL);
6976 memcpy(block->block_contents, &data->datatype, sizeof(char));
6977 offset += sizeof(char);
6979 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6980 offset += sizeof(char);
6982 if(dependency & TNG_FRAME_DEPENDENT)
6984 if(stride_length > 1)
6992 memcpy(block->block_contents+offset, &temp, sizeof(char));
6993 offset += sizeof(char);
6996 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6997 sizeof(data->n_values_per_frame));
6998 if(tng_data->output_endianness_swap_func_64)
7000 if(tng_data->output_endianness_swap_func_64(tng_data,
7001 (int64_t *)block->header_contents+offset)
7004 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7005 __FILE__, __LINE__);
7008 offset += sizeof(data->n_values_per_frame);
7010 memcpy(block->block_contents+offset, &data->codec_id,
7011 sizeof(data->codec_id));
7012 if(tng_data->output_endianness_swap_func_64)
7014 if(tng_data->output_endianness_swap_func_64(tng_data,
7015 (int64_t *)block->header_contents+offset)
7018 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7019 __FILE__, __LINE__);
7022 offset += sizeof(data->codec_id);
7024 if(data->codec_id != TNG_UNCOMPRESSED)
7026 memcpy(block->block_contents+offset, &data->compression_multiplier,
7027 sizeof(data->compression_multiplier));
7028 if(tng_data->output_endianness_swap_func_64)
7030 if(tng_data->output_endianness_swap_func_64(tng_data,
7031 (int64_t *)block->header_contents+offset)
7034 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7035 __FILE__, __LINE__);
7038 offset += sizeof(data->compression_multiplier);
7041 if(data->n_frames > 0 && stride_length > 1)
7043 /* FIXME: first_frame_with_data is not reliably set */
7044 if(data->first_frame_with_data == 0)
7046 data->first_frame_with_data = frame_set->first_frame;
7048 memcpy(block->block_contents+offset, &data->first_frame_with_data,
7049 sizeof(data->first_frame_with_data));
7050 if(tng_data->output_endianness_swap_func_64)
7052 if(tng_data->output_endianness_swap_func_64(tng_data,
7053 (int64_t *)block->header_contents+offset)
7056 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7057 __FILE__, __LINE__);
7060 offset += sizeof(data->first_frame_with_data);
7062 memcpy(block->block_contents+offset, &stride_length,
7063 sizeof(data->stride_length));
7064 if(tng_data->output_endianness_swap_func_64)
7066 if(tng_data->output_endianness_swap_func_64(tng_data,
7067 (int64_t *)block->header_contents+offset)
7070 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7071 __FILE__, __LINE__);
7074 offset += sizeof(data->stride_length);
7077 if(data->datatype == TNG_CHAR_DATA)
7081 for(i = 0; i < frame_step; i++)
7083 for(j = 0; j < data->n_values_per_frame; j++)
7085 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7086 strncpy(block->block_contents+offset, data->strings[i][j],
7093 else if(data->values)
7095 memcpy(block->block_contents + offset, data->values,
7096 block->block_contents_size - offset);
7097 switch(data->datatype)
7099 case TNG_FLOAT_DATA:
7100 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7101 data->codec_id == TNG_TNG_COMPRESSION)
7103 if(tng_data->input_endianness_swap_func_32)
7105 for(i = offset; i < block->block_contents_size; i+=size)
7107 if(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 multiplier = data->compression_multiplier;
7120 if(fabs(multiplier - 1.0) > 0.00001 ||
7121 tng_data->input_endianness_swap_func_32)
7123 for(i = offset; block->block_contents_size; i+=size)
7125 *(float *)(block->block_contents + i) *= (float)multiplier;
7126 if(tng_data->input_endianness_swap_func_32 &&
7127 tng_data->input_endianness_swap_func_32(tng_data,
7128 (int32_t *)(block->block_contents + i))
7131 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7132 __FILE__, __LINE__);
7139 if(tng_data->input_endianness_swap_func_64)
7141 for(i = offset; i < block->block_contents_size; i+=size)
7143 if(tng_data->input_endianness_swap_func_64(tng_data,
7144 (int64_t *)(block->block_contents + i))
7147 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7148 __FILE__, __LINE__);
7153 case TNG_DOUBLE_DATA:
7154 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7155 data->codec_id == TNG_TNG_COMPRESSION)
7157 if(tng_data->input_endianness_swap_func_64)
7159 for(i = offset; i < block->block_contents_size; i+=size)
7161 if(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__);
7173 multiplier = data->compression_multiplier;
7174 if(fabs(multiplier - 1.0) > 0.00001 ||
7175 tng_data->input_endianness_swap_func_64)
7177 for(i = offset; i < block->block_contents_size; i+=size)
7179 *(double *)(block->block_contents + i) *= multiplier;
7180 if(tng_data->input_endianness_swap_func_64 &&
7181 tng_data->input_endianness_swap_func_64(tng_data,
7182 (int64_t *)(block->block_contents + i))
7185 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7186 __FILE__, __LINE__);
7198 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7201 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7202 frame_set->n_unwritten_frames = 0;
7204 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7206 switch(data->codec_id)
7209 case TNG_GZIP_COMPRESSION:
7210 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7211 stat = tng_gzip_compress(tng_data, block,
7212 block->block_contents + data_start_pos,
7213 block->block_contents_size - data_start_pos);
7214 if(stat != TNG_SUCCESS)
7216 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7218 if(stat == TNG_CRITICAL)
7220 return(TNG_CRITICAL);
7222 data->codec_id = TNG_UNCOMPRESSED;
7224 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7230 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7232 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7233 tng_data->output_file_path, __FILE__, __LINE__);
7234 return(TNG_CRITICAL);
7237 if(fwrite(block->block_contents, block->block_contents_size, 1,
7238 tng_data->output_file) != 1)
7240 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7241 __FILE__, __LINE__);
7242 return(TNG_CRITICAL);
7245 return(TNG_SUCCESS);
7248 /** Read the meta information of a data block (particle or non-particle data).
7249 * @param tng_data is a trajectory data container.
7250 * @param block is the block to store the data (should already contain
7251 * the block headers).
7252 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7253 * error has occured.
7255 static tng_function_status tng_data_block_meta_information_read
7256 (tng_trajectory_t tng_data,
7257 tng_gen_block_t block,
7264 int64_t *first_frame_with_data,
7265 int64_t *stride_length,
7267 int64_t *num_first_particle,
7268 int64_t *block_n_particles,
7274 if(block->block_contents)
7276 contents = block->block_contents;
7280 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7281 contents = malloc(meta_size);
7284 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7285 meta_size, __FILE__, __LINE__);
7288 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7290 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7292 return(TNG_CRITICAL);
7296 memcpy(datatype, contents+*offset,
7298 *offset += sizeof(*datatype);
7300 memcpy(dependency, contents+*offset,
7301 sizeof(*dependency));
7302 *offset += sizeof(*dependency);
7304 if(*dependency & TNG_FRAME_DEPENDENT)
7306 memcpy(sparse_data, contents+*offset,
7307 sizeof(*sparse_data));
7308 *offset += sizeof(*sparse_data);
7311 memcpy(n_values, contents+*offset,
7313 if(tng_data->input_endianness_swap_func_64)
7315 if(tng_data->input_endianness_swap_func_64(tng_data,
7319 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7320 __FILE__, __LINE__);
7323 *offset += sizeof(*n_values);
7325 memcpy(codec_id, contents+*offset,
7327 if(tng_data->input_endianness_swap_func_64)
7329 if(tng_data->input_endianness_swap_func_64(tng_data,
7333 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7334 __FILE__, __LINE__);
7337 *offset += sizeof(*codec_id);
7339 if(*codec_id != TNG_UNCOMPRESSED)
7341 memcpy(multiplier, contents+*offset,
7342 sizeof(*multiplier));
7343 if(tng_data->input_endianness_swap_func_64)
7345 if(tng_data->input_endianness_swap_func_64(tng_data,
7346 (int64_t *) multiplier)
7349 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7350 __FILE__, __LINE__);
7353 *offset += sizeof(*multiplier);
7360 if(*dependency & TNG_FRAME_DEPENDENT)
7364 memcpy(first_frame_with_data, contents+*offset,
7365 sizeof(*first_frame_with_data));
7366 if(tng_data->input_endianness_swap_func_64)
7368 if(tng_data->input_endianness_swap_func_64(tng_data,
7369 first_frame_with_data)
7372 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7373 __FILE__, __LINE__);
7376 *offset += sizeof(*first_frame_with_data);
7378 memcpy(stride_length, contents+*offset,
7379 sizeof(*stride_length));
7380 if(tng_data->input_endianness_swap_func_64)
7382 if(tng_data->input_endianness_swap_func_64(tng_data,
7386 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7387 __FILE__, __LINE__);
7390 *offset += sizeof(*stride_length);
7391 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7392 (*first_frame_with_data -
7393 tng_data->current_trajectory_frame_set.first_frame);
7397 *first_frame_with_data = 0;
7399 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7404 *first_frame_with_data = 0;
7409 if (*dependency & TNG_PARTICLE_DEPENDENT)
7411 memcpy(num_first_particle, contents+*offset,
7412 sizeof(*num_first_particle));
7413 if(tng_data->input_endianness_swap_func_64)
7415 if(tng_data->input_endianness_swap_func_64(tng_data,
7419 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7420 __FILE__, __LINE__);
7423 *offset += sizeof(*num_first_particle);
7425 memcpy(block_n_particles, contents+*offset,
7426 sizeof(*block_n_particles));
7427 if(tng_data->input_endianness_swap_func_64)
7429 if(tng_data->input_endianness_swap_func_64(tng_data,
7433 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7434 __FILE__, __LINE__);
7437 *offset += sizeof(*block_n_particles);
7440 if(!block->block_contents)
7444 return(TNG_SUCCESS);
7447 /** Read the contents of a data block (particle or non-particle data).
7448 * @param tng_data is a trajectory data container.
7449 * @param block is the block to store the data (should already contain
7450 * the block headers).
7451 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7452 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7453 * compared to the md5 hash of the read contents to ensure valid data.
7454 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7455 * error has occured.
7457 static tng_function_status tng_data_block_contents_read
7458 (tng_trajectory_t tng_data,
7459 tng_gen_block_t block,
7460 const char hash_mode)
7462 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7463 int64_t stride_length, block_n_particles, num_first_particle;
7465 char datatype, dependency, sparse_data;
7469 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7471 return(TNG_CRITICAL);
7474 if(block->block_contents)
7476 free(block->block_contents);
7479 block->block_contents = malloc(block->block_contents_size);
7480 if(!block->block_contents)
7482 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7483 block->block_contents_size, __FILE__, __LINE__);
7484 return(TNG_CRITICAL);
7487 /* Read the whole block into block_contents to be able to write it to
7488 * disk even if it cannot be interpreted. */
7489 if(fread(block->block_contents, block->block_contents_size, 1,
7490 tng_data->input_file) == 0)
7492 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7493 return(TNG_CRITICAL);
7496 /* FIXME: Does not check if the size of the contents matches the expected
7497 * size or if the contents can be read. */
7499 if(hash_mode == TNG_USE_HASH)
7501 tng_md5_hash_match_verify(block, &same_hash);
7502 if(same_hash != TNG_TRUE)
7504 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7505 block->name, __FILE__, __LINE__);
7506 /* return(TNG_FAILURE); */
7510 if(tng_data_block_meta_information_read(tng_data, block,
7512 &dependency, &sparse_data,
7513 &n_values, &codec_id,
7514 &first_frame_with_data,
7515 &stride_length, &n_frames,
7516 &num_first_particle,
7518 &multiplier) == TNG_CRITICAL)
7520 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7521 block->name, __FILE__, __LINE__);
7522 return(TNG_CRITICAL);
7525 if (dependency & TNG_PARTICLE_DEPENDENT)
7527 return(tng_particle_data_read(tng_data, block,
7531 first_frame_with_data,
7534 codec_id, multiplier));
7538 return(tng_data_read(tng_data, block,
7540 first_frame_with_data,
7543 codec_id, multiplier));
7548 // ** Move the blocks in a frame set so that there is no unused space between
7549 // * them. This can only be done on the last frame set in the file and should
7550 // * be done e.g. if the last frame set in the file has fewer frames than
7551 // * default or after compressing data blocks in a frame set.
7552 // * @param tng_data is a trajectory data container.
7553 // * @details the current_trajectory_frame_set is the one that will be modified.
7554 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7555 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7556 // * FIXME: This function is not finished!!!
7558 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7560 // tng_gen_block_t block;
7561 // tng_trajectory_frame_set_t frame_set;
7562 // FILE *temp = tng_data->input_file;
7563 // int64_t pos, contents_start_pos, output_file_len;
7565 // frame_set = &tng_data->current_trajectory_frame_set;
7567 // if(frame_set->n_written_frames == frame_set->n_frames)
7569 // return(TNG_SUCCESS);
7572 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7573 // tng_data->last_trajectory_frame_set_output_file_pos)
7577 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7579 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7580 // __FILE__, __LINE__);
7581 // return(TNG_CRITICAL);
7584 // tng_block_init(&block);
7585 // // output_file_pos = ftello(tng_data->output_file);
7587 // tng_data->input_file = tng_data->output_file;
7589 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7591 // fseeko(tng_data->output_file, pos, SEEK_SET);
7592 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7594 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7595 // __FILE__, __LINE__);
7596 // tng_data->input_file = temp;
7597 // tng_block_destroy(&block);
7598 // return(TNG_CRITICAL);
7601 // contents_start_pos = ftello(tng_data->output_file);
7603 // fseeko(tng_data->output_file, 0, SEEK_END);
7604 // output_file_len = ftello(tng_data->output_file);
7605 // pos = contents_start_pos + block->block_contents_size;
7606 // fseeko(tng_data->output_file, pos,
7609 // while(pos < output_file_len)
7611 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7613 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7614 // __FILE__, __LINE__);
7615 // tng_data->input_file = temp;
7616 // tng_block_destroy(&block);
7617 // return(TNG_CRITICAL);
7619 // pos += block->header_contents_size + block->block_contents_size;
7620 // fseeko(tng_data->output_file, pos, SEEK_SET);
7623 // return(TNG_SUCCESS);
7626 /** Finish writing the current frame set. Update the number of frames
7627 * and the hashes of the frame set and all its data blocks (if hash_mode
7629 * @param tng_data is a trajectory data container.
7630 * @param hash_mode specifies whether to update the block md5 hash when
7631 * updating the pointers.
7632 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7633 * error has occured.
7635 static tng_function_status tng_frame_set_finalize
7636 (tng_trajectory_t tng_data, const char hash_mode)
7638 tng_gen_block_t block;
7639 tng_trajectory_frame_set_t frame_set;
7640 FILE *temp = tng_data->input_file;
7641 int64_t pos, contents_start_pos, output_file_len;
7643 frame_set = &tng_data->current_trajectory_frame_set;
7645 if(frame_set->n_written_frames == frame_set->n_frames)
7647 return(TNG_SUCCESS);
7650 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7652 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7653 __FILE__, __LINE__);
7654 return(TNG_CRITICAL);
7657 tng_block_init(&block);
7658 /* output_file_pos = ftello(tng_data->output_file); */
7660 tng_data->input_file = tng_data->output_file;
7662 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7664 fseeko(tng_data->output_file, pos, SEEK_SET);
7666 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7668 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7669 __FILE__, __LINE__);
7670 tng_data->input_file = temp;
7671 tng_block_destroy(&block);
7672 return(TNG_CRITICAL);
7675 contents_start_pos = ftello(tng_data->output_file);
7677 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7678 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7679 1, tng_data->output_file) != 1)
7681 tng_data->input_file = temp;
7682 tng_block_destroy(&block);
7683 return(TNG_CRITICAL);
7687 if(hash_mode == TNG_USE_HASH)
7689 tng_md5_hash_update(tng_data, block, pos,
7690 pos + block->header_contents_size);
7693 fseeko(tng_data->output_file, 0, SEEK_END);
7694 output_file_len = ftello(tng_data->output_file);
7695 pos = contents_start_pos + block->block_contents_size;
7696 fseeko(tng_data->output_file, pos, SEEK_SET);
7698 while(pos < output_file_len)
7700 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7702 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7703 __FILE__, __LINE__);
7704 tng_data->input_file = temp;
7705 tng_block_destroy(&block);
7706 return(TNG_CRITICAL);
7709 if(hash_mode == TNG_USE_HASH)
7711 tng_md5_hash_update(tng_data, block, pos,
7712 pos + block->header_contents_size);
7714 pos += block->header_contents_size + block->block_contents_size;
7715 fseeko(tng_data->output_file, pos, SEEK_SET);
7718 tng_data->input_file = temp;
7719 tng_block_destroy(&block);
7720 return(TNG_SUCCESS);
7724 // ** Sets the name of a file contents block
7725 // * @param tng_data is a trajectory data container.
7726 // * @param block is the block, of which to change names.
7727 // * @param new_name is the new name of the block.
7728 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7729 // * error has occured.
7731 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7732 // tng_gen_block_t block,
7733 // const char *new_name)
7737 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7739 // * If the currently stored string length is not enough to store the new
7740 // * string it is freed and reallocated. *
7741 // if(block->name && strlen(block->name) < len)
7743 // free(block->name);
7748 // block->name = malloc(len);
7751 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7752 // __FILE__, __LINE__);
7753 // return(TNG_CRITICAL);
7757 // strncpy(block->name, new_name, len);
7759 // return(TNG_SUCCESS);
7763 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7764 const tng_atom_t atom,
7765 tng_residue_t *residue)
7769 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7771 *residue = atom->residue;
7773 return(TNG_SUCCESS);
7776 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7777 const tng_atom_t atom,
7782 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7783 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7785 strncpy(name, atom->name, max_len - 1);
7786 name[max_len - 1] = 0;
7788 if(strlen(atom->name) > (unsigned int)max_len - 1)
7790 return(TNG_FAILURE);
7792 return(TNG_SUCCESS);
7795 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7797 const char *new_name)
7802 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7803 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7805 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7807 /* If the currently stored string length is not enough to store the new
7808 * string it is freed and reallocated. */
7809 if(atom->name && strlen(atom->name) < len)
7816 atom->name = malloc(len);
7819 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7820 __FILE__, __LINE__);
7821 return(TNG_CRITICAL);
7825 strncpy(atom->name, new_name, len);
7827 return(TNG_SUCCESS);
7830 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7831 const tng_atom_t atom,
7836 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7837 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7839 strncpy(type, atom->atom_type, max_len - 1);
7840 type[max_len - 1] = 0;
7842 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7844 return(TNG_FAILURE);
7846 return(TNG_SUCCESS);
7849 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7851 const char *new_type)
7856 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7857 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7859 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7861 /* If the currently stored string length is not enough to store the new
7862 * string it is freed and reallocated. */
7863 if(atom->atom_type && strlen(atom->atom_type) < len)
7865 free(atom->atom_type);
7866 atom->atom_type = 0;
7868 if(!atom->atom_type)
7870 atom->atom_type = malloc(len);
7871 if(!atom->atom_type)
7873 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7874 __FILE__, __LINE__);
7875 return(TNG_CRITICAL);
7879 strncpy(atom->atom_type, new_type, len);
7881 return(TNG_SUCCESS);
7884 /** Initialise an atom struct
7885 * @param atom is the atom to initialise.
7886 * @return TNG_SUCCESS (0) if successful.
7888 static tng_function_status tng_atom_init(tng_atom_t atom)
7891 atom->atom_type = 0;
7893 return(TNG_SUCCESS);
7896 /** Free the memory in an atom struct
7897 * @param atom is the atom to destroy.
7898 * @return TNG_SUCCESS (0) if successful.
7900 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7909 free(atom->atom_type);
7910 atom->atom_type = 0;
7913 return(TNG_SUCCESS);
7916 tng_function_status DECLSPECDLLEXPORT tng_version_major
7917 (const tng_trajectory_t tng_data,
7922 *version = TNG_VERSION_MAJOR;
7924 return(TNG_SUCCESS);
7927 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7928 (const tng_trajectory_t tng_data,
7933 *version = TNG_VERSION_MINOR;
7935 return(TNG_SUCCESS);
7938 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7939 (const tng_trajectory_t tng_data,
7944 *patch_level = TNG_VERSION_PATCHLEVEL;
7946 return(TNG_SUCCESS);
7949 tng_function_status DECLSPECDLLEXPORT tng_version
7950 (const tng_trajectory_t tng_data,
7955 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
7957 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
7959 return(TNG_SUCCESS);
7962 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7963 (tng_trajectory_t tng_data,
7965 tng_molecule_t *molecule)
7969 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7970 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7972 /* Set ID to the ID of the last molecule + 1 */
7973 if(tng_data->n_molecules)
7975 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7982 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7985 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7986 (tng_trajectory_t tng_data,
7989 tng_molecule_t *molecule)
7991 tng_molecule_t new_molecules;
7992 int64_t *new_molecule_cnt_list;
7993 tng_function_status stat = TNG_SUCCESS;
7995 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7996 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7998 new_molecules = realloc(tng_data->molecules,
7999 sizeof(struct tng_molecule) *
8000 (tng_data->n_molecules + 1));
8004 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8005 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8006 __FILE__, __LINE__);
8007 free(tng_data->molecules);
8008 tng_data->molecules = 0;
8009 return(TNG_CRITICAL);
8012 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8014 (tng_data->n_molecules + 1));
8016 if(!new_molecule_cnt_list)
8018 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8019 sizeof(int64_t) * (tng_data->n_molecules + 1),
8020 __FILE__, __LINE__);
8021 free(tng_data->molecule_cnt_list);
8022 tng_data->molecule_cnt_list = 0;
8023 free(new_molecules);
8024 return(TNG_CRITICAL);
8027 tng_data->molecules = new_molecules;
8028 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8030 *molecule = &new_molecules[tng_data->n_molecules];
8032 tng_molecule_init(tng_data, *molecule);
8033 tng_molecule_name_set(tng_data, *molecule, name);
8035 /* FIXME: Should this be a function argument instead? */
8036 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8038 (*molecule)->id = id;
8040 tng_data->n_molecules++;
8045 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
8046 (tng_trajectory_t tng_data,
8047 tng_molecule_t *molecule_p)
8049 int64_t *new_molecule_cnt_list, id;
8050 tng_molecule_t new_molecules, molecule;
8052 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8054 /* Set ID to the ID of the last molecule + 1 */
8055 if(tng_data->n_molecules)
8057 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
8064 new_molecules = realloc(tng_data->molecules,
8065 sizeof(struct tng_molecule) *
8066 (tng_data->n_molecules + 1));
8070 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8071 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8072 __FILE__, __LINE__);
8073 free(tng_data->molecules);
8074 tng_data->molecules = 0;
8075 return(TNG_CRITICAL);
8078 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8080 (tng_data->n_molecules + 1));
8082 if(!new_molecule_cnt_list)
8084 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8085 sizeof(int64_t) * (tng_data->n_molecules + 1),
8086 __FILE__, __LINE__);
8087 free(tng_data->molecule_cnt_list);
8088 tng_data->molecule_cnt_list = 0;
8089 free(new_molecules);
8090 return(TNG_CRITICAL);
8093 molecule = *molecule_p;
8095 tng_data->molecules = new_molecules;
8096 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8098 new_molecules[tng_data->n_molecules] = *molecule;
8100 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8104 molecule = &new_molecules[tng_data->n_molecules];
8106 *molecule_p = molecule;
8110 tng_data->n_molecules++;
8112 return(TNG_SUCCESS);
8115 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8116 const tng_molecule_t molecule,
8121 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8122 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8124 strncpy(name, molecule->name, max_len - 1);
8125 name[max_len - 1] = 0;
8127 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8129 return(TNG_FAILURE);
8131 return(TNG_SUCCESS);
8134 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8135 (tng_trajectory_t tng_data,
8136 tng_molecule_t molecule,
8137 const char *new_name)
8142 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8143 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8145 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8147 /* If the currently stored string length is not enough to store the new
8148 * string it is freed and reallocated. */
8149 if(molecule->name && strlen(molecule->name) < len)
8151 free(molecule->name);
8156 molecule->name = malloc(len);
8159 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8160 __FILE__, __LINE__);
8161 return(TNG_CRITICAL);
8165 strncpy(molecule->name, new_name, len);
8167 return(TNG_SUCCESS);
8170 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8171 (const tng_trajectory_t tng_data,
8172 const tng_molecule_t molecule,
8175 int64_t i, index = -1;
8177 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8178 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8180 for(i = 0; i < tng_data->n_molecules; i++)
8182 if(&tng_data->molecules[i] == molecule)
8190 return(TNG_FAILURE);
8192 *cnt = tng_data->molecule_cnt_list[index];
8194 return(TNG_SUCCESS);
8197 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8198 (tng_trajectory_t tng_data,
8199 tng_molecule_t molecule,
8202 int64_t i, old_cnt, index = -1;
8204 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8206 for(i = 0; i < tng_data->n_molecules; i++)
8208 if(&tng_data->molecules[i] == molecule)
8216 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8217 __FILE__, __LINE__);
8218 return(TNG_FAILURE);
8220 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8222 old_cnt = tng_data->molecule_cnt_list[index];
8223 tng_data->molecule_cnt_list[index] = cnt;
8225 tng_data->n_particles += (cnt-old_cnt) *
8226 tng_data->molecules[index].n_atoms;
8230 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8231 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8233 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8234 tng_data->molecules[index].n_atoms;
8237 return(TNG_SUCCESS);
8240 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8241 (tng_trajectory_t tng_data,
8244 tng_molecule_t *molecule)
8246 int64_t i, n_molecules;
8248 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8249 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8250 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8252 n_molecules = tng_data->n_molecules;
8254 for(i = n_molecules - 1; i >= 0; i--)
8256 *molecule = &tng_data->molecules[i];
8257 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8259 if(nr == -1 || nr == (*molecule)->id)
8261 return(TNG_SUCCESS);
8268 return(TNG_FAILURE);
8271 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8272 (tng_trajectory_t tng_data,
8274 tng_molecule_t *molecule)
8276 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8277 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8279 if(index >= tng_data->n_molecules)
8282 return(TNG_FAILURE);
8284 *molecule = &tng_data->molecules[index];
8285 return(TNG_SUCCESS);
8288 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8289 tng_trajectory_t tng_data_dest)
8291 tng_molecule_t molecule, molecule_temp;
8292 tng_chain_t chain, chain_temp;
8293 tng_residue_t residue, residue_temp;
8294 tng_atom_t atom, atom_temp;
8295 tng_bond_t bond_temp;
8296 tng_function_status stat;
8297 int64_t i, j, k, l, *list_temp;
8299 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8300 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8302 for(i = 0; i < tng_data_dest->n_molecules; i++)
8304 molecule = &tng_data_dest->molecules[i];
8305 tng_molecule_destroy(tng_data_dest, molecule);
8308 tng_data_dest->n_molecules = 0;
8309 tng_data_dest->n_particles = 0;
8311 molecule_temp = realloc(tng_data_dest->molecules,
8312 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8315 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8316 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8317 __FILE__, __LINE__);
8318 free(tng_data_dest->molecules);
8319 tng_data_dest->molecules = 0;
8320 return(TNG_CRITICAL);
8322 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8323 sizeof(int64_t) * tng_data_src->n_molecules);
8326 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8327 sizeof(int64_t) * tng_data_src->n_molecules,
8328 __FILE__, __LINE__);
8329 free(tng_data_dest->molecule_cnt_list);
8330 tng_data_dest->molecule_cnt_list = 0;
8331 free(molecule_temp);
8332 return(TNG_CRITICAL);
8335 tng_data_dest->molecules = molecule_temp;
8336 tng_data_dest->molecule_cnt_list = list_temp;
8338 for(i = 0; i < tng_data_src->n_molecules; i++)
8340 molecule = &tng_data_src->molecules[i];
8341 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8343 if(stat != TNG_SUCCESS)
8345 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8346 __FILE__, __LINE__);
8349 molecule_temp->quaternary_str = molecule->quaternary_str;
8350 for(j = 0; j < molecule->n_chains; j++)
8352 chain = &molecule->chains[j];
8353 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8354 chain->name, chain->id,
8356 if(stat != TNG_SUCCESS)
8358 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8359 __FILE__, __LINE__);
8362 for(k = 0; k < chain->n_residues; k++)
8364 residue = &chain->residues[k];
8365 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8366 residue->name, residue->id,
8368 if(stat != TNG_SUCCESS)
8370 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8371 __FILE__, __LINE__);
8374 for(l = 0; l < residue->n_atoms; l++)
8376 atom = &molecule->atoms[residue->atoms_offset + l];
8377 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8378 atom->name, atom->atom_type,
8379 atom->id, &atom_temp);
8380 if(stat != TNG_SUCCESS)
8382 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8383 __FILE__, __LINE__);
8389 molecule_temp->n_bonds = molecule->n_bonds;
8390 if(molecule->n_bonds > 0)
8392 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8396 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8397 sizeof(struct tng_bond) * molecule->n_bonds,
8398 __FILE__, __LINE__);
8399 free(molecule_temp->bonds);
8400 molecule_temp->n_bonds = 0;
8401 return(TNG_CRITICAL);
8403 molecule_temp->bonds = bond_temp;
8404 for(j = 0; j < molecule->n_bonds; j++)
8406 molecule_temp->bonds[j] = molecule->bonds[j];
8409 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8410 tng_data_src->molecule_cnt_list[i]);
8411 if(stat != TNG_SUCCESS)
8413 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8414 __FILE__, __LINE__);
8418 return(TNG_SUCCESS);
8421 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8422 (const tng_trajectory_t tng_data,
8423 const tng_molecule_t molecule,
8427 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8428 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8430 *n = molecule->n_chains;
8432 return(TNG_SUCCESS);
8435 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8436 (tng_trajectory_t tng_data,
8437 tng_molecule_t molecule,
8442 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8443 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8445 if(index >= molecule->n_chains)
8448 return(TNG_FAILURE);
8450 *chain = &molecule->chains[index];
8451 return(TNG_SUCCESS);
8454 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8455 (const tng_trajectory_t tng_data,
8456 const tng_molecule_t molecule,
8460 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8461 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8463 *n = molecule->n_residues;
8465 return(TNG_SUCCESS);
8468 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8469 (const tng_trajectory_t tng_data,
8470 const tng_molecule_t molecule,
8471 const int64_t index,
8472 tng_residue_t *residue)
8475 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8476 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8478 if(index >= molecule->n_residues)
8481 return(TNG_FAILURE);
8483 *residue = &molecule->residues[index];
8484 return(TNG_SUCCESS);
8487 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8488 (const tng_trajectory_t tng_data,
8489 const tng_molecule_t molecule,
8493 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8494 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8496 *n = molecule->n_atoms;
8498 return(TNG_SUCCESS);
8501 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8502 (const tng_trajectory_t tng_data,
8503 const tng_molecule_t molecule,
8504 const int64_t index,
8508 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8509 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8511 if(index >= molecule->n_atoms)
8514 return(TNG_FAILURE);
8516 *atom = &molecule->atoms[index];
8517 return(TNG_SUCCESS);
8520 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8521 (tng_trajectory_t tng_data,
8522 tng_molecule_t molecule,
8527 int64_t i, n_chains;
8530 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8531 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8533 n_chains = molecule->n_chains;
8535 for(i = n_chains - 1; i >= 0; i--)
8537 *chain = &molecule->chains[i];
8538 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8540 if(nr == -1 || nr == (*chain)->id)
8542 return(TNG_SUCCESS);
8549 return(TNG_FAILURE);
8552 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8553 (tng_trajectory_t tng_data,
8554 tng_molecule_t molecule,
8560 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8561 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8563 /* Set ID to the ID of the last chain + 1 */
8564 if(molecule->n_chains)
8566 id = molecule->chains[molecule->n_chains-1].id + 1;
8573 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8577 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8578 (tng_trajectory_t tng_data,
8579 tng_molecule_t molecule,
8584 tng_chain_t new_chains;
8585 tng_function_status stat = TNG_SUCCESS;
8587 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8588 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8590 new_chains = realloc(molecule->chains,
8591 sizeof(struct tng_chain) *
8592 (molecule->n_chains + 1));
8596 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8597 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8598 __FILE__, __LINE__);
8599 free(molecule->chains);
8600 molecule->chains = 0;
8601 return(TNG_CRITICAL);
8604 molecule->chains = new_chains;
8606 *chain = &new_chains[molecule->n_chains];
8609 tng_chain_name_set(tng_data, *chain, name);
8611 (*chain)->molecule = molecule;
8612 (*chain)->n_residues = 0;
8614 molecule->n_chains++;
8621 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8622 (const tng_trajectory_t tng_data,
8623 tng_molecule_t molecule,
8624 const int64_t from_atom_id,
8625 const int64_t to_atom_id,
8628 tng_bond_t new_bonds;
8631 new_bonds = realloc(molecule->bonds,
8632 sizeof(struct tng_bond) *
8633 (molecule->n_bonds + 1));
8637 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8638 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8639 __FILE__, __LINE__);
8641 free(molecule->bonds);
8642 molecule->bonds = 0;
8643 return(TNG_CRITICAL);
8646 molecule->bonds = new_bonds;
8648 *bond = &new_bonds[molecule->n_bonds];
8650 (*bond)->from_atom_id = from_atom_id;
8651 (*bond)->to_atom_id = to_atom_id;
8653 molecule->n_bonds++;
8655 return(TNG_SUCCESS);
8658 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8659 (tng_trajectory_t tng_data,
8660 tng_molecule_t molecule,
8668 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8670 n_atoms = molecule->n_atoms;
8672 for(i = n_atoms - 1; i >= 0; i--)
8674 *atom = &molecule->atoms[i];
8675 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8677 if(id == -1 || id == (*atom)->id)
8679 return(TNG_SUCCESS);
8686 return(TNG_FAILURE);
8689 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8690 const tng_chain_t chain,
8695 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8696 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8698 strncpy(name, chain->name, max_len - 1);
8699 name[max_len - 1] = 0;
8701 if(strlen(chain->name) > (unsigned int)max_len - 1)
8703 return(TNG_FAILURE);
8705 return(TNG_SUCCESS);
8708 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8709 (tng_trajectory_t tng_data,
8711 const char *new_name)
8716 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8718 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8720 /* If the currently stored string length is not enough to store the new
8721 * string it is freed and reallocated. */
8722 if(chain->name && strlen(chain->name) < len)
8729 chain->name = malloc(len);
8732 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8733 __FILE__, __LINE__);
8734 return(TNG_CRITICAL);
8738 strncpy(chain->name, new_name, len);
8740 return(TNG_SUCCESS);
8743 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8744 (const tng_trajectory_t tng_data,
8745 const tng_chain_t chain,
8749 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8750 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8752 *n = chain->n_residues;
8754 return(TNG_SUCCESS);
8757 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8758 (const tng_trajectory_t tng_data,
8759 const tng_chain_t chain,
8760 const int64_t index,
8761 tng_residue_t *residue)
8764 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8765 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8767 if(index >= chain->n_residues)
8770 return(TNG_FAILURE);
8772 *residue = &chain->residues[index];
8773 return(TNG_SUCCESS);
8776 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8777 (tng_trajectory_t tng_data,
8781 tng_residue_t *residue)
8783 int64_t i, n_residues;
8786 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8788 n_residues = chain->n_residues;
8790 for(i = n_residues - 1; i >= 0; i--)
8792 *residue = &chain->residues[i];
8793 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8795 if(id == -1 || id == (*residue)->id)
8797 return(TNG_SUCCESS);
8804 return(TNG_FAILURE);
8807 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8808 (tng_trajectory_t tng_data,
8811 tng_residue_t *residue)
8815 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8816 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8818 /* Set ID to the ID of the last residue + 1 */
8819 if(chain->n_residues)
8821 id = chain->residues[chain->n_residues-1].id + 1;
8828 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8832 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8833 (tng_trajectory_t tng_data,
8837 tng_residue_t *residue)
8840 tng_residue_t new_residues, temp_residue, last_residue;
8841 tng_molecule_t molecule = chain->molecule;
8842 tng_function_status stat = TNG_SUCCESS;
8844 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8845 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8847 if(chain->n_residues)
8849 curr_index = chain->residues - molecule->residues;
8856 new_residues = realloc(molecule->residues,
8857 sizeof(struct tng_residue) *
8858 (molecule->n_residues + 1));
8862 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8863 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8864 __FILE__, __LINE__);
8865 free(molecule->residues);
8866 molecule->residues = 0;
8867 return(TNG_CRITICAL);
8870 molecule->residues = new_residues;
8872 if(curr_index != -1)
8874 chain->residues = new_residues + curr_index;
8875 if(molecule->n_residues)
8877 last_residue = &new_residues[molecule->n_residues - 1];
8879 temp_residue = chain->residues + (chain->n_residues - 1);
8880 /* Make space in list of residues to add the new residues together with the other
8881 * residues of this chain */
8882 if(temp_residue != last_residue)
8885 memmove(temp_residue + 1, temp_residue,
8886 last_residue - temp_residue);
8892 curr_index = molecule->n_residues;
8895 *residue = &molecule->residues[curr_index + chain->n_residues];
8897 if(!chain->n_residues)
8899 chain->residues = *residue;
8903 chain->residues = &molecule->residues[curr_index];
8906 (*residue)->name = 0;
8907 tng_residue_name_set(tng_data, *residue, name);
8909 (*residue)->chain = chain;
8910 (*residue)->n_atoms = 0;
8911 (*residue)->atoms_offset = 0;
8913 chain->n_residues++;
8914 molecule->n_residues++;
8916 (*residue)->id = id;
8921 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8922 const tng_residue_t residue,
8927 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8928 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8930 strncpy(name, residue->name, max_len - 1);
8931 name[max_len - 1] = 0;
8933 if(strlen(residue->name) > (unsigned int)max_len - 1)
8935 return(TNG_FAILURE);
8937 return(TNG_SUCCESS);
8940 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8941 tng_residue_t residue,
8942 const char *new_name)
8947 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8948 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8950 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8952 /* If the currently stored string length is not enough to store the new
8953 * string it is freed and reallocated. */
8954 if(residue->name && strlen(residue->name) < len)
8956 free(residue->name);
8961 residue->name = malloc(len);
8964 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8965 __FILE__, __LINE__);
8966 return(TNG_CRITICAL);
8970 strncpy(residue->name, new_name, len);
8972 return(TNG_SUCCESS);
8975 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8976 (const tng_trajectory_t tng_data,
8977 const tng_residue_t residue,
8981 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8982 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8984 *n = residue->n_atoms;
8986 return(TNG_SUCCESS);
8989 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8990 (const tng_trajectory_t tng_data,
8991 const tng_residue_t residue,
8992 const int64_t index,
8996 tng_molecule_t molecule;
8999 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
9000 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
9002 if(index >= residue->n_atoms)
9005 return(TNG_FAILURE);
9007 chain = residue->chain;
9008 molecule = chain->molecule;
9010 if(index + residue->atoms_offset >= molecule->n_atoms)
9013 return(TNG_FAILURE);
9016 *atom = &molecule->atoms[residue->atoms_offset + index];
9017 return(TNG_SUCCESS);
9020 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
9021 (tng_trajectory_t tng_data,
9022 tng_residue_t residue,
9023 const char *atom_name,
9024 const char *atom_type,
9029 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9030 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9031 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9033 /* Set ID to the ID of the last atom + 1 */
9034 if(residue->chain->molecule->n_atoms)
9036 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
9043 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
9047 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
9048 (tng_trajectory_t tng_data,
9049 tng_residue_t residue,
9050 const char *atom_name,
9051 const char *atom_type,
9055 tng_atom_t new_atoms;
9056 tng_molecule_t molecule = residue->chain->molecule;
9057 tng_function_status stat = TNG_SUCCESS;
9059 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9060 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9061 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9063 if(!residue->n_atoms)
9065 residue->atoms_offset = molecule->n_atoms;
9068 new_atoms = realloc(molecule->atoms,
9069 sizeof(struct tng_atom) *
9070 (molecule->n_atoms + 1));
9074 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9075 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
9076 __FILE__, __LINE__);
9077 free(molecule->atoms);
9078 molecule->atoms = 0;
9079 return(TNG_CRITICAL);
9082 molecule->atoms = new_atoms;
9084 *atom = &new_atoms[molecule->n_atoms];
9086 tng_atom_init(*atom);
9087 tng_atom_name_set(tng_data, *atom, atom_name);
9088 tng_atom_type_set(tng_data, *atom, atom_type);
9090 (*atom)->residue = residue;
9093 molecule->n_atoms++;
9100 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
9101 tng_molecule_t *molecule_p)
9103 *molecule_p = malloc(sizeof(struct tng_molecule));
9106 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9107 sizeof(struct tng_molecule), __FILE__, __LINE__);
9108 return(TNG_CRITICAL);
9111 tng_molecule_init(tng_data, *molecule_p);
9113 return(TNG_SUCCESS);
9116 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9117 tng_molecule_t *molecule_p)
9121 return(TNG_SUCCESS);
9124 tng_molecule_destroy(tng_data, *molecule_p);
9129 return(TNG_SUCCESS);
9132 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9133 tng_molecule_t molecule)
9136 molecule->quaternary_str = 1;
9138 molecule->n_chains = 0;
9139 molecule->chains = 0;
9140 molecule->n_residues = 0;
9141 molecule->residues = 0;
9142 molecule->n_atoms = 0;
9143 molecule->atoms = 0;
9144 molecule->n_bonds = 0;
9145 molecule->bonds = 0;
9147 return(TNG_SUCCESS);
9150 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9151 tng_molecule_t molecule)
9158 free(molecule->name);
9162 if(molecule->chains)
9164 for(i = 0; i < molecule->n_chains; i++)
9166 if(molecule->chains[i].name)
9168 free(molecule->chains[i].name);
9169 molecule->chains[i].name = 0;
9172 free(molecule->chains);
9173 molecule->chains = 0;
9175 molecule->n_chains = 0;
9177 if(molecule->residues)
9179 for(i = 0; i < molecule->n_residues; i++)
9181 if(molecule->residues[i].name)
9183 free(molecule->residues[i].name);
9184 molecule->residues[i].name = 0;
9187 free(molecule->residues);
9188 molecule->residues = 0;
9190 molecule->n_residues = 0;
9194 for(i = 0; i < molecule->n_atoms; i++)
9196 tng_atom_destroy(&molecule->atoms[i]);
9198 free(molecule->atoms);
9199 molecule->atoms = 0;
9201 molecule->n_atoms = 0;
9205 free(molecule->bonds);
9206 molecule->bonds = 0;
9208 molecule->n_bonds = 0;
9210 return(TNG_SUCCESS);
9213 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9214 (const tng_trajectory_t tng_data,
9219 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9221 tng_bool found = TNG_FALSE;
9223 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9224 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9226 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9228 if(!molecule_cnt_list)
9230 return(TNG_FAILURE);
9233 for(i = 0; i < tng_data->n_molecules; i++)
9235 mol = &tng_data->molecules[i];
9236 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9238 cnt += mol->n_atoms * molecule_cnt_list[i];
9246 return(TNG_FAILURE);
9249 strncpy(name, mol->name, max_len - 1);
9250 name[max_len - 1] = 0;
9252 if(strlen(mol->name) > (unsigned int)max_len - 1)
9254 return(TNG_FAILURE);
9256 return(TNG_SUCCESS);
9259 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9260 (const tng_trajectory_t tng_data,
9264 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9266 tng_bool found = TNG_FALSE;
9268 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9269 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9271 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9273 if(!molecule_cnt_list)
9275 return(TNG_FAILURE);
9278 for(i = 0; i < tng_data->n_molecules; i++)
9280 mol = &tng_data->molecules[i];
9281 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9283 cnt += mol->n_atoms * molecule_cnt_list[i];
9291 return(TNG_FAILURE);
9296 return(TNG_SUCCESS);
9299 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9300 (const tng_trajectory_t tng_data,
9302 int64_t **from_atoms,
9305 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9306 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9310 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9311 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9312 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9313 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9315 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9317 if(!molecule_cnt_list)
9319 return(TNG_FAILURE);
9323 /* First count the total number of bonds to allocate memory */
9324 for(i = 0; i < tng_data->n_molecules; i++)
9326 mol = &tng_data->molecules[i];
9327 mol_cnt = molecule_cnt_list[i];
9328 *n_bonds += mol_cnt * mol->n_bonds;
9332 return(TNG_SUCCESS);
9335 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9338 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9339 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9340 return(TNG_CRITICAL);
9342 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9345 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9346 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9349 return(TNG_CRITICAL);
9353 for(i = 0; i < tng_data->n_molecules; i++)
9355 mol = &tng_data->molecules[i];
9356 mol_cnt = molecule_cnt_list[i];
9357 for(j = 0; j < mol_cnt; j++)
9359 for(k = 0; k < mol->n_bonds; k++)
9361 bond = &mol->bonds[k];
9362 from_atom = atom_cnt + bond->from_atom_id;
9363 to_atom = atom_cnt + bond->to_atom_id;
9364 (*from_atoms)[cnt] = from_atom;
9365 (*to_atoms)[cnt++] = to_atom;
9367 atom_cnt += mol->n_atoms;
9371 return(TNG_SUCCESS);
9374 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9375 (const tng_trajectory_t tng_data,
9380 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9383 tng_bool found = TNG_FALSE;
9385 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9386 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9388 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9390 if(!molecule_cnt_list)
9392 return(TNG_FAILURE);
9395 for(i = 0; i < tng_data->n_molecules; i++)
9397 mol = &tng_data->molecules[i];
9398 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9400 cnt += mol->n_atoms * molecule_cnt_list[i];
9403 atom = &mol->atoms[nr % mol->n_atoms];
9409 return(TNG_FAILURE);
9411 if(!atom->residue || !atom->residue->chain)
9413 return(TNG_FAILURE);
9416 strncpy(name, atom->residue->chain->name, max_len - 1);
9417 name[max_len - 1] = 0;
9419 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9421 return(TNG_FAILURE);
9423 return(TNG_SUCCESS);
9426 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9427 (const tng_trajectory_t tng_data,
9432 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9435 tng_bool found = TNG_FALSE;
9437 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9438 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9440 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9442 if(!molecule_cnt_list)
9444 return(TNG_FAILURE);
9447 for(i = 0; i < tng_data->n_molecules; i++)
9449 mol = &tng_data->molecules[i];
9450 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9452 cnt += mol->n_atoms * molecule_cnt_list[i];
9455 atom = &mol->atoms[nr % mol->n_atoms];
9461 return(TNG_FAILURE);
9465 return(TNG_FAILURE);
9468 strncpy(name, atom->residue->name, max_len - 1);
9469 name[max_len - 1] = 0;
9471 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9473 return(TNG_FAILURE);
9475 return(TNG_SUCCESS);
9478 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9479 (const tng_trajectory_t tng_data,
9483 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9486 tng_bool found = TNG_FALSE;
9488 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9489 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9491 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9493 if(!molecule_cnt_list)
9495 return(TNG_FAILURE);
9498 for(i = 0; i < tng_data->n_molecules; i++)
9500 mol = &tng_data->molecules[i];
9501 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9503 cnt += mol->n_atoms * molecule_cnt_list[i];
9506 atom = &mol->atoms[nr % mol->n_atoms];
9512 return(TNG_FAILURE);
9516 return(TNG_FAILURE);
9519 *id = atom->residue->id;
9521 return(TNG_SUCCESS);
9524 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9525 (const tng_trajectory_t tng_data,
9529 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9532 tng_bool found = TNG_FALSE;
9534 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9535 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9537 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9539 if(!molecule_cnt_list)
9541 return(TNG_FAILURE);
9544 for(i = 0; i < tng_data->n_molecules; i++)
9546 mol = &tng_data->molecules[i];
9547 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9549 cnt += mol->n_atoms * molecule_cnt_list[i];
9550 offset += mol->n_residues * molecule_cnt_list[i];
9553 atom = &mol->atoms[nr % mol->n_atoms];
9559 return(TNG_FAILURE);
9563 return(TNG_FAILURE);
9566 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9568 *id = atom->residue->id + offset;
9570 return(TNG_SUCCESS);
9573 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9574 (const tng_trajectory_t tng_data,
9579 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9582 tng_bool found = TNG_FALSE;
9584 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9585 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9587 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9589 if(!molecule_cnt_list)
9591 return(TNG_FAILURE);
9594 for(i = 0; i < tng_data->n_molecules; i++)
9596 mol = &tng_data->molecules[i];
9597 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9599 cnt += mol->n_atoms * molecule_cnt_list[i];
9602 atom = &mol->atoms[nr % mol->n_atoms];
9608 return(TNG_FAILURE);
9611 strncpy(name, atom->name, max_len - 1);
9612 name[max_len - 1] = 0;
9614 if(strlen(atom->name) > (unsigned int)max_len - 1)
9616 return(TNG_FAILURE);
9618 return(TNG_SUCCESS);
9621 tng_function_status tng_atom_type_of_particle_nr_get
9622 (const tng_trajectory_t tng_data,
9627 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9630 tng_bool found = TNG_FALSE;
9632 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9633 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9635 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9637 if(!molecule_cnt_list)
9639 return(TNG_FAILURE);
9642 for(i = 0; i < tng_data->n_molecules; i++)
9644 mol = &tng_data->molecules[i];
9645 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9647 cnt += mol->n_atoms * molecule_cnt_list[i];
9650 atom = &mol->atoms[nr % mol->n_atoms];
9656 return(TNG_FAILURE);
9659 strncpy(type, atom->atom_type, max_len - 1);
9660 type[max_len - 1] = 0;
9662 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9664 return(TNG_FAILURE);
9666 return(TNG_SUCCESS);
9669 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9670 (tng_trajectory_t tng_data,
9671 const int64_t num_first_particle,
9672 const int64_t n_particles,
9673 const int64_t *mapping_table)
9676 tng_particle_mapping_t mapping;
9677 tng_trajectory_frame_set_t frame_set;
9679 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9681 frame_set = &tng_data->current_trajectory_frame_set;
9683 /* Sanity check of the particle ranges. Split into multiple if
9684 * statements for improved readability */
9685 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9687 mapping = &frame_set->mappings[i];
9688 if(num_first_particle >= mapping->num_first_particle &&
9689 num_first_particle < mapping->num_first_particle +
9690 mapping->n_particles)
9692 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9693 return(TNG_FAILURE);
9695 if(num_first_particle + n_particles >=
9696 mapping->num_first_particle &&
9697 num_first_particle + n_particles <
9698 mapping->num_first_particle + mapping->n_particles)
9700 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9701 return(TNG_FAILURE);
9703 if(mapping->num_first_particle >= num_first_particle &&
9704 mapping->num_first_particle < num_first_particle +
9707 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9708 return(TNG_FAILURE);
9710 if(mapping->num_first_particle + mapping->n_particles >
9711 num_first_particle &&
9712 mapping->num_first_particle + mapping->n_particles <
9713 num_first_particle + n_particles)
9715 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9716 return(TNG_FAILURE);
9720 frame_set->n_mapping_blocks++;
9722 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9723 frame_set->n_mapping_blocks);
9727 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9728 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9729 __FILE__, __LINE__);
9730 free(frame_set->mappings);
9731 frame_set->mappings = 0;
9732 return(TNG_CRITICAL);
9734 frame_set->mappings = mapping;
9736 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9737 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9739 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9740 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9742 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9743 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9744 return(TNG_CRITICAL);
9747 for(i=0; i<n_particles; i++)
9749 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9752 return(TNG_SUCCESS);
9755 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9757 tng_trajectory_frame_set_t frame_set;
9758 tng_particle_mapping_t mapping;
9761 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9763 frame_set = &tng_data->current_trajectory_frame_set;
9765 if(frame_set->n_mapping_blocks && frame_set->mappings)
9767 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9769 mapping = &frame_set->mappings[i];
9770 if(mapping->real_particle_numbers)
9772 free(mapping->real_particle_numbers);
9773 mapping->real_particle_numbers = 0;
9776 free(frame_set->mappings);
9777 frame_set->mappings = 0;
9778 frame_set->n_mapping_blocks = 0;
9781 return(TNG_SUCCESS);
9784 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9787 tng_trajectory_frame_set_t frame_set;
9788 tng_trajectory_t tng_data;
9790 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9793 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9794 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9795 return(TNG_CRITICAL);
9798 tng_data = *tng_data_p;
9800 frame_set = &tng_data->current_trajectory_frame_set;
9802 tng_data->input_file_path = 0;
9803 tng_data->input_file = 0;
9804 tng_data->input_file_len = 0;
9805 tng_data->output_file_path = 0;
9806 tng_data->output_file = 0;
9808 tng_data->first_program_name = 0;
9809 tng_data->first_user_name = 0;
9810 tng_data->first_computer_name = 0;
9811 tng_data->first_pgp_signature = 0;
9812 tng_data->last_program_name = 0;
9813 tng_data->last_user_name = 0;
9814 tng_data->last_computer_name = 0;
9815 tng_data->last_pgp_signature = 0;
9816 tng_data->forcefield_name = 0;
9821 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9825 tng_data->time = seconds;
9828 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9829 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9830 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9831 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9832 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9833 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9834 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9835 tng_data->frame_set_n_frames = 100;
9836 tng_data->n_trajectory_frame_sets = 0;
9837 tng_data->medium_stride_length = 100;
9838 tng_data->long_stride_length = 10000;
9840 tng_data->time_per_frame = -1;
9842 tng_data->n_particle_data_blocks = 0;
9843 tng_data->n_data_blocks = 0;
9845 tng_data->non_tr_particle_data = 0;
9846 tng_data->non_tr_data = 0;
9848 tng_data->compress_algo_pos = 0;
9849 tng_data->compress_algo_vel = 0;
9850 tng_data->compression_precision = 1000;
9851 tng_data->distance_unit_exponential = -9;
9853 frame_set->first_frame = -1;
9854 frame_set->n_mapping_blocks = 0;
9855 frame_set->mappings = 0;
9856 frame_set->molecule_cnt_list = 0;
9858 frame_set->n_particle_data_blocks = 0;
9859 frame_set->n_data_blocks = 0;
9861 frame_set->tr_particle_data = 0;
9862 frame_set->tr_data = 0;
9864 frame_set->n_written_frames = 0;
9865 frame_set->n_unwritten_frames = 0;
9867 frame_set->next_frame_set_file_pos = -1;
9868 frame_set->prev_frame_set_file_pos = -1;
9869 frame_set->medium_stride_next_frame_set_file_pos = -1;
9870 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9871 frame_set->long_stride_next_frame_set_file_pos = -1;
9872 frame_set->long_stride_prev_frame_set_file_pos = -1;
9874 frame_set->first_frame_time = -1;
9876 tng_data->n_molecules = 0;
9877 tng_data->molecules = 0;
9878 tng_data->molecule_cnt_list = 0;
9879 tng_data->n_particles = 0;
9882 /* Check the endianness of the computer */
9883 static int32_t endianness_32 = 0x01234567;
9885 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9887 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9891 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9893 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9898 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9900 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9904 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9905 /* 0x0123456789ABCDEF */
9906 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9908 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9911 /* 0xEFCDAB8967452301 */
9912 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9914 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9917 /* 0x89ABCDEF01234567 */
9918 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9920 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9923 /* 0x45670123CDEF89AB */
9924 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9926 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9929 /* 0x23016745AB89EFCD */
9930 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9932 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9936 /* By default do not swap the byte order, i.e. keep the byte order of the
9937 * architecture. The input file endianness will be set when reading the
9938 * header. The output endianness can be changed - before the file is
9940 tng_data->input_endianness_swap_func_32 = 0;
9941 tng_data->input_endianness_swap_func_64 = 0;
9942 tng_data->output_endianness_swap_func_32 = 0;
9943 tng_data->output_endianness_swap_func_64 = 0;
9945 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9946 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9947 tng_data->current_trajectory_frame_set.n_frames = 0;
9949 return(TNG_SUCCESS);
9952 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9955 int64_t n_particles, n_values_per_frame;
9956 tng_trajectory_t tng_data = *tng_data_p;
9957 tng_trajectory_frame_set_t frame_set;
9961 return(TNG_SUCCESS);
9964 frame_set = &tng_data->current_trajectory_frame_set;
9966 if(tng_data->input_file_path)
9968 free(tng_data->input_file_path);
9969 tng_data->input_file_path = 0;
9972 if(tng_data->input_file)
9974 if(tng_data->output_file == tng_data->input_file)
9976 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9977 tng_data->output_file = 0;
9979 fclose(tng_data->input_file);
9980 tng_data->input_file = 0;
9983 if(tng_data->output_file_path)
9985 free(tng_data->output_file_path);
9986 tng_data->output_file_path = 0;
9989 if(tng_data->output_file)
9991 /* FIXME: Do not always write the hash */
9992 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9993 fclose(tng_data->output_file);
9994 tng_data->output_file = 0;
9997 if(tng_data->first_program_name)
9999 free(tng_data->first_program_name);
10000 tng_data->first_program_name = 0;
10003 if(tng_data->last_program_name)
10005 free(tng_data->last_program_name);
10006 tng_data->last_program_name = 0;
10009 if(tng_data->first_user_name)
10011 free(tng_data->first_user_name);
10012 tng_data->first_user_name = 0;
10015 if(tng_data->last_user_name)
10017 free(tng_data->last_user_name);
10018 tng_data->last_user_name = 0;
10021 if(tng_data->first_computer_name)
10023 free(tng_data->first_computer_name);
10024 tng_data->first_computer_name = 0;
10027 if(tng_data->last_computer_name)
10029 free(tng_data->last_computer_name);
10030 tng_data->last_computer_name = 0;
10033 if(tng_data->first_pgp_signature)
10035 free(tng_data->first_pgp_signature);
10036 tng_data->first_pgp_signature = 0;
10039 if(tng_data->last_pgp_signature)
10041 free(tng_data->last_pgp_signature);
10042 tng_data->last_pgp_signature = 0;
10045 if(tng_data->forcefield_name)
10047 free(tng_data->forcefield_name);
10048 tng_data->forcefield_name = 0;
10051 tng_frame_set_particle_mapping_free(tng_data);
10053 if(frame_set->molecule_cnt_list)
10055 free(frame_set->molecule_cnt_list);
10056 frame_set->molecule_cnt_list = 0;
10059 if(tng_data->var_num_atoms_flag)
10061 n_particles = frame_set->n_particles;
10065 n_particles = tng_data->n_particles;
10068 if(tng_data->non_tr_particle_data)
10070 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
10072 if(tng_data->non_tr_particle_data[i].values)
10074 free(tng_data->non_tr_particle_data[i].values);
10075 tng_data->non_tr_particle_data[i].values = 0;
10078 if(tng_data->non_tr_particle_data[i].strings)
10080 n_values_per_frame = tng_data->non_tr_particle_data[i].
10081 n_values_per_frame;
10082 if(tng_data->non_tr_particle_data[i].strings[0])
10084 for(j = 0; j < n_particles; j++)
10086 if(tng_data->non_tr_particle_data[i].strings[0][j])
10088 for(k = 0; k < n_values_per_frame; k++)
10090 if(tng_data->non_tr_particle_data[i].
10093 free(tng_data->non_tr_particle_data[i].
10095 tng_data->non_tr_particle_data[i].
10096 strings[0][j][k] = 0;
10099 free(tng_data->non_tr_particle_data[i].
10101 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
10104 free(tng_data->non_tr_particle_data[i].strings[0]);
10105 tng_data->non_tr_particle_data[i].strings[0] = 0;
10107 free(tng_data->non_tr_particle_data[i].strings);
10108 tng_data->non_tr_particle_data[i].strings = 0;
10111 if(tng_data->non_tr_particle_data[i].block_name)
10113 free(tng_data->non_tr_particle_data[i].block_name);
10114 tng_data->non_tr_particle_data[i].block_name = 0;
10117 free(tng_data->non_tr_particle_data);
10118 tng_data->non_tr_particle_data = 0;
10121 if(tng_data->non_tr_data)
10123 for(i = 0; i < tng_data->n_data_blocks; i++)
10125 if(tng_data->non_tr_data[i].values)
10127 free(tng_data->non_tr_data[i].values);
10128 tng_data->non_tr_data[i].values = 0;
10131 if(tng_data->non_tr_data[i].strings)
10133 n_values_per_frame = tng_data->non_tr_data[i].
10134 n_values_per_frame;
10135 if(tng_data->non_tr_data[i].strings[0])
10137 for(j = 0; j < n_values_per_frame; j++)
10139 if(tng_data->non_tr_data[i].strings[0][j])
10141 free(tng_data->non_tr_data[i].strings[0][j]);
10142 tng_data->non_tr_data[i].strings[0][j] = 0;
10145 free(tng_data->non_tr_data[i].strings[0]);
10146 tng_data->non_tr_data[i].strings[0] = 0;
10148 free(tng_data->non_tr_data[i].strings);
10149 tng_data->non_tr_data[i].strings = 0;
10152 if(tng_data->non_tr_data[i].block_name)
10154 free(tng_data->non_tr_data[i].block_name);
10155 tng_data->non_tr_data[i].block_name = 0;
10158 free(tng_data->non_tr_data);
10159 tng_data->non_tr_data = 0;
10162 tng_data->n_particle_data_blocks = 0;
10163 tng_data->n_data_blocks = 0;
10165 if(tng_data->compress_algo_pos)
10167 free(tng_data->compress_algo_pos);
10168 tng_data->compress_algo_pos = 0;
10170 if(tng_data->compress_algo_vel)
10172 free(tng_data->compress_algo_vel);
10173 tng_data->compress_algo_vel = 0;
10176 if(frame_set->tr_particle_data)
10178 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10180 if(frame_set->tr_particle_data[i].values)
10182 free(frame_set->tr_particle_data[i].values);
10183 frame_set->tr_particle_data[i].values = 0;
10186 if(frame_set->tr_particle_data[i].strings)
10188 n_values_per_frame = frame_set->tr_particle_data[i].
10189 n_values_per_frame;
10190 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10192 if(frame_set->tr_particle_data[i].strings[j])
10194 for(k = 0; k < n_particles; k++)
10196 if(frame_set->tr_particle_data[i].
10199 for(l = 0; l < n_values_per_frame; l++)
10201 if(frame_set->tr_particle_data[i].
10204 free(frame_set->tr_particle_data[i].
10206 frame_set->tr_particle_data[i].
10207 strings[j][k][l] = 0;
10210 free(frame_set->tr_particle_data[i].
10212 frame_set->tr_particle_data[i].
10216 free(frame_set->tr_particle_data[i].strings[j]);
10217 frame_set->tr_particle_data[i].strings[j] = 0;
10220 free(frame_set->tr_particle_data[i].strings);
10221 frame_set->tr_particle_data[i].strings = 0;
10224 if(frame_set->tr_particle_data[i].block_name)
10226 free(frame_set->tr_particle_data[i].block_name);
10227 frame_set->tr_particle_data[i].block_name = 0;
10230 free(frame_set->tr_particle_data);
10231 frame_set->tr_particle_data = 0;
10234 if(frame_set->tr_data)
10236 for(i = 0; i < frame_set->n_data_blocks; i++)
10238 if(frame_set->tr_data[i].values)
10240 free(frame_set->tr_data[i].values);
10241 frame_set->tr_data[i].values = 0;
10244 if(frame_set->tr_data[i].strings)
10246 n_values_per_frame = frame_set->tr_data[i].
10247 n_values_per_frame;
10248 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10250 if(frame_set->tr_data[i].strings[j])
10252 for(k = 0; k < n_values_per_frame; k++)
10254 if(frame_set->tr_data[i].strings[j][k])
10256 free(frame_set->tr_data[i].strings[j][k]);
10257 frame_set->tr_data[i].strings[j][k] = 0;
10260 free(frame_set->tr_data[i].strings[j]);
10261 frame_set->tr_data[i].strings[j] = 0;
10264 free(frame_set->tr_data[i].strings);
10265 frame_set->tr_data[i].strings = 0;
10268 if(frame_set->tr_data[i].block_name)
10270 free(frame_set->tr_data[i].block_name);
10271 frame_set->tr_data[i].block_name = 0;
10274 free(frame_set->tr_data);
10275 frame_set->tr_data = 0;
10278 frame_set->n_particle_data_blocks = 0;
10279 frame_set->n_data_blocks = 0;
10281 if(tng_data->molecules)
10283 for(i = 0; i < tng_data->n_molecules; i++)
10285 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10287 free(tng_data->molecules);
10288 tng_data->molecules = 0;
10289 tng_data->n_molecules = 0;
10291 if(tng_data->molecule_cnt_list)
10293 free(tng_data->molecule_cnt_list);
10294 tng_data->molecule_cnt_list = 0;
10300 return(TNG_SUCCESS);
10303 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10304 tng_trajectory_t *dest_p)
10306 tng_trajectory_frame_set_t frame_set;
10307 tng_trajectory_t dest;
10309 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10311 *dest_p = malloc(sizeof(struct tng_trajectory));
10314 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10315 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10316 return(TNG_CRITICAL);
10321 frame_set = &dest->current_trajectory_frame_set;
10323 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10324 if(!dest->input_file_path)
10326 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10327 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10328 return(TNG_CRITICAL);
10330 strcpy(dest->input_file_path, src->input_file_path);
10331 dest->input_file = 0;
10332 dest->input_file_len = src->input_file_len;
10333 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10334 if(!dest->output_file_path)
10336 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10337 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10338 return(TNG_CRITICAL);
10340 strcpy(dest->output_file_path, src->output_file_path);
10341 dest->output_file = 0;
10343 dest->first_program_name = 0;
10344 dest->first_user_name = 0;
10345 dest->first_computer_name = 0;
10346 dest->first_pgp_signature = 0;
10347 dest->last_program_name = 0;
10348 dest->last_user_name = 0;
10349 dest->last_computer_name = 0;
10350 dest->last_pgp_signature = 0;
10351 dest->forcefield_name = 0;
10353 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10354 dest->first_trajectory_frame_set_input_file_pos =
10355 src->first_trajectory_frame_set_input_file_pos;
10356 dest->last_trajectory_frame_set_input_file_pos =
10357 src->last_trajectory_frame_set_input_file_pos;
10358 dest->current_trajectory_frame_set_input_file_pos =
10359 src->current_trajectory_frame_set_input_file_pos;
10360 dest->first_trajectory_frame_set_output_file_pos =
10361 src->first_trajectory_frame_set_output_file_pos;
10362 dest->last_trajectory_frame_set_output_file_pos =
10363 src->last_trajectory_frame_set_output_file_pos;
10364 dest->current_trajectory_frame_set_output_file_pos =
10365 src->current_trajectory_frame_set_output_file_pos;
10366 dest->frame_set_n_frames = src->frame_set_n_frames;
10367 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10368 dest->medium_stride_length = src->medium_stride_length;
10369 dest->long_stride_length = src->long_stride_length;
10371 dest->time_per_frame = src->time_per_frame;
10373 /* Currently the non trajectory data blocks are not copied since it
10374 * can lead to problems when freeing memory in a parallel block. */
10375 dest->n_particle_data_blocks = 0;
10376 dest->n_data_blocks = 0;
10377 dest->non_tr_particle_data = 0;
10378 dest->non_tr_data = 0;
10380 dest->compress_algo_pos = 0;
10381 dest->compress_algo_vel = 0;
10382 dest->distance_unit_exponential = -9;
10383 dest->compression_precision = 1000;
10385 frame_set->n_mapping_blocks = 0;
10386 frame_set->mappings = 0;
10387 frame_set->molecule_cnt_list = 0;
10389 frame_set->n_particle_data_blocks = 0;
10390 frame_set->n_data_blocks = 0;
10392 frame_set->tr_particle_data = 0;
10393 frame_set->tr_data = 0;
10395 frame_set->next_frame_set_file_pos = -1;
10396 frame_set->prev_frame_set_file_pos = -1;
10397 frame_set->medium_stride_next_frame_set_file_pos = -1;
10398 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10399 frame_set->long_stride_next_frame_set_file_pos = -1;
10400 frame_set->long_stride_prev_frame_set_file_pos = -1;
10401 frame_set->first_frame = -1;
10403 dest->n_molecules = 0;
10404 dest->molecules = 0;
10405 dest->molecule_cnt_list = 0;
10406 dest->n_particles = src->n_particles;
10408 dest->endianness_32 = src->endianness_32;
10409 dest->endianness_64 = src->endianness_64;
10410 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10411 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10412 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10413 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10415 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10416 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10417 dest->current_trajectory_frame_set.n_frames = 0;
10419 return(TNG_SUCCESS);
10422 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10423 char *file_name, const int max_len)
10425 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10426 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10428 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10429 file_name[max_len - 1] = 0;
10431 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10433 return(TNG_FAILURE);
10435 return(TNG_SUCCESS);
10438 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10439 const char *file_name)
10444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10445 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10448 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10451 return(TNG_SUCCESS);
10454 if(tng_data->input_file)
10456 fclose(tng_data->input_file);
10459 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10460 temp = realloc(tng_data->input_file_path, len);
10463 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10464 __FILE__, __LINE__);
10465 free(tng_data->input_file_path);
10466 tng_data->input_file_path = 0;
10467 return(TNG_CRITICAL);
10469 tng_data->input_file_path = temp;
10471 strncpy(tng_data->input_file_path, file_name, len);
10473 return(tng_input_file_init(tng_data));
10476 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10477 char *file_name, const int max_len)
10479 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10480 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10482 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10483 file_name[max_len - 1] = 0;
10485 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10487 return(TNG_FAILURE);
10489 return(TNG_SUCCESS);
10492 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10493 const char *file_name)
10498 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10499 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10501 if(tng_data->output_file_path &&
10502 strcmp(tng_data->output_file_path, file_name) == 0)
10504 return(TNG_SUCCESS);
10507 if(tng_data->output_file)
10509 fclose(tng_data->output_file);
10512 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10513 temp = realloc(tng_data->output_file_path, len);
10516 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10517 __FILE__, __LINE__);
10518 free(tng_data->output_file_path);
10519 tng_data->output_file_path = 0;
10520 return(TNG_CRITICAL);
10522 tng_data->output_file_path = temp;
10524 strncpy(tng_data->output_file_path, file_name, len);
10526 return(tng_output_file_init(tng_data));
10529 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10530 (tng_trajectory_t tng_data,
10531 const char *file_name)
10536 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10537 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10539 if(tng_data->output_file_path &&
10540 strcmp(tng_data->output_file_path, file_name) == 0)
10542 return(TNG_SUCCESS);
10545 if(tng_data->output_file)
10547 fclose(tng_data->output_file);
10550 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10551 temp = realloc(tng_data->output_file_path, len);
10554 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10555 __FILE__, __LINE__);
10556 free(tng_data->output_file_path);
10557 tng_data->output_file_path = 0;
10558 return(TNG_CRITICAL);
10560 tng_data->output_file_path = temp;
10562 strncpy(tng_data->output_file_path, file_name, len);
10564 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10565 if(!tng_data->output_file)
10567 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10568 tng_data->output_file_path, __FILE__, __LINE__);
10569 return(TNG_CRITICAL);
10571 tng_data->input_file = tng_data->output_file;
10573 return(TNG_SUCCESS);
10576 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10577 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10579 tng_endianness_32 end_32;
10580 tng_endianness_64 end_64;
10582 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10583 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10585 if(tng_data->output_endianness_swap_func_32)
10587 /* If other endianness variants are added they must be added here as well */
10588 if(tng_data->output_endianness_swap_func_32 ==
10589 &tng_swap_byte_order_big_endian_32)
10591 end_32 = TNG_BIG_ENDIAN_32;
10593 else if(tng_data->output_endianness_swap_func_32 ==
10594 &tng_swap_byte_order_little_endian_32)
10596 end_32 = TNG_LITTLE_ENDIAN_32;
10600 return(TNG_FAILURE);
10605 end_32 = (tng_endianness_32)tng_data->endianness_32;
10608 if(tng_data->output_endianness_swap_func_64)
10610 /* If other endianness variants are added they must be added here as well */
10611 if(tng_data->output_endianness_swap_func_64 ==
10612 &tng_swap_byte_order_big_endian_64)
10614 end_64 = TNG_BIG_ENDIAN_64;
10616 else if(tng_data->output_endianness_swap_func_64 ==
10617 &tng_swap_byte_order_little_endian_64)
10619 end_64 = TNG_LITTLE_ENDIAN_64;
10623 return(TNG_FAILURE);
10628 end_64 = (tng_endianness_64)tng_data->endianness_64;
10631 if((int)end_32 != (int)end_64)
10633 return(TNG_FAILURE);
10636 if(end_32 == TNG_LITTLE_ENDIAN_32)
10638 *endianness = TNG_LITTLE_ENDIAN;
10641 else if(end_32 == TNG_BIG_ENDIAN_32)
10643 *endianness = TNG_BIG_ENDIAN;
10647 return(TNG_FAILURE);
10650 return(TNG_SUCCESS);
10653 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10654 (tng_trajectory_t tng_data,
10655 const tng_file_endianness endianness)
10657 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10659 /* Tne endianness cannot be changed if the data has already been written
10660 * to the output file. */
10661 if(ftello(tng_data->output_file) > 0)
10663 return(TNG_FAILURE);
10666 if(endianness == TNG_BIG_ENDIAN)
10668 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10670 tng_data->output_endianness_swap_func_32 = 0;
10674 tng_data->output_endianness_swap_func_32 =
10675 &tng_swap_byte_order_big_endian_32;
10677 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10679 tng_data->output_endianness_swap_func_64 = 0;
10683 tng_data->output_endianness_swap_func_64 =
10684 &tng_swap_byte_order_big_endian_64;
10686 return(TNG_SUCCESS);
10688 else if(endianness == TNG_LITTLE_ENDIAN)
10690 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10692 tng_data->output_endianness_swap_func_32 = 0;
10696 tng_data->output_endianness_swap_func_32 =
10697 &tng_swap_byte_order_little_endian_32;
10699 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10701 tng_data->output_endianness_swap_func_64 = 0;
10705 tng_data->output_endianness_swap_func_64 =
10706 &tng_swap_byte_order_little_endian_64;
10708 return(TNG_SUCCESS);
10711 /* If the specified endianness is neither big nor little endian return a
10713 return(TNG_FAILURE);
10716 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10717 (const tng_trajectory_t tng_data,
10718 char *name, const int max_len)
10720 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10721 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10723 strncpy(name, tng_data->first_program_name, max_len - 1);
10724 name[max_len - 1] = 0;
10726 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10728 return(TNG_FAILURE);
10730 return(TNG_SUCCESS);
10733 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10734 const char *new_name)
10738 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10739 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10741 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10743 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10745 free(tng_data->first_program_name);
10746 tng_data->first_program_name = 0;
10748 if(!tng_data->first_program_name)
10750 tng_data->first_program_name = malloc(len);
10751 if(!tng_data->first_program_name)
10753 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10754 __FILE__, __LINE__);
10755 return(TNG_CRITICAL);
10759 strncpy(tng_data->first_program_name, new_name, len);
10761 return(TNG_SUCCESS);
10764 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10765 (const tng_trajectory_t tng_data,
10766 char *name, const int max_len)
10768 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10769 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10771 strncpy(name, tng_data->last_program_name, max_len - 1);
10772 name[max_len - 1] = 0;
10774 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10776 return(TNG_FAILURE);
10778 return(TNG_SUCCESS);
10781 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10782 (tng_trajectory_t tng_data,
10783 const char *new_name)
10787 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10788 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10790 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10792 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10794 free(tng_data->last_program_name);
10795 tng_data->last_program_name = 0;
10797 if(!tng_data->last_program_name)
10799 tng_data->last_program_name = malloc(len);
10800 if(!tng_data->last_program_name)
10802 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10803 __FILE__, __LINE__);
10804 return(TNG_CRITICAL);
10808 strncpy(tng_data->last_program_name, new_name, len);
10810 return(TNG_SUCCESS);
10813 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10814 (const tng_trajectory_t tng_data,
10815 char *name, const int max_len)
10817 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10818 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10820 strncpy(name, tng_data->first_user_name, max_len - 1);
10821 name[max_len - 1] = 0;
10823 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10825 return(TNG_FAILURE);
10827 return(TNG_SUCCESS);
10830 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10831 (tng_trajectory_t tng_data,
10832 const char *new_name)
10836 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10837 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10839 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10841 /* If the currently stored string length is not enough to store the new
10842 * string it is freed and reallocated. */
10843 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10845 free(tng_data->first_user_name);
10846 tng_data->first_user_name = 0;
10848 if(!tng_data->first_user_name)
10850 tng_data->first_user_name = malloc(len);
10851 if(!tng_data->first_user_name)
10853 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10854 __FILE__, __LINE__);
10855 return(TNG_CRITICAL);
10859 strncpy(tng_data->first_user_name, new_name, len);
10861 return(TNG_SUCCESS);
10864 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10865 (const tng_trajectory_t tng_data,
10866 char *name, const int max_len)
10868 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10869 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10871 strncpy(name, tng_data->last_user_name, max_len - 1);
10872 name[max_len - 1] = 0;
10874 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10876 return(TNG_FAILURE);
10878 return(TNG_SUCCESS);
10881 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10882 (tng_trajectory_t tng_data,
10883 const char *new_name)
10887 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10888 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10890 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10892 /* If the currently stored string length is not enough to store the new
10893 * string it is freed and reallocated. */
10894 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10896 free(tng_data->last_user_name);
10897 tng_data->last_user_name = 0;
10899 if(!tng_data->last_user_name)
10901 tng_data->last_user_name = malloc(len);
10902 if(!tng_data->last_user_name)
10904 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10905 __FILE__, __LINE__);
10906 return(TNG_CRITICAL);
10910 strncpy(tng_data->last_user_name, new_name, len);
10912 return(TNG_SUCCESS);
10915 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10916 (const tng_trajectory_t tng_data,
10917 char *name, const int max_len)
10919 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10920 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10922 strncpy(name, tng_data->first_computer_name, max_len - 1);
10923 name[max_len - 1] = 0;
10925 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10927 return(TNG_FAILURE);
10929 return(TNG_SUCCESS);
10932 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10933 (tng_trajectory_t tng_data,
10934 const char *new_name)
10938 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10939 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10941 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10943 /* If the currently stored string length is not enough to store the new
10944 * string it is freed and reallocated. */
10945 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10947 free(tng_data->first_computer_name);
10948 tng_data->first_computer_name = 0;
10950 if(!tng_data->first_computer_name)
10952 tng_data->first_computer_name = malloc(len);
10953 if(!tng_data->first_computer_name)
10955 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10956 __FILE__, __LINE__);
10957 return(TNG_CRITICAL);
10961 strncpy(tng_data->first_computer_name, new_name, len);
10963 return(TNG_SUCCESS);
10966 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10967 (const tng_trajectory_t tng_data,
10968 char *name, const int max_len)
10970 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10971 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10973 strncpy(name, tng_data->last_computer_name, max_len - 1);
10974 name[max_len - 1] = 0;
10976 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10978 return(TNG_FAILURE);
10980 return(TNG_SUCCESS);
10983 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10984 (tng_trajectory_t tng_data,
10985 const char *new_name)
10989 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10990 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10992 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10994 /* If the currently stored string length is not enough to store the new
10995 * string it is freed and reallocated. */
10996 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10999 free(tng_data->last_computer_name);
11000 tng_data->last_computer_name = 0;
11002 if(!tng_data->last_computer_name)
11004 tng_data->last_computer_name = malloc(len);
11005 if(!tng_data->last_computer_name)
11007 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11008 __FILE__, __LINE__);
11009 return(TNG_CRITICAL);
11013 strncpy(tng_data->last_computer_name, new_name, len);
11015 return(TNG_SUCCESS);
11018 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
11019 (const tng_trajectory_t tng_data,
11020 char *signature, const int max_len)
11022 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11023 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11025 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
11026 signature[max_len - 1] = 0;
11028 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
11030 return(TNG_FAILURE);
11032 return(TNG_SUCCESS);
11035 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
11036 (tng_trajectory_t tng_data,
11037 const char *signature)
11041 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11042 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11044 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11046 /* If the currently stored string length is not enough to store the new
11047 * string it is freed and reallocated. */
11048 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
11051 free(tng_data->first_pgp_signature);
11052 tng_data->first_pgp_signature = 0;
11054 if(!tng_data->first_pgp_signature)
11056 tng_data->first_pgp_signature = malloc(len);
11057 if(!tng_data->first_pgp_signature)
11059 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11060 __FILE__, __LINE__);
11061 return(TNG_CRITICAL);
11065 strncpy(tng_data->first_pgp_signature, signature, len);
11067 return(TNG_SUCCESS);
11070 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11071 (const tng_trajectory_t tng_data,
11072 char *signature, const int max_len)
11074 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11075 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11077 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
11078 signature[max_len - 1] = 0;
11080 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
11082 return(TNG_FAILURE);
11084 return(TNG_SUCCESS);
11087 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11088 (tng_trajectory_t tng_data,
11089 const char *signature)
11093 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11094 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11096 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11098 /* If the currently stored string length is not enough to store the new
11099 * string it is freed and reallocated. */
11100 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
11103 free(tng_data->last_pgp_signature);
11104 tng_data->last_pgp_signature = 0;
11106 if(!tng_data->last_pgp_signature)
11108 tng_data->last_pgp_signature = malloc(len);
11109 if(!tng_data->last_pgp_signature)
11111 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11112 __FILE__, __LINE__);
11113 return(TNG_CRITICAL);
11117 strncpy(tng_data->last_pgp_signature, signature, len);
11119 return(TNG_SUCCESS);
11122 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11123 (const tng_trajectory_t tng_data,
11124 char *name, const int max_len)
11126 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11127 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11129 strncpy(name, tng_data->forcefield_name, max_len - 1);
11130 name[max_len - 1] = 0;
11132 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11134 return(TNG_FAILURE);
11136 return(TNG_SUCCESS);
11139 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11140 (tng_trajectory_t tng_data,
11141 const char *new_name)
11145 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11146 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11148 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11150 /* If the currently stored string length is not enough to store the new
11151 * string it is freed and reallocated. */
11152 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11154 free(tng_data->forcefield_name);
11155 tng_data->forcefield_name = 0;
11157 if(!tng_data->forcefield_name)
11159 tng_data->forcefield_name = malloc(len);
11160 if(!tng_data->forcefield_name)
11162 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11163 __FILE__, __LINE__);
11164 return(TNG_CRITICAL);
11168 strncpy(tng_data->forcefield_name, new_name, len);
11170 return(TNG_SUCCESS);
11173 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11174 (const tng_trajectory_t tng_data,
11177 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11178 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11180 *len = tng_data->medium_stride_length;
11182 return(TNG_SUCCESS);
11185 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11186 (tng_trajectory_t tng_data,
11189 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11191 if(len >= tng_data->long_stride_length)
11193 return(TNG_FAILURE);
11195 tng_data->medium_stride_length = len;
11197 return(TNG_SUCCESS);
11200 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11201 (const tng_trajectory_t tng_data,
11204 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11205 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11207 *len = tng_data->long_stride_length;
11209 return(TNG_SUCCESS);
11212 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11213 (tng_trajectory_t tng_data,
11216 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11218 if(len <= tng_data->medium_stride_length)
11220 return(TNG_FAILURE);
11222 tng_data->long_stride_length = len;
11224 return(TNG_SUCCESS);
11227 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11228 (const tng_trajectory_t tng_data,
11231 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11232 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11234 *time = tng_data->time_per_frame;
11236 return(TNG_SUCCESS);
11239 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11240 (tng_trajectory_t tng_data,
11243 tng_trajectory_frame_set_t frame_set;
11245 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11246 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11248 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11250 return(TNG_SUCCESS);
11253 frame_set = &tng_data->current_trajectory_frame_set;
11255 /* If the current frame set is not finished write it to disk before
11256 changing time per frame. */
11257 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11259 frame_set->n_frames = frame_set->n_unwritten_frames;
11260 tng_frame_set_write(tng_data, TNG_USE_HASH);
11262 tng_data->time_per_frame = time;
11264 return(TNG_SUCCESS);
11267 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11268 (const tng_trajectory_t tng_data,
11271 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11272 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11274 *len = tng_data->input_file_len;
11276 return(TNG_SUCCESS);
11279 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11280 (const tng_trajectory_t tng_data,
11283 tng_gen_block_t block;
11284 tng_function_status stat;
11285 int64_t file_pos, last_file_pos, first_frame, n_frames;
11287 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11288 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11289 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11291 file_pos = ftello(tng_data->input_file);
11292 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11294 if(last_file_pos <= 0)
11296 return(TNG_FAILURE);
11299 tng_block_init(&block);
11300 fseeko(tng_data->input_file,
11303 /* Read block headers first to see that a frame set block is found. */
11304 stat = tng_block_header_read(tng_data, block);
11305 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11307 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11308 __FILE__, __LINE__);
11309 tng_block_destroy(&block);
11310 return(TNG_FAILURE);
11312 tng_block_destroy(&block);
11314 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11316 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11317 __FILE__, __LINE__);
11318 return(TNG_CRITICAL);
11320 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11322 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11323 __FILE__, __LINE__);
11324 return(TNG_CRITICAL);
11326 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11328 *n = first_frame + n_frames;
11330 return(TNG_SUCCESS);
11333 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11334 (const tng_trajectory_t tng_data,
11337 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11339 *precision = tng_data->compression_precision;
11341 return(TNG_SUCCESS);
11344 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11345 (tng_trajectory_t tng_data,
11346 const double precision)
11348 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11350 tng_data->compression_precision = precision;
11352 return(TNG_SUCCESS);
11355 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11356 (tng_trajectory_t tng_data,
11359 tng_molecule_t mol;
11363 tng_function_status stat;
11364 int64_t diff, n_mod, n_impl;
11366 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11368 diff = n - tng_data->n_particles;
11370 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11371 if(stat == TNG_SUCCESS)
11373 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11375 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11376 __FILE__, __LINE__);
11377 return(TNG_FAILURE);
11379 diff -= n_impl * mol->n_atoms;
11384 if(stat == TNG_SUCCESS)
11386 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11389 return(TNG_SUCCESS);
11393 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11394 fprintf(stderr, "particle count.\n");
11395 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11396 __FILE__, __LINE__);
11397 /* FIXME: Should we set the count of all other molecules to 0 and add
11398 * implicit molecules? */
11399 return(TNG_FAILURE);
11401 if(stat != TNG_SUCCESS)
11403 stat = tng_molecule_add(tng_data,
11404 "TNG_IMPLICIT_MOL",
11406 if(stat != TNG_SUCCESS)
11410 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11411 if(stat != TNG_SUCCESS)
11415 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11416 if(stat != TNG_SUCCESS)
11420 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11421 if(stat != TNG_SUCCESS)
11428 if(mol->n_atoms > 1)
11430 n_mod = diff % mol->n_atoms;
11433 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11434 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11435 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11436 __FILE__, __LINE__);
11437 return(TNG_FAILURE);
11439 diff /= mol->n_atoms;
11442 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11447 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11448 (const tng_trajectory_t tng_data,
11451 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11452 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11454 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11456 *n = tng_data->n_particles;
11460 *n = tng_data->current_trajectory_frame_set.n_particles;
11463 return(TNG_SUCCESS);
11466 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11467 (const tng_trajectory_t tng_data,
11470 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11471 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11473 *variable = tng_data->var_num_atoms_flag;
11475 return(TNG_SUCCESS);
11478 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11479 (const tng_trajectory_t tng_data,
11482 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11483 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11485 *n = tng_data->n_molecules;
11487 return(TNG_SUCCESS);
11490 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11491 (const tng_trajectory_t tng_data,
11494 int64_t *cnt_list = 0, cnt = 0, i;
11496 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11497 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11499 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11503 return(TNG_FAILURE);
11506 for(i = 0; i < tng_data->n_molecules; i++)
11508 cnt += cnt_list[i];
11513 return(TNG_SUCCESS);
11516 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11517 (const tng_trajectory_t tng_data,
11518 int64_t **mol_cnt_list)
11520 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11522 if(tng_data->var_num_atoms_flag)
11524 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11529 *mol_cnt_list = tng_data->molecule_cnt_list;
11531 if(*mol_cnt_list == 0)
11533 return(TNG_FAILURE);
11535 return(TNG_SUCCESS);
11538 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11539 (const tng_trajectory_t tng_data,
11542 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11543 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11545 *exp = tng_data->distance_unit_exponential;
11547 return(TNG_SUCCESS);
11550 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11551 (const tng_trajectory_t tng_data,
11554 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11556 tng_data->distance_unit_exponential = exp;
11558 return(TNG_SUCCESS);
11561 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11562 (const tng_trajectory_t tng_data,
11565 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11566 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11568 *n = tng_data->frame_set_n_frames;
11570 return(TNG_SUCCESS);
11573 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11574 (const tng_trajectory_t tng_data,
11577 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11579 tng_data->frame_set_n_frames = n;
11581 return(TNG_SUCCESS);
11584 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11585 (const tng_trajectory_t tng_data,
11588 int64_t long_stride_length, medium_stride_length;
11589 int64_t file_pos, orig_frame_set_file_pos;
11590 tng_trajectory_frame_set_t frame_set;
11591 struct tng_trajectory_frame_set orig_frame_set;
11592 tng_gen_block_t block;
11593 tng_function_status stat;
11596 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11597 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11599 orig_frame_set = tng_data->current_trajectory_frame_set;
11601 frame_set = &tng_data->current_trajectory_frame_set;
11603 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11604 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11608 *n = tng_data->n_trajectory_frame_sets = cnt;
11609 return(TNG_SUCCESS);
11612 tng_block_init(&block);
11613 fseeko(tng_data->input_file,
11616 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11617 /* Read block headers first to see what block is found. */
11618 stat = tng_block_header_read(tng_data, block);
11619 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11621 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11622 __FILE__, __LINE__);
11623 tng_block_destroy(&block);
11624 return(TNG_CRITICAL);
11627 if(tng_block_read_next(tng_data, block,
11628 TNG_SKIP_HASH) != TNG_SUCCESS)
11630 tng_block_destroy(&block);
11631 return(TNG_CRITICAL);
11636 long_stride_length = tng_data->long_stride_length;
11637 medium_stride_length = tng_data->medium_stride_length;
11639 /* Take long steps forward until a long step forward would be too long or
11640 * the last frame set is found */
11641 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11642 while(file_pos > 0)
11646 cnt += long_stride_length;
11647 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11648 /* Read block headers first to see what block is found. */
11649 stat = tng_block_header_read(tng_data, block);
11650 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11652 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11653 file_pos, __FILE__, __LINE__);
11654 tng_block_destroy(&block);
11655 return(TNG_CRITICAL);
11658 if(tng_block_read_next(tng_data, block,
11659 TNG_SKIP_HASH) != TNG_SUCCESS)
11661 tng_block_destroy(&block);
11662 return(TNG_CRITICAL);
11665 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11668 /* Take medium steps forward until a medium step forward would be too long
11669 * or the last frame set is found */
11670 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11671 while(file_pos > 0)
11675 cnt += medium_stride_length;
11676 fseeko(tng_data->input_file,
11679 /* Read block headers first to see what block is found. */
11680 stat = tng_block_header_read(tng_data, block);
11681 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11683 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11684 file_pos, __FILE__, __LINE__);
11685 tng_block_destroy(&block);
11686 return(TNG_CRITICAL);
11689 if(tng_block_read_next(tng_data, block,
11690 TNG_SKIP_HASH) != TNG_SUCCESS)
11692 tng_block_destroy(&block);
11693 return(TNG_CRITICAL);
11696 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11699 /* Take one step forward until the last frame set is found */
11700 file_pos = frame_set->next_frame_set_file_pos;
11701 while(file_pos > 0)
11706 fseeko(tng_data->input_file,
11709 /* Read block headers first to see what block is found. */
11710 stat = tng_block_header_read(tng_data, block);
11711 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11713 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11714 file_pos, __FILE__, __LINE__);
11715 tng_block_destroy(&block);
11716 return(TNG_CRITICAL);
11719 if(tng_block_read_next(tng_data, block,
11720 TNG_SKIP_HASH) != TNG_SUCCESS)
11722 tng_block_destroy(&block);
11723 return(TNG_CRITICAL);
11726 file_pos = frame_set->next_frame_set_file_pos;
11729 tng_block_destroy(&block);
11731 *n = tng_data->n_trajectory_frame_sets = cnt;
11733 *frame_set = orig_frame_set;
11734 /* The mapping block in the original frame set has been freed when reading
11735 * other frame sets. */
11736 frame_set->mappings = 0;
11737 frame_set->n_mapping_blocks = 0;
11739 fseeko(tng_data->input_file,
11740 tng_data->first_trajectory_frame_set_input_file_pos,
11743 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11745 return(TNG_SUCCESS);
11748 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11749 (const tng_trajectory_t tng_data,
11750 tng_trajectory_frame_set_t *frame_set_p)
11752 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11754 *frame_set_p = &tng_data->current_trajectory_frame_set;
11756 return(TNG_SUCCESS);
11759 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11760 (tng_trajectory_t tng_data,
11763 int64_t long_stride_length, medium_stride_length;
11764 int64_t file_pos, curr_nr = 0, n_frame_sets;
11765 tng_trajectory_frame_set_t frame_set;
11766 tng_gen_block_t block;
11767 tng_function_status stat;
11769 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11770 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11772 frame_set = &tng_data->current_trajectory_frame_set;
11774 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11776 if(stat != TNG_SUCCESS)
11781 if(nr >= n_frame_sets)
11783 return(TNG_FAILURE);
11786 long_stride_length = tng_data->long_stride_length;
11787 medium_stride_length = tng_data->medium_stride_length;
11789 /* FIXME: The frame set number of the current frame set is not stored */
11791 if(nr < n_frame_sets - 1 - nr)
11793 /* Start from the beginning */
11794 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11798 /* Start from the end */
11799 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11800 curr_nr = n_frame_sets - 1;
11804 return(TNG_FAILURE);
11807 tng_block_init(&block);
11808 fseeko(tng_data->input_file,
11811 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11812 /* Read block headers first to see what block is found. */
11813 stat = tng_block_header_read(tng_data, block);
11814 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11816 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11817 __FILE__, __LINE__);
11818 tng_block_destroy(&block);
11819 return(TNG_CRITICAL);
11822 if(tng_block_read_next(tng_data, block,
11823 TNG_SKIP_HASH) != TNG_SUCCESS)
11825 tng_block_destroy(&block);
11826 return(TNG_CRITICAL);
11831 tng_block_destroy(&block);
11832 return(TNG_SUCCESS);
11835 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11837 /* Take long steps forward until a long step forward would be too long or
11838 * the right frame set is found */
11839 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11841 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11844 curr_nr += long_stride_length;
11845 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11846 /* Read block headers first to see what block is found. */
11847 stat = tng_block_header_read(tng_data, block);
11848 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11850 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11851 file_pos, __FILE__, __LINE__);
11852 tng_block_destroy(&block);
11853 return(TNG_CRITICAL);
11856 if(tng_block_read_next(tng_data, block,
11857 TNG_SKIP_HASH) != TNG_SUCCESS)
11859 tng_block_destroy(&block);
11860 return(TNG_CRITICAL);
11864 tng_block_destroy(&block);
11865 return(TNG_SUCCESS);
11870 /* Take medium steps forward until a medium step forward would be too long
11871 * or the right frame set is found */
11872 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11874 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11877 curr_nr += medium_stride_length;
11878 fseeko(tng_data->input_file,
11881 /* Read block headers first to see what block is found. */
11882 stat = tng_block_header_read(tng_data, block);
11883 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11885 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11886 file_pos, __FILE__, __LINE__);
11887 tng_block_destroy(&block);
11888 return(TNG_CRITICAL);
11891 if(tng_block_read_next(tng_data, block,
11892 TNG_SKIP_HASH) != TNG_SUCCESS)
11894 tng_block_destroy(&block);
11895 return(TNG_CRITICAL);
11899 tng_block_destroy(&block);
11900 return(TNG_SUCCESS);
11905 /* Take one step forward until the right frame set is found */
11906 while(file_pos > 0 && curr_nr < nr)
11908 file_pos = frame_set->next_frame_set_file_pos;
11913 fseeko(tng_data->input_file,
11916 /* Read block headers first to see what block is found. */
11917 stat = tng_block_header_read(tng_data, block);
11918 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11920 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11921 file_pos, __FILE__, __LINE__);
11922 tng_block_destroy(&block);
11923 return(TNG_CRITICAL);
11926 if(tng_block_read_next(tng_data, block,
11927 TNG_SKIP_HASH) != TNG_SUCCESS)
11929 tng_block_destroy(&block);
11930 return(TNG_CRITICAL);
11934 tng_block_destroy(&block);
11935 return(TNG_SUCCESS);
11940 /* Take long steps backward until a long step backward would be too long
11941 * or the right frame set is found */
11942 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11944 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11947 curr_nr -= long_stride_length;
11948 fseeko(tng_data->input_file,
11951 /* Read block headers first to see what block is found. */
11952 stat = tng_block_header_read(tng_data, block);
11953 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11955 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11956 file_pos, __FILE__, __LINE__);
11957 tng_block_destroy(&block);
11958 return(TNG_CRITICAL);
11961 if(tng_block_read_next(tng_data, block,
11962 TNG_SKIP_HASH) != TNG_SUCCESS)
11964 tng_block_destroy(&block);
11965 return(TNG_CRITICAL);
11969 tng_block_destroy(&block);
11970 return(TNG_SUCCESS);
11975 /* Take medium steps backward until a medium step backward would be too long
11976 * or the right frame set is found */
11977 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11979 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11982 curr_nr -= medium_stride_length;
11983 fseeko(tng_data->input_file,
11986 /* Read block headers first to see what block is found. */
11987 stat = tng_block_header_read(tng_data, block);
11988 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11990 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11991 file_pos, __FILE__, __LINE__);
11992 tng_block_destroy(&block);
11993 return(TNG_CRITICAL);
11996 if(tng_block_read_next(tng_data, block,
11997 TNG_SKIP_HASH) != TNG_SUCCESS)
11999 tng_block_destroy(&block);
12000 return(TNG_CRITICAL);
12004 tng_block_destroy(&block);
12005 return(TNG_SUCCESS);
12010 /* Take one step backward until the right frame set is found */
12011 while(file_pos > 0 && curr_nr > nr)
12013 file_pos = frame_set->prev_frame_set_file_pos;
12017 fseeko(tng_data->input_file,
12020 /* Read block headers first to see what block is found. */
12021 stat = tng_block_header_read(tng_data, block);
12022 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12024 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12025 file_pos, __FILE__, __LINE__);
12026 tng_block_destroy(&block);
12027 return(TNG_CRITICAL);
12030 if(tng_block_read_next(tng_data, block,
12031 TNG_SKIP_HASH) != TNG_SUCCESS)
12033 tng_block_destroy(&block);
12034 return(TNG_CRITICAL);
12038 tng_block_destroy(&block);
12039 return(TNG_SUCCESS);
12044 /* If for some reason the current frame set is not yet found,
12045 * take one step forward until the right frame set is found */
12046 while(file_pos > 0 && curr_nr < nr)
12048 file_pos = frame_set->next_frame_set_file_pos;
12052 fseeko(tng_data->input_file,
12055 /* Read block headers first to see what block is found. */
12056 stat = tng_block_header_read(tng_data, block);
12057 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12059 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12060 file_pos, __FILE__, __LINE__);
12061 tng_block_destroy(&block);
12062 return(TNG_CRITICAL);
12065 if(tng_block_read_next(tng_data, block,
12066 TNG_SKIP_HASH) != TNG_SUCCESS)
12068 tng_block_destroy(&block);
12069 return(TNG_CRITICAL);
12073 tng_block_destroy(&block);
12074 return(TNG_SUCCESS);
12079 tng_block_destroy(&block);
12080 return(TNG_FAILURE);
12083 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12084 (tng_trajectory_t tng_data,
12085 const int64_t frame)
12087 int64_t first_frame, last_frame, n_frames_per_frame_set;
12088 int64_t long_stride_length, medium_stride_length;
12089 int64_t file_pos, temp_frame, n_frames;
12090 tng_trajectory_frame_set_t frame_set;
12091 tng_gen_block_t block;
12092 tng_function_status stat;
12094 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12095 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
12097 frame_set = &tng_data->current_trajectory_frame_set;
12099 tng_block_init(&block);
12101 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
12103 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12104 fseeko(tng_data->input_file,
12107 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12108 /* Read block headers first to see what block is found. */
12109 stat = tng_block_header_read(tng_data, block);
12110 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12112 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12113 file_pos, __FILE__, __LINE__);
12114 tng_block_destroy(&block);
12115 return(TNG_CRITICAL);
12118 if(tng_block_read_next(tng_data, block,
12119 TNG_SKIP_HASH) != TNG_SUCCESS)
12121 tng_block_destroy(&block);
12122 return(TNG_CRITICAL);
12126 first_frame = tng_max_i64(frame_set->first_frame, 0);
12127 last_frame = first_frame + frame_set->n_frames - 1;
12128 /* Is this the right frame set? */
12129 if(first_frame <= frame && frame <= last_frame)
12131 tng_block_destroy(&block);
12132 return(TNG_SUCCESS);
12135 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12136 long_stride_length = tng_data->long_stride_length;
12137 medium_stride_length = tng_data->medium_stride_length;
12139 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12142 if(temp_frame - first_frame > n_frames_per_frame_set)
12144 n_frames_per_frame_set = temp_frame - first_frame;
12148 tng_num_frames_get(tng_data, &n_frames);
12150 if(frame >= n_frames)
12152 tng_block_destroy(&block);
12153 return(TNG_FAILURE);
12156 if(first_frame - frame >= frame ||
12157 frame - last_frame >
12158 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12160 /* Start from the beginning */
12161 if(first_frame - frame >= frame)
12163 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12167 tng_block_destroy(&block);
12168 return(TNG_FAILURE);
12171 /* Start from the end */
12172 else if(frame - first_frame > (n_frames - 1) - frame)
12174 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12176 /* If the last frame set position is not set start from the current
12177 * frame set, since it will be closer than the first frame set. */
12179 /* Start from current */
12182 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12187 fseeko(tng_data->input_file,
12190 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12191 /* Read block headers first to see what block is found. */
12192 stat = tng_block_header_read(tng_data, block);
12193 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12195 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12196 file_pos, __FILE__, __LINE__);
12197 tng_block_destroy(&block);
12198 return(TNG_CRITICAL);
12201 if(tng_block_read_next(tng_data, block,
12202 TNG_SKIP_HASH) != TNG_SUCCESS)
12204 tng_block_destroy(&block);
12205 return(TNG_CRITICAL);
12210 first_frame = tng_max_i64(frame_set->first_frame, 0);
12211 last_frame = first_frame + frame_set->n_frames - 1;
12213 if(frame >= first_frame && frame <= last_frame)
12215 tng_block_destroy(&block);
12216 return(TNG_SUCCESS);
12219 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12221 /* Take long steps forward until a long step forward would be too long or
12222 * the right frame set is found */
12223 while(file_pos > 0 && first_frame + long_stride_length *
12224 n_frames_per_frame_set <= frame)
12226 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12229 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12230 /* Read block headers first to see what block is found. */
12231 stat = tng_block_header_read(tng_data, block);
12232 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12234 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12235 file_pos, __FILE__, __LINE__);
12236 tng_block_destroy(&block);
12237 return(TNG_CRITICAL);
12240 if(tng_block_read_next(tng_data, block,
12241 TNG_SKIP_HASH) != TNG_SUCCESS)
12243 tng_block_destroy(&block);
12244 return(TNG_CRITICAL);
12247 first_frame = tng_max_i64(frame_set->first_frame, 0);
12248 last_frame = first_frame + frame_set->n_frames - 1;
12249 if(frame >= first_frame && frame <= last_frame)
12251 tng_block_destroy(&block);
12252 return(TNG_SUCCESS);
12256 /* Take medium steps forward until a medium step forward would be too long
12257 * or the right frame set is found */
12258 while(file_pos > 0 && first_frame + medium_stride_length *
12259 n_frames_per_frame_set <= frame)
12261 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12264 fseeko(tng_data->input_file,
12267 /* Read block headers first to see what block is found. */
12268 stat = tng_block_header_read(tng_data, block);
12269 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12271 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12272 file_pos, __FILE__, __LINE__);
12273 tng_block_destroy(&block);
12274 return(TNG_CRITICAL);
12277 if(tng_block_read_next(tng_data, block,
12278 TNG_SKIP_HASH) != TNG_SUCCESS)
12280 tng_block_destroy(&block);
12281 return(TNG_CRITICAL);
12284 first_frame = tng_max_i64(frame_set->first_frame, 0);
12285 last_frame = first_frame + frame_set->n_frames - 1;
12286 if(frame >= first_frame && frame <= last_frame)
12288 tng_block_destroy(&block);
12289 return(TNG_SUCCESS);
12293 /* Take one step forward until the right frame set is found */
12294 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12296 file_pos = frame_set->next_frame_set_file_pos;
12299 fseeko(tng_data->input_file,
12302 /* Read block headers first to see what block is found. */
12303 stat = tng_block_header_read(tng_data, block);
12304 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12306 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12307 file_pos, __FILE__, __LINE__);
12308 tng_block_destroy(&block);
12309 return(TNG_CRITICAL);
12312 if(tng_block_read_next(tng_data, block,
12313 TNG_SKIP_HASH) != TNG_SUCCESS)
12315 tng_block_destroy(&block);
12316 return(TNG_CRITICAL);
12319 first_frame = tng_max_i64(frame_set->first_frame, 0);
12320 last_frame = first_frame + frame_set->n_frames - 1;
12321 if(frame >= first_frame && frame <= last_frame)
12323 tng_block_destroy(&block);
12324 return(TNG_SUCCESS);
12328 /* Take long steps backward until a long step backward would be too long
12329 * or the right frame set is found */
12330 while(file_pos > 0 && first_frame - long_stride_length *
12331 n_frames_per_frame_set >= frame)
12333 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12336 fseeko(tng_data->input_file,
12339 /* Read block headers first to see what block is found. */
12340 stat = tng_block_header_read(tng_data, block);
12341 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12343 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12344 file_pos, __FILE__, __LINE__);
12345 tng_block_destroy(&block);
12346 return(TNG_CRITICAL);
12349 if(tng_block_read_next(tng_data, block,
12350 TNG_SKIP_HASH) != TNG_SUCCESS)
12352 tng_block_destroy(&block);
12353 return(TNG_CRITICAL);
12356 first_frame = tng_max_i64(frame_set->first_frame, 0);
12357 last_frame = first_frame + frame_set->n_frames - 1;
12358 if(frame >= first_frame && frame <= last_frame)
12360 tng_block_destroy(&block);
12361 return(TNG_SUCCESS);
12365 /* Take medium steps backward until a medium step backward would be too long
12366 * or the right frame set is found */
12367 while(file_pos > 0 && first_frame - medium_stride_length *
12368 n_frames_per_frame_set >= frame)
12370 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12373 fseeko(tng_data->input_file,
12376 /* Read block headers first to see what block is found. */
12377 stat = tng_block_header_read(tng_data, block);
12378 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12380 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12381 file_pos, __FILE__, __LINE__);
12382 tng_block_destroy(&block);
12383 return(TNG_CRITICAL);
12386 if(tng_block_read_next(tng_data, block,
12387 TNG_SKIP_HASH) != TNG_SUCCESS)
12389 tng_block_destroy(&block);
12390 return(TNG_CRITICAL);
12393 first_frame = tng_max_i64(frame_set->first_frame, 0);
12394 last_frame = first_frame + frame_set->n_frames - 1;
12395 if(frame >= first_frame && frame <= last_frame)
12397 tng_block_destroy(&block);
12398 return(TNG_SUCCESS);
12402 /* Take one step backward until the right frame set is found */
12403 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12405 file_pos = frame_set->prev_frame_set_file_pos;
12408 fseeko(tng_data->input_file,
12411 /* Read block headers first to see what block is found. */
12412 stat = tng_block_header_read(tng_data, block);
12413 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12415 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12416 file_pos, __FILE__, __LINE__);
12417 tng_block_destroy(&block);
12418 return(TNG_CRITICAL);
12421 if(tng_block_read_next(tng_data, block,
12422 TNG_SKIP_HASH) != TNG_SUCCESS)
12424 tng_block_destroy(&block);
12425 return(TNG_CRITICAL);
12428 first_frame = tng_max_i64(frame_set->first_frame, 0);
12429 last_frame = first_frame + frame_set->n_frames - 1;
12430 if(frame >= first_frame && frame <= last_frame)
12432 tng_block_destroy(&block);
12433 return(TNG_SUCCESS);
12437 /* If for some reason the current frame set is not yet found,
12438 * take one step forward until the right frame set is found */
12439 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12441 file_pos = frame_set->next_frame_set_file_pos;
12444 fseeko(tng_data->input_file,
12447 /* Read block headers first to see what block is found. */
12448 stat = tng_block_header_read(tng_data, block);
12449 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12451 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12452 file_pos, __FILE__, __LINE__);
12453 tng_block_destroy(&block);
12454 return(TNG_CRITICAL);
12457 if(tng_block_read_next(tng_data, block,
12458 TNG_SKIP_HASH) != TNG_SUCCESS)
12460 tng_block_destroy(&block);
12461 return(TNG_CRITICAL);
12464 first_frame = tng_max_i64(frame_set->first_frame, 0);
12465 last_frame = first_frame + frame_set->n_frames - 1;
12466 if(frame >= first_frame && frame <= last_frame)
12468 tng_block_destroy(&block);
12469 return(TNG_SUCCESS);
12473 tng_block_destroy(&block);
12474 return(TNG_FAILURE);
12477 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12478 (const tng_trajectory_t tng_data,
12479 const tng_trajectory_frame_set_t frame_set,
12484 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12485 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12487 *pos = frame_set->next_frame_set_file_pos;
12489 return(TNG_SUCCESS);
12492 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12493 (const tng_trajectory_t tng_data,
12494 const tng_trajectory_frame_set_t frame_set,
12499 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12500 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12502 *pos = frame_set->prev_frame_set_file_pos;
12504 return(TNG_SUCCESS);
12507 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12508 (const tng_trajectory_t tng_data,
12509 const tng_trajectory_frame_set_t frame_set,
12510 int64_t *first_frame,
12511 int64_t *last_frame)
12515 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12516 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12517 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12519 *first_frame = frame_set->first_frame;
12520 *last_frame = *first_frame + frame_set->n_frames - 1;
12522 return(TNG_SUCCESS);
12525 /** Translate from the particle numbering used in a frame set to the real
12526 * particle numbering - used in the molecule description.
12527 * @param frame_set is the frame_set containing the mappings to use.
12528 * @param local is the index number of the atom in this frame set
12529 * @param real is set to the index of the atom in the molecular system.
12530 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12533 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12534 (const tng_trajectory_frame_set_t frame_set,
12535 const int64_t local,
12538 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12539 tng_particle_mapping_t mapping;
12543 return(TNG_SUCCESS);
12545 for(i = 0; i < n_blocks; i++)
12547 mapping = &frame_set->mappings[i];
12548 first = mapping->num_first_particle;
12549 if(local < first ||
12550 local >= first + mapping->n_particles)
12554 *real = mapping->real_particle_numbers[local-first];
12555 return(TNG_SUCCESS);
12558 return(TNG_FAILURE);
12561 /** Translate from the real particle numbering to the particle numbering
12562 * used in a frame set.
12563 * @param frame_set is the frame_set containing the mappings to use.
12564 * @param real is the index number of the atom in the molecular system.
12565 * @param local is set to the index of the atom in this frame set.
12566 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12569 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12570 (const tng_trajectory_frame_set_t frame_set,
12571 const int64_t real,
12574 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12575 tng_particle_mapping_t mapping;
12579 return(TNG_SUCCESS);
12581 for(i = 0; i < n_blocks; i++)
12583 mapping = &frame_set->mappings[i];
12584 for(j = mapping->n_particles; j--;)
12586 if(mapping->real_particle_numbers[j] == real)
12589 return(TNG_SUCCESS);
12593 return(TNG_FAILURE);
12597 static tng_function_status tng_file_headers_len_get
12598 (tng_trajectory_t tng_data,
12602 tng_gen_block_t block;
12604 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12606 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12608 return(TNG_CRITICAL);
12613 orig_pos = ftello(tng_data->input_file);
12615 if(!tng_data->input_file_len)
12617 fseeko(tng_data->input_file, 0, SEEK_END);
12618 tng_data->input_file_len = ftello(tng_data->input_file);
12620 fseeko(tng_data->input_file, 0, SEEK_SET);
12622 tng_block_init(&block);
12623 /* Read through the headers of non-trajectory blocks (they come before the
12624 * trajectory blocks in the file) */
12625 while (*len < tng_data->input_file_len &&
12626 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12628 block->id != TNG_TRAJECTORY_FRAME_SET)
12630 *len += block->header_contents_size + block->block_contents_size;
12631 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12634 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
12636 tng_block_destroy(&block);
12638 return(TNG_SUCCESS);
12641 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12642 (tng_trajectory_t tng_data,
12643 const char hash_mode)
12645 int64_t prev_pos = 0;
12646 tng_gen_block_t block;
12648 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12650 tng_data->n_trajectory_frame_sets = 0;
12652 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12654 return(TNG_CRITICAL);
12657 if(!tng_data->input_file_len)
12659 fseeko(tng_data->input_file, 0, SEEK_END);
12660 tng_data->input_file_len = ftello(tng_data->input_file);
12662 fseeko(tng_data->input_file, 0, SEEK_SET);
12664 tng_block_init(&block);
12665 /* Non trajectory blocks (they come before the trajectory
12666 * blocks in the file) */
12667 while (prev_pos < tng_data->input_file_len &&
12668 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12670 block->id != TNG_TRAJECTORY_FRAME_SET)
12672 tng_block_read_next(tng_data, block, hash_mode);
12673 prev_pos = ftello(tng_data->input_file);
12676 /* Go back if a trajectory block was encountered */
12677 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12679 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
12682 tng_block_destroy(&block);
12684 return(TNG_SUCCESS);
12687 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12688 (tng_trajectory_t tng_data,
12689 const char hash_mode)
12692 int64_t len, orig_len, tot_len = 0, data_start_pos;
12693 tng_function_status stat;
12694 tng_gen_block_t block;
12696 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12698 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12700 return(TNG_CRITICAL);
12703 if(tng_data->n_trajectory_frame_sets > 0)
12705 stat = tng_file_headers_len_get(tng_data, &orig_len);
12706 if(stat != TNG_SUCCESS)
12711 tng_block_init(&block);
12712 block->name = malloc(TNG_MAX_STR_LEN);
12715 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12716 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12717 tng_block_destroy(&block);
12718 return(TNG_CRITICAL);
12720 strcpy(block->name, "GENERAL INFO");
12721 tng_block_header_len_calculate(tng_data, block, &len);
12723 tng_general_info_block_len_calculate(tng_data, &len);
12725 strcpy(block->name, "MOLECULES");
12726 tng_block_header_len_calculate(tng_data, block, &len);
12728 tng_molecules_block_len_calculate(tng_data, &len);
12731 for(i = 0; i < tng_data->n_data_blocks; i++)
12733 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12734 tng_block_header_len_calculate(tng_data, block, &len);
12736 tng_data_block_len_calculate(tng_data,
12737 (tng_particle_data_t)&tng_data->non_tr_data[i],
12738 TNG_FALSE, 1, 1, 1, 0,
12739 1, 0, &data_start_pos,
12743 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12745 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12746 tng_block_header_len_calculate(tng_data, block, &len);
12748 tng_data_block_len_calculate(tng_data,
12749 &tng_data->non_tr_particle_data[i],
12750 TNG_TRUE, 1, 1, 1, 0,
12751 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12756 tng_block_destroy(&block);
12758 if(tot_len > orig_len)
12760 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12763 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12766 /* TODO: If there is already frame set data written to this file (e.g. when
12767 * appending to an already existing file we might need to move frame sets to
12768 * the end of the file. */
12770 if(tng_general_info_block_write(tng_data, hash_mode)
12773 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12774 tng_data->input_file_path, __FILE__, __LINE__);
12775 return(TNG_CRITICAL);
12778 if(tng_molecules_block_write(tng_data, hash_mode)
12781 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12782 tng_data->input_file_path, __FILE__, __LINE__);
12783 return(TNG_CRITICAL);
12786 /* FIXME: Currently writing non-trajectory data blocks here.
12787 * Should perhaps be moved. */
12788 tng_block_init(&block);
12789 for(i = 0; i < tng_data->n_data_blocks; i++)
12791 block->id = tng_data->non_tr_data[i].block_id;
12792 tng_data_block_write(tng_data, block,
12796 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12798 block->id = tng_data->non_tr_particle_data[i].block_id;
12799 tng_particle_data_block_write(tng_data, block,
12803 tng_block_destroy(&block);
12805 return(TNG_SUCCESS);
12808 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12809 tng_gen_block_t block,
12810 const char hash_mode)
12812 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12813 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12817 case TNG_TRAJECTORY_FRAME_SET:
12818 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12819 case TNG_PARTICLE_MAPPING:
12820 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12821 case TNG_GENERAL_INFO:
12822 return(tng_general_info_block_read(tng_data, block, hash_mode));
12823 case TNG_MOLECULES:
12824 return(tng_molecules_block_read(tng_data, block, hash_mode));
12826 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12828 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12832 /* Skip to the next block */
12833 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12834 return(TNG_FAILURE);
12839 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12840 (tng_trajectory_t tng_data,
12841 const char hash_mode)
12844 tng_gen_block_t block;
12845 tng_function_status stat;
12847 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12849 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12851 return(TNG_CRITICAL);
12854 file_pos = ftello(tng_data->input_file);
12856 tng_block_init(&block);
12858 if(!tng_data->input_file_len)
12860 fseeko(tng_data->input_file, 0, SEEK_END);
12861 tng_data->input_file_len = ftello(tng_data->input_file);
12862 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12865 /* Read block headers first to see what block is found. */
12866 stat = tng_block_header_read(tng_data, block);
12867 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12870 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12871 file_pos, __FILE__, __LINE__);
12872 tng_block_destroy(&block);
12873 return(TNG_CRITICAL);
12876 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12878 if(tng_block_read_next(tng_data, block,
12879 hash_mode) == TNG_SUCCESS)
12881 tng_data->n_trajectory_frame_sets++;
12882 file_pos = ftello(tng_data->input_file);
12883 /* Read all blocks until next frame set block */
12884 stat = tng_block_header_read(tng_data, block);
12885 while(file_pos < tng_data->input_file_len &&
12886 stat != TNG_CRITICAL &&
12887 block->id != TNG_TRAJECTORY_FRAME_SET &&
12890 stat = tng_block_read_next(tng_data, block,
12892 if(stat != TNG_CRITICAL)
12894 file_pos = ftello(tng_data->input_file);
12895 if(file_pos < tng_data->input_file_len)
12897 stat = tng_block_header_read(tng_data, block);
12901 if(stat == TNG_CRITICAL)
12903 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12904 file_pos, __FILE__, __LINE__);
12905 tng_block_destroy(&block);
12909 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12911 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12915 tng_block_destroy(&block);
12917 return(TNG_SUCCESS);
12921 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12922 (tng_trajectory_t tng_data,
12923 const char hash_mode,
12924 const int64_t block_id)
12927 tng_gen_block_t block;
12928 tng_function_status stat;
12929 int found_flag = 1;
12931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12933 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12935 return(TNG_CRITICAL);
12938 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12942 /* No current frame set. This means that the first frame set must be
12945 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12950 fseeko(tng_data->input_file,
12956 return(TNG_FAILURE);
12959 tng_block_init(&block);
12961 if(!tng_data->input_file_len)
12963 fseeko(tng_data->input_file, 0, SEEK_END);
12964 tng_data->input_file_len = ftello(tng_data->input_file);
12965 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12968 /* Read block headers first to see what block is found. */
12969 stat = tng_block_header_read(tng_data, block);
12970 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12972 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12973 file_pos, __FILE__, __LINE__);
12974 tng_block_destroy(&block);
12975 return(TNG_CRITICAL);
12977 /* If the current frame set had already been read skip its block contents */
12980 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12982 /* Otherwiese read the frame set block */
12985 stat = tng_block_read_next(tng_data, block,
12987 if(stat != TNG_SUCCESS)
12989 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12990 tng_block_destroy(&block);
12994 file_pos = ftello(tng_data->input_file);
12998 /* Read only blocks of the requested ID
12999 * until next frame set block */
13000 stat = tng_block_header_read(tng_data, block);
13001 while(file_pos < tng_data->input_file_len &&
13002 stat != TNG_CRITICAL &&
13003 block->id != TNG_TRAJECTORY_FRAME_SET &&
13006 if(block->id == block_id)
13008 stat = tng_block_read_next(tng_data, block,
13010 if(stat != TNG_CRITICAL)
13012 file_pos = ftello(tng_data->input_file);
13014 if(file_pos < tng_data->input_file_len)
13016 stat = tng_block_header_read(tng_data, block);
13022 file_pos += (block->block_contents_size + block->header_contents_size);
13023 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13024 if(file_pos < tng_data->input_file_len)
13026 stat = tng_block_header_read(tng_data, block);
13030 if(stat == TNG_CRITICAL)
13032 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13033 file_pos, __FILE__, __LINE__);
13034 tng_block_destroy(&block);
13038 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13040 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13043 tng_block_destroy(&block);
13047 return(TNG_SUCCESS);
13051 return(TNG_FAILURE);
13055 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
13056 (tng_trajectory_t tng_data,
13057 const char hash_mode)
13061 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13063 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13065 return(TNG_CRITICAL);
13068 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13070 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13072 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13077 fseeko(tng_data->input_file,
13083 return(TNG_FAILURE);
13086 return(tng_frame_set_read(tng_data, hash_mode));
13089 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13090 (tng_trajectory_t tng_data,
13091 const char hash_mode,
13092 const int64_t block_id)
13095 tng_gen_block_t block;
13096 tng_function_status stat;
13098 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13100 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13102 return(TNG_CRITICAL);
13105 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13107 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13109 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13114 fseeko(tng_data->input_file,
13120 return(TNG_FAILURE);
13123 tng_block_init(&block);
13125 if(!tng_data->input_file_len)
13127 fseeko(tng_data->input_file, 0, SEEK_END);
13128 tng_data->input_file_len = ftello(tng_data->input_file);
13129 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13132 /* Read block headers first to see what block is found. */
13133 stat = tng_block_header_read(tng_data, block);
13134 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13136 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13137 file_pos, __FILE__, __LINE__);
13138 tng_block_destroy(&block);
13139 return(TNG_CRITICAL);
13142 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13144 if(tng_block_read_next(tng_data, block,
13145 hash_mode) == TNG_SUCCESS)
13147 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13150 tng_block_destroy(&block);
13155 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13156 const char hash_mode)
13159 tng_gen_block_t block;
13160 tng_trajectory_frame_set_t frame_set;
13161 tng_function_status stat;
13163 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13165 frame_set = &tng_data->current_trajectory_frame_set;
13167 if(frame_set->n_written_frames == frame_set->n_frames)
13169 return(TNG_SUCCESS);
13172 tng_data->current_trajectory_frame_set_output_file_pos =
13173 ftello(tng_data->output_file);
13174 tng_data->last_trajectory_frame_set_output_file_pos =
13175 tng_data->current_trajectory_frame_set_output_file_pos;
13177 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13179 return(TNG_FAILURE);
13182 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13184 tng_data->first_trajectory_frame_set_output_file_pos =
13185 tng_data->current_trajectory_frame_set_output_file_pos;
13188 tng_block_init(&block);
13190 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13192 tng_block_destroy(&block);
13193 return(TNG_FAILURE);
13196 /* Write non-particle data blocks */
13197 for(i = 0; i<frame_set->n_data_blocks; i++)
13199 block->id = frame_set->tr_data[i].block_id;
13200 tng_data_block_write(tng_data, block, i, hash_mode);
13202 /* Write the mapping blocks and particle data blocks*/
13203 if(frame_set->n_mapping_blocks)
13205 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13207 block->id = TNG_PARTICLE_MAPPING;
13208 if(frame_set->mappings[i].n_particles > 0)
13210 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13211 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13213 block->id = frame_set->tr_particle_data[j].block_id;
13214 tng_particle_data_block_write(tng_data, block,
13215 j, &frame_set->mappings[i],
13223 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13225 block->id = frame_set->tr_particle_data[i].block_id;
13226 tng_particle_data_block_write(tng_data, block,
13232 /* Update pointers in the general info block */
13233 stat = tng_header_pointers_update(tng_data, hash_mode);
13235 if(stat == TNG_SUCCESS)
13237 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13240 tng_block_destroy(&block);
13242 frame_set->n_unwritten_frames = 0;
13244 fflush(tng_data->output_file);
13249 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13250 (tng_trajectory_t tng_data,
13251 const char hash_mode)
13253 tng_trajectory_frame_set_t frame_set;
13255 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13257 frame_set = &tng_data->current_trajectory_frame_set;
13259 if(frame_set->n_unwritten_frames == 0)
13261 return(TNG_SUCCESS);
13263 frame_set->n_frames = frame_set->n_unwritten_frames;
13265 return(tng_frame_set_write(tng_data, hash_mode));
13268 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13269 (tng_trajectory_t tng_data,
13270 const int64_t first_frame,
13271 const int64_t n_frames)
13273 tng_gen_block_t block;
13274 tng_trajectory_frame_set_t frame_set;
13275 FILE *temp = tng_data->input_file;
13278 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13279 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13280 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13282 frame_set = &tng_data->current_trajectory_frame_set;
13284 curr_pos = ftello(tng_data->output_file);
13288 tng_file_headers_write(tng_data, TNG_USE_HASH);
13291 /* Set pointer to previous frame set to the one that was loaded
13293 * FIXME: This is a bit risky. If they are not added in order
13294 * it will be wrong. */
13295 if(tng_data->n_trajectory_frame_sets)
13297 frame_set->prev_frame_set_file_pos =
13298 tng_data->current_trajectory_frame_set_output_file_pos;
13301 tng_data->current_trajectory_frame_set_output_file_pos =
13302 ftello(tng_data->output_file);
13304 tng_data->n_trajectory_frame_sets++;
13306 /* Set the medium range pointers */
13307 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13309 frame_set->medium_stride_prev_frame_set_file_pos =
13310 tng_data->first_trajectory_frame_set_output_file_pos;
13312 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13314 /* FIXME: Currently only working if the previous frame set has its
13315 * medium stride pointer already set. This might need some fixing. */
13316 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13317 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13319 tng_block_init(&block);
13320 tng_data->input_file = tng_data->output_file;
13322 curr_pos = ftello(tng_data->output_file);
13323 fseeko(tng_data->output_file,
13324 frame_set->medium_stride_prev_frame_set_file_pos,
13327 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13329 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13330 __FILE__, __LINE__);
13331 tng_data->input_file = temp;
13332 tng_block_destroy(&block);
13333 return(TNG_CRITICAL);
13336 /* Read the next frame set from the previous frame set and one
13337 * medium stride step back */
13338 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13339 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13340 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13341 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13342 1, tng_data->output_file) == 0)
13344 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13345 tng_data->input_file = temp;
13346 tng_block_destroy(&block);
13347 return(TNG_CRITICAL);
13350 if(tng_data->input_endianness_swap_func_64)
13352 if(tng_data->input_endianness_swap_func_64(tng_data,
13353 &frame_set->medium_stride_prev_frame_set_file_pos)
13356 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13357 __FILE__, __LINE__);
13361 tng_block_destroy(&block);
13363 /* Set the long range pointers */
13364 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13366 frame_set->long_stride_prev_frame_set_file_pos =
13367 tng_data->first_trajectory_frame_set_output_file_pos;
13369 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13371 /* FIXME: Currently only working if the previous frame set has its
13372 * long stride pointer already set. This might need some fixing. */
13373 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13374 frame_set->long_stride_prev_frame_set_file_pos != 0)
13376 tng_block_init(&block);
13377 tng_data->input_file = tng_data->output_file;
13379 fseeko(tng_data->output_file,
13380 frame_set->long_stride_prev_frame_set_file_pos,
13383 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13385 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13386 __FILE__, __LINE__);
13387 tng_data->input_file = temp;
13388 tng_block_destroy(&block);
13389 return(TNG_CRITICAL);
13392 /* Read the next frame set from the previous frame set and one
13393 * long stride step back */
13394 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13395 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13397 tng_block_destroy(&block);
13399 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13400 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13401 1, tng_data->output_file) == 0)
13403 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13404 tng_data->input_file = temp;
13405 return(TNG_CRITICAL);
13408 if(tng_data->input_endianness_swap_func_64)
13410 if(tng_data->input_endianness_swap_func_64(tng_data,
13411 &frame_set->long_stride_prev_frame_set_file_pos)
13414 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13415 __FILE__, __LINE__);
13422 tng_data->input_file = temp;
13423 fseeko(tng_data->output_file, curr_pos, SEEK_SET);
13427 frame_set->first_frame = first_frame;
13428 frame_set->n_frames = n_frames;
13429 frame_set->n_written_frames = 0;
13430 frame_set->n_unwritten_frames = 0;
13431 frame_set->first_frame_time = -1;
13433 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13434 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13436 tng_data->first_trajectory_frame_set_output_file_pos =
13437 tng_data->current_trajectory_frame_set_output_file_pos;
13439 /* FIXME: Should check the frame number instead of the file_pos,
13440 * in case frame sets are not in order */
13441 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13442 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13443 tng_data->last_trajectory_frame_set_output_file_pos <
13444 tng_data->current_trajectory_frame_set_output_file_pos)
13446 tng_data->last_trajectory_frame_set_output_file_pos =
13447 tng_data->current_trajectory_frame_set_output_file_pos;
13450 return(TNG_SUCCESS);
13453 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13454 (tng_trajectory_t tng_data,
13455 const int64_t first_frame,
13456 const int64_t n_frames,
13457 const double first_frame_time)
13459 tng_function_status stat;
13461 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13462 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13463 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13464 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13467 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13468 if(stat != TNG_SUCCESS)
13472 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13477 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13478 (tng_trajectory_t tng_data,
13479 const double first_frame_time)
13481 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13482 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13484 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13486 return(TNG_SUCCESS);
13489 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13490 (const tng_trajectory_t tng_data,
13493 int64_t file_pos, next_frame_set_file_pos;
13494 tng_gen_block_t block;
13495 tng_function_status stat;
13497 tng_trajectory_frame_set_t frame_set;
13499 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13500 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13501 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13503 file_pos = ftello(tng_data->input_file);
13505 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13507 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13511 frame_set = &tng_data->current_trajectory_frame_set;
13512 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
13515 if(next_frame_set_file_pos <= 0)
13517 return(TNG_FAILURE);
13520 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
13521 /* Read block headers first to see that a frame set block is found. */
13522 tng_block_init(&block);
13523 stat = tng_block_header_read(tng_data, block);
13524 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13526 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13527 file_pos, __FILE__, __LINE__);
13528 return(TNG_CRITICAL);
13530 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13532 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13534 tng_block_destroy(&block);
13536 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13538 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13539 __FILE__, __LINE__);
13540 return(TNG_CRITICAL);
13542 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13544 return(TNG_SUCCESS);
13547 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13548 (tng_trajectory_t tng_data,
13550 const char *block_name,
13551 const char datatype,
13552 const char block_type_flag,
13554 const int64_t n_values_per_frame,
13555 int64_t stride_length,
13556 const int64_t codec_id,
13559 int i, j, size, len;
13560 tng_trajectory_frame_set_t frame_set;
13561 tng_non_particle_data_t data;
13562 char **first_dim_values;
13563 char *new_data_c=new_data;
13564 int64_t n_frames_div;
13566 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13567 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13568 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13570 frame_set = &tng_data->current_trajectory_frame_set;
13572 if(stride_length <= 0)
13577 /* If the block does not exist, create it */
13578 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13580 if(tng_data_block_create(tng_data, block_type_flag) !=
13583 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13584 __FILE__, __LINE__);
13585 return(TNG_CRITICAL);
13587 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13589 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13593 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13595 data->block_id = id;
13597 data->block_name = malloc(strlen(block_name) + 1);
13598 if(!data->block_name)
13600 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13601 (int)strlen(block_name)+1, __FILE__, __LINE__);
13602 return(TNG_CRITICAL);
13604 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13607 /* FIXME: Memory leak from strings. */
13609 data->last_retrieved_frame = -1;
13612 data->datatype = datatype;
13613 data->stride_length = tng_max_i64(stride_length, 1);
13614 data->n_values_per_frame = n_values_per_frame;
13615 data->n_frames = n_frames;
13616 data->codec_id = codec_id;
13617 data->compression_multiplier = 1.0;
13618 /* FIXME: This can cause problems. */
13619 data->first_frame_with_data = frame_set->first_frame;
13623 case TNG_FLOAT_DATA:
13624 size = sizeof(float);
13627 size = sizeof(int64_t);
13629 case TNG_DOUBLE_DATA:
13631 size = sizeof(double);
13637 /* Allocate memory */
13638 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13639 n_values_per_frame) !=
13642 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13643 __FILE__, __LINE__);
13644 return(TNG_CRITICAL);
13647 if(n_frames > frame_set->n_unwritten_frames)
13649 frame_set->n_unwritten_frames = n_frames;
13652 n_frames_div = (n_frames % stride_length) ?
13653 n_frames / stride_length + 1:
13654 n_frames / stride_length;
13656 if(datatype == TNG_CHAR_DATA)
13658 for(i = 0; i < n_frames_div; i++)
13660 first_dim_values = data->strings[i];
13661 for(j = 0; j < n_values_per_frame; j++)
13663 len = tng_min_i((int)strlen(new_data_c) + 1,
13665 if(first_dim_values[j])
13667 free(first_dim_values[j]);
13669 first_dim_values[j] = malloc(len);
13670 if(!first_dim_values[j])
13672 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13673 len, __FILE__, __LINE__);
13674 return(TNG_CRITICAL);
13676 strncpy(first_dim_values[j],
13684 memcpy(data->values, new_data, size * n_frames_div *
13685 n_values_per_frame);
13689 return(TNG_SUCCESS);
13692 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13693 (tng_trajectory_t tng_data,
13695 const char *block_name,
13696 const char datatype,
13697 const char block_type_flag,
13699 const int64_t n_values_per_frame,
13700 int64_t stride_length,
13701 const int64_t num_first_particle,
13702 const int64_t n_particles,
13703 const int64_t codec_id,
13708 int64_t tot_n_particles, n_frames_div;
13709 char ***first_dim_values, **second_dim_values;
13710 tng_trajectory_frame_set_t frame_set;
13711 tng_particle_data_t data;
13712 char *new_data_c=new_data;
13714 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13715 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13716 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13717 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13718 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13721 frame_set = &tng_data->current_trajectory_frame_set;
13723 if(stride_length <= 0)
13728 /* If the block does not exist, create it */
13729 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13731 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13734 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13735 __FILE__, __LINE__);
13736 return(TNG_CRITICAL);
13738 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13740 data = &frame_set->tr_particle_data[frame_set->
13741 n_particle_data_blocks - 1];
13745 data = &tng_data->non_tr_particle_data[tng_data->
13746 n_particle_data_blocks - 1];
13748 data->block_id = id;
13750 data->block_name = malloc(strlen(block_name) + 1);
13751 if(!data->block_name)
13753 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13754 (int)strlen(block_name)+1, __FILE__, __LINE__);
13755 return(TNG_CRITICAL);
13757 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13759 data->datatype = datatype;
13762 /* FIXME: Memory leak from strings. */
13764 data->last_retrieved_frame = -1;
13767 data->stride_length = tng_max_i64(stride_length, 1);
13768 data->n_values_per_frame = n_values_per_frame;
13769 data->n_frames = n_frames;
13770 data->codec_id = codec_id;
13771 data->compression_multiplier = 1.0;
13772 /* FIXME: This can cause problems. */
13773 data->first_frame_with_data = frame_set->first_frame;
13775 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13777 tot_n_particles = frame_set->n_particles;
13781 tot_n_particles = tng_data->n_particles;
13784 /* If data values are supplied add that data to the data block. */
13787 /* Allocate memory */
13788 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13789 stride_length, tot_n_particles,
13790 n_values_per_frame) !=
13793 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13794 __FILE__, __LINE__);
13795 return(TNG_CRITICAL);
13798 if(n_frames > frame_set->n_unwritten_frames)
13800 frame_set->n_unwritten_frames = n_frames;
13803 n_frames_div = (n_frames % stride_length) ?
13804 n_frames / stride_length + 1:
13805 n_frames / stride_length;
13807 if(datatype == TNG_CHAR_DATA)
13809 for(i = 0; i < n_frames_div; i++)
13811 first_dim_values = data->strings[i];
13812 for(j = num_first_particle; j < num_first_particle + n_particles;
13815 second_dim_values = first_dim_values[j];
13816 for(k = 0; k < n_values_per_frame; k++)
13818 len = tng_min_i((int)strlen(new_data_c) + 1,
13820 if(second_dim_values[k])
13822 free(second_dim_values[k]);
13824 second_dim_values[k] = malloc(len);
13825 if(!second_dim_values[k])
13827 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13828 len, __FILE__, __LINE__);
13829 return(TNG_CRITICAL);
13831 strncpy(second_dim_values[k],
13843 size = sizeof(int64_t);
13845 case TNG_FLOAT_DATA:
13846 size = sizeof(float);
13848 case TNG_DOUBLE_DATA:
13850 size = sizeof(double);
13853 memcpy(data->values, new_data, size * n_frames_div *
13854 n_particles * n_values_per_frame);
13858 return(TNG_SUCCESS);
13861 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13862 (tng_trajectory_t tng_data,
13868 tng_trajectory_frame_set_t frame_set;
13869 tng_function_status stat;
13870 tng_particle_data_t p_data;
13871 tng_non_particle_data_t np_data;
13872 int block_type = -1;
13874 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13875 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13877 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13879 p_data = &tng_data->non_tr_particle_data[i];
13880 if(p_data->block_id == block_id)
13882 strncpy(name, p_data->block_name, max_len);
13883 name[max_len - 1] = '\0';
13884 return(TNG_SUCCESS);
13887 for(i = 0; i < tng_data->n_data_blocks; i++)
13889 np_data = &tng_data->non_tr_data[i];
13890 if(np_data->block_id == block_id)
13892 strncpy(name, np_data->block_name, max_len);
13893 name[max_len - 1] = '\0';
13894 return(TNG_SUCCESS);
13898 frame_set = &tng_data->current_trajectory_frame_set;
13900 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13901 if(stat == TNG_SUCCESS)
13903 block_type = TNG_PARTICLE_BLOCK_DATA;
13907 stat = tng_data_find(tng_data, block_id, &np_data);
13908 if(stat == TNG_SUCCESS)
13910 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13914 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13915 if(stat != TNG_SUCCESS)
13919 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13920 if(stat == TNG_SUCCESS)
13922 block_type = TNG_PARTICLE_BLOCK_DATA;
13926 stat = tng_data_find(tng_data, block_id, &np_data);
13927 if(stat == TNG_SUCCESS)
13929 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13934 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13936 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13938 p_data = &frame_set->tr_particle_data[i];
13939 if(p_data->block_id == block_id)
13941 strncpy(name, p_data->block_name, max_len);
13942 name[max_len - 1] = '\0';
13943 return(TNG_SUCCESS);
13947 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13949 for(i = 0; i < frame_set->n_data_blocks; i++)
13951 np_data = &frame_set->tr_data[i];
13952 if(np_data->block_id == block_id)
13954 strncpy(name, np_data->block_name, max_len);
13955 name[max_len - 1] = '\0';
13956 return(TNG_SUCCESS);
13961 return(TNG_FAILURE);
13964 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13965 (const tng_trajectory_t tng_data,
13967 int *block_dependency)
13970 tng_function_status stat;
13971 tng_particle_data_t p_data;
13972 tng_non_particle_data_t np_data;
13974 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13975 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13977 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13979 p_data = &tng_data->non_tr_particle_data[i];
13980 if(p_data->block_id == block_id)
13982 *block_dependency = TNG_PARTICLE_DEPENDENT;
13983 return(TNG_SUCCESS);
13986 for(i = 0; i < tng_data->n_data_blocks; i++)
13988 np_data = &tng_data->non_tr_data[i];
13989 if(np_data->block_id == block_id)
13991 *block_dependency = 0;
13992 return(TNG_SUCCESS);
13996 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13997 if(stat == TNG_SUCCESS)
13999 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
14000 return(TNG_SUCCESS);
14004 stat = tng_data_find(tng_data, block_id, &np_data);
14005 if(stat == TNG_SUCCESS)
14007 *block_dependency = TNG_FRAME_DEPENDENT;
14008 return(TNG_SUCCESS);
14012 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14013 if(stat != TNG_SUCCESS)
14017 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14018 if(stat == TNG_SUCCESS)
14020 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
14021 return(TNG_SUCCESS);
14025 stat = tng_data_find(tng_data, block_id, &np_data);
14026 if(stat == TNG_SUCCESS)
14028 *block_dependency = TNG_FRAME_DEPENDENT;
14029 return(TNG_SUCCESS);
14035 return(TNG_FAILURE);
14038 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
14039 (const tng_trajectory_t tng_data,
14041 int64_t *n_values_per_frame)
14044 tng_function_status stat;
14045 tng_particle_data_t p_data;
14046 tng_non_particle_data_t np_data;
14048 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14049 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14051 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
14053 p_data = &tng_data->non_tr_particle_data[i];
14054 if(p_data->block_id == block_id)
14056 *n_values_per_frame = p_data->n_values_per_frame;
14057 return(TNG_SUCCESS);
14060 for(i = 0; i < tng_data->n_data_blocks; i++)
14062 np_data = &tng_data->non_tr_data[i];
14063 if(np_data->block_id == block_id)
14065 *n_values_per_frame = np_data->n_values_per_frame;
14066 return(TNG_SUCCESS);
14070 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14071 if(stat == TNG_SUCCESS)
14073 *n_values_per_frame = p_data->n_values_per_frame;
14074 return(TNG_SUCCESS);
14078 stat = tng_data_find(tng_data, block_id, &np_data);
14079 if(stat == TNG_SUCCESS)
14081 *n_values_per_frame = np_data->n_values_per_frame;
14082 return(TNG_SUCCESS);
14086 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14087 if(stat != TNG_SUCCESS)
14091 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14092 if(stat == TNG_SUCCESS)
14094 *n_values_per_frame = p_data->n_values_per_frame;
14095 return(TNG_SUCCESS);
14099 stat = tng_data_find(tng_data, block_id, &np_data);
14100 if(stat == TNG_SUCCESS)
14102 *n_values_per_frame = np_data->n_values_per_frame;
14103 return(TNG_SUCCESS);
14109 return(TNG_FAILURE);
14112 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14113 (tng_trajectory_t tng_data,
14114 const int64_t frame_nr,
14115 const int64_t block_id,
14116 const void *values,
14117 const char hash_mode)
14119 int64_t header_pos, file_pos;
14120 int64_t output_file_len, n_values_per_frame, size, contents_size;
14121 int64_t header_size, temp_first, temp_last;
14122 int64_t i, last_frame, temp_current;
14123 tng_gen_block_t block;
14124 tng_trajectory_frame_set_t frame_set;
14125 FILE *temp = tng_data->input_file;
14126 struct tng_non_particle_data data;
14127 tng_function_status stat;
14128 char dependency, sparse_data, datatype;
14131 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14132 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14133 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14135 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14137 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14138 __FILE__, __LINE__);
14139 return(TNG_CRITICAL);
14142 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14143 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14144 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14145 tng_data->first_trajectory_frame_set_input_file_pos =
14146 tng_data->first_trajectory_frame_set_output_file_pos;
14147 tng_data->last_trajectory_frame_set_input_file_pos =
14148 tng_data->last_trajectory_frame_set_output_file_pos;
14149 tng_data->current_trajectory_frame_set_input_file_pos =
14150 tng_data->current_trajectory_frame_set_output_file_pos;
14152 tng_data->input_file = tng_data->output_file;
14154 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14156 frame_set = &tng_data->current_trajectory_frame_set;
14158 if(stat != TNG_SUCCESS)
14160 last_frame = frame_set->first_frame +
14161 frame_set->n_frames - 1;
14162 /* If the wanted frame would be in the frame set after the last
14163 * frame set create a new frame set. */
14164 if(stat == TNG_FAILURE &&
14165 last_frame < frame_nr)
14166 /* (last_frame < frame_nr &&
14167 tng_data->current_trajectory_frame_set.first_frame +
14168 tng_data->frame_set_n_frames >= frame_nr))*/
14170 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14172 last_frame = frame_nr - 1;
14174 tng_frame_set_new(tng_data,
14176 tng_data->frame_set_n_frames);
14177 file_pos = ftello(tng_data->output_file);
14178 fseeko(tng_data->output_file, 0, SEEK_END);
14179 output_file_len = ftello(tng_data->output_file);
14180 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14182 /* Read mapping blocks from the last frame set */
14183 tng_block_init(&block);
14185 stat = tng_block_header_read(tng_data, block);
14186 while(file_pos < output_file_len &&
14187 stat != TNG_CRITICAL &&
14188 block->id != TNG_TRAJECTORY_FRAME_SET &&
14191 if(block->id == TNG_PARTICLE_MAPPING)
14193 tng_trajectory_mapping_block_read(tng_data, block,
14198 fseeko(tng_data->output_file, block->block_contents_size,
14201 file_pos = ftello(tng_data->output_file);
14202 if(file_pos < output_file_len)
14204 stat = tng_block_header_read(tng_data, block);
14208 tng_block_destroy(&block);
14209 /* Write the frame set to disk */
14210 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14212 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14213 return(TNG_CRITICAL);
14218 tng_data->input_file = temp;
14219 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14220 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14221 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14226 tng_block_init(&block);
14228 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14230 fseeko(tng_data->output_file, 0, SEEK_END);
14231 output_file_len = ftello(tng_data->output_file);
14232 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14234 /* Read past the frame set block first */
14235 stat = tng_block_header_read(tng_data, block);
14236 if(stat == TNG_CRITICAL)
14238 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14239 file_pos, __FILE__, __LINE__);
14240 tng_block_destroy(&block);
14241 tng_data->input_file = temp;
14243 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14244 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14245 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14248 fseeko(tng_data->output_file, block->block_contents_size,
14251 /* Read all block headers until next frame set block or
14252 * until the wanted block id is found */
14253 stat = tng_block_header_read(tng_data, block);
14254 while(file_pos < output_file_len &&
14255 stat != TNG_CRITICAL &&
14256 block->id != block_id &&
14257 block->id != TNG_TRAJECTORY_FRAME_SET &&
14260 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14261 file_pos = ftello(tng_data->output_file);
14262 if(file_pos < output_file_len)
14264 stat = tng_block_header_read(tng_data, block);
14267 if(stat == TNG_CRITICAL)
14269 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14270 file_pos, __FILE__, __LINE__);
14271 tng_block_destroy(&block);
14272 tng_data->input_file = temp;
14273 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14274 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14275 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14279 contents_size = block->block_contents_size;
14280 header_size = block->header_contents_size;
14282 header_pos = ftello(tng_data->output_file) - header_size;
14283 frame_set = &tng_data->current_trajectory_frame_set;
14285 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14287 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14288 tng_block_destroy(&block);
14289 return(TNG_CRITICAL);
14291 if(fread(&dependency, sizeof(dependency), 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);
14297 data.datatype = datatype;
14299 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14300 (dependency & TNG_PARTICLE_DEPENDENT))
14302 tng_block_destroy(&block);
14303 tng_data->input_file = temp;
14305 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14306 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14307 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14308 return(TNG_FAILURE);
14311 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14313 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14314 tng_block_destroy(&block);
14315 return(TNG_CRITICAL);
14318 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14319 tng_data->input_file) == 0)
14321 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14322 tng_block_destroy(&block);
14323 return(TNG_CRITICAL);
14325 if(tng_data->output_endianness_swap_func_64)
14327 if(tng_data->output_endianness_swap_func_64(tng_data,
14328 &data.n_values_per_frame)
14331 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14332 __FILE__, __LINE__);
14336 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14337 tng_data->input_file) == 0)
14339 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14340 tng_block_destroy(&block);
14341 return(TNG_CRITICAL);
14343 if(tng_data->output_endianness_swap_func_64)
14345 if(tng_data->output_endianness_swap_func_64(tng_data,
14349 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14350 __FILE__, __LINE__);
14354 if(data.codec_id != TNG_UNCOMPRESSED)
14356 if(fread(&data.compression_multiplier,
14357 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14360 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14361 tng_block_destroy(&block);
14362 return(TNG_CRITICAL);
14364 if(tng_data->output_endianness_swap_func_64)
14366 if(tng_data->output_endianness_swap_func_64(tng_data,
14367 (int64_t *)&data.compression_multiplier)
14370 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14371 __FILE__, __LINE__);
14377 data.compression_multiplier = 1;
14382 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14383 1, tng_data->input_file) == 0)
14385 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14386 tng_block_destroy(&block);
14387 return(TNG_CRITICAL);
14389 if(tng_data->output_endianness_swap_func_64)
14391 if(tng_data->output_endianness_swap_func_64(tng_data,
14392 &data.first_frame_with_data)
14395 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14396 __FILE__, __LINE__);
14400 if(fread(&data.stride_length, sizeof(data.stride_length),
14401 1, tng_data->input_file) == 0)
14403 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14404 tng_block_destroy(&block);
14405 return(TNG_CRITICAL);
14407 if(tng_data->output_endianness_swap_func_64)
14409 if(tng_data->output_endianness_swap_func_64(tng_data,
14410 &data.stride_length)
14413 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14414 __FILE__, __LINE__);
14420 data.first_frame_with_data = 0;
14421 data.stride_length = 1;
14423 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14425 tng_data->input_file = temp;
14427 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14428 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14429 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14431 switch(data.datatype)
14433 case(TNG_INT_DATA):
14434 size = sizeof(int64_t);
14436 case(TNG_FLOAT_DATA):
14437 size = sizeof(float);
14439 case(TNG_DOUBLE_DATA):
14440 size = sizeof(double);
14443 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14445 tng_block_destroy(&block);
14446 return(TNG_FAILURE);
14449 n_values_per_frame = data.n_values_per_frame;
14451 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14452 data.first_frame_with_data)) /
14453 data.stride_length;
14454 file_pos *= size * n_values_per_frame;
14456 if(file_pos > contents_size)
14458 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14460 tng_block_destroy(&block);
14461 return(TNG_FAILURE);
14464 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
14466 /* If the endianness is not big endian the data needs to be swapped */
14467 if((data.datatype == TNG_INT_DATA ||
14468 data.datatype == TNG_DOUBLE_DATA) &&
14469 tng_data->output_endianness_swap_func_64)
14471 copy = malloc(n_values_per_frame * size);
14472 memcpy(copy, values, n_values_per_frame * size);
14473 for(i = 0; i < n_values_per_frame; i++)
14475 if(tng_data->output_endianness_swap_func_64(tng_data,
14479 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14480 __FILE__, __LINE__);
14483 fwrite(copy, n_values_per_frame, size,
14484 tng_data->output_file);
14487 else if(data.datatype == TNG_FLOAT_DATA &&
14488 tng_data->output_endianness_swap_func_32)
14490 copy = malloc(n_values_per_frame * size);
14491 memcpy(copy, values, n_values_per_frame * size);
14492 for(i = 0; i < n_values_per_frame; i++)
14494 if(tng_data->output_endianness_swap_func_32(tng_data,
14498 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14499 __FILE__, __LINE__);
14502 fwrite(copy, n_values_per_frame, size,
14503 tng_data->output_file);
14509 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14512 fflush(tng_data->output_file);
14514 /* Update the number of written frames in the frame set. */
14515 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14517 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14520 /* If the last frame has been written update the hash */
14521 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14522 data.first_frame_with_data) >=
14523 frame_set->n_frames)
14525 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14529 tng_block_destroy(&block);
14531 return(TNG_SUCCESS);
14534 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14535 (tng_trajectory_t tng_data,
14536 const int64_t frame_nr,
14537 const int64_t block_id,
14538 const int64_t val_first_particle,
14539 const int64_t val_n_particles,
14540 const void *values,
14541 const char hash_mode)
14543 int64_t header_pos, file_pos, tot_n_particles;
14544 int64_t output_file_len, n_values_per_frame, size, contents_size;
14545 int64_t header_size, temp_first, temp_last;
14546 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14547 int64_t i, last_frame, temp_current;
14548 tng_gen_block_t block;
14549 tng_trajectory_frame_set_t frame_set;
14550 FILE *temp = tng_data->input_file;
14551 struct tng_particle_data data;
14552 tng_function_status stat;
14553 tng_particle_mapping_t mapping;
14554 char dependency, sparse_data, datatype;
14557 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14558 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14559 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14560 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14561 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14563 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14565 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14566 __FILE__, __LINE__);
14567 return(TNG_CRITICAL);
14570 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14571 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14572 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14573 tng_data->first_trajectory_frame_set_input_file_pos =
14574 tng_data->first_trajectory_frame_set_output_file_pos;
14575 tng_data->last_trajectory_frame_set_input_file_pos =
14576 tng_data->last_trajectory_frame_set_output_file_pos;
14577 tng_data->current_trajectory_frame_set_input_file_pos =
14578 tng_data->current_trajectory_frame_set_output_file_pos;
14580 tng_data->input_file = tng_data->output_file;
14582 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14584 frame_set = &tng_data->current_trajectory_frame_set;
14586 if(stat != TNG_SUCCESS)
14588 last_frame = frame_set->first_frame +
14589 frame_set->n_frames - 1;
14590 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14592 /* If the wanted frame would be in the frame set after the last
14593 * frame set create a new frame set. */
14594 if(stat == TNG_FAILURE &&
14595 (last_frame < frame_nr &&
14596 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14598 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14600 last_frame = frame_nr - 1;
14602 tng_frame_set_new(tng_data,
14604 tng_data->frame_set_n_frames);
14606 file_pos = ftello(tng_data->output_file);
14607 fseeko(tng_data->output_file, 0, SEEK_END);
14608 output_file_len = ftello(tng_data->output_file);
14609 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14611 /* Read mapping blocks from the last frame set */
14612 tng_block_init(&block);
14614 stat = tng_block_header_read(tng_data, block);
14615 while(file_pos < output_file_len &&
14616 stat != TNG_CRITICAL &&
14617 block->id != TNG_TRAJECTORY_FRAME_SET &&
14620 if(block->id == TNG_PARTICLE_MAPPING)
14622 tng_trajectory_mapping_block_read(tng_data, block,
14627 fseeko(tng_data->output_file, block->block_contents_size,
14630 file_pos = ftello(tng_data->output_file);
14631 if(file_pos < output_file_len)
14633 stat = tng_block_header_read(tng_data, block);
14637 tng_block_destroy(&block);
14638 /* Write the frame set to disk */
14639 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14641 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14647 tng_data->input_file = temp;
14648 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14649 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14650 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14656 tng_block_init(&block);
14658 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14660 fseeko(tng_data->output_file, 0, SEEK_END);
14661 output_file_len = ftello(tng_data->output_file);
14662 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14664 /* Read past the frame set block first */
14665 stat = tng_block_header_read(tng_data, block);
14666 if(stat == TNG_CRITICAL)
14668 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14669 file_pos, __FILE__, __LINE__);
14670 tng_block_destroy(&block);
14671 tng_data->input_file = temp;
14673 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14674 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14675 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14678 fseeko(tng_data->output_file, block->block_contents_size,
14681 if(tng_data->var_num_atoms_flag)
14683 tot_n_particles = frame_set->n_particles;
14687 tot_n_particles = tng_data->n_particles;
14690 if(val_n_particles < tot_n_particles)
14692 mapping_block_end_pos = -1;
14693 /* Read all mapping blocks to find the right place to put the data */
14694 stat = tng_block_header_read(tng_data, block);
14695 while(file_pos < output_file_len &&
14696 stat != TNG_CRITICAL &&
14697 block->id != TNG_TRAJECTORY_FRAME_SET &&
14700 if(block->id == TNG_PARTICLE_MAPPING)
14702 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14706 fseeko(tng_data->output_file, block->block_contents_size,
14709 file_pos = ftello(tng_data->output_file);
14710 if(block->id == TNG_PARTICLE_MAPPING)
14712 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14713 if(val_first_particle >= mapping->num_first_particle &&
14714 val_first_particle < mapping->num_first_particle +
14715 mapping->n_particles &&
14716 val_first_particle + val_n_particles <=
14717 mapping->num_first_particle + mapping->n_particles)
14719 mapping_block_end_pos = file_pos;
14722 if(file_pos < output_file_len)
14724 stat = tng_block_header_read(tng_data, block);
14727 if(stat == TNG_CRITICAL)
14729 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14730 file_pos, __FILE__, __LINE__);
14731 tng_block_destroy(&block);
14732 tng_data->input_file = temp;
14734 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14735 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14736 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14739 if(mapping_block_end_pos < 0)
14741 tng_block_destroy(&block);
14742 tng_data->input_file = temp;
14744 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14745 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14746 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14747 return(TNG_FAILURE);
14749 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
14752 /* Read all block headers until next frame set block or
14753 * until the wanted block id is found */
14754 stat = tng_block_header_read(tng_data, block);
14755 while(file_pos < output_file_len &&
14756 stat != TNG_CRITICAL &&
14757 block->id != block_id &&
14758 block->id != TNG_PARTICLE_MAPPING &&
14759 block->id != TNG_TRAJECTORY_FRAME_SET &&
14762 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14763 file_pos = ftello(tng_data->output_file);
14764 if(file_pos < output_file_len)
14766 stat = tng_block_header_read(tng_data, block);
14769 if(stat == TNG_CRITICAL)
14771 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14772 file_pos, __FILE__, __LINE__);
14773 tng_block_destroy(&block);
14774 tng_data->input_file = temp;
14776 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14777 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14778 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14782 contents_size = block->block_contents_size;
14783 header_size = block->header_contents_size;
14785 header_pos = ftello(tng_data->output_file) - header_size;
14786 frame_set = &tng_data->current_trajectory_frame_set;
14788 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14790 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14791 tng_block_destroy(&block);
14792 return(TNG_CRITICAL);
14795 data.datatype = datatype;
14797 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14799 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14800 tng_block_destroy(&block);
14801 return(TNG_CRITICAL);
14804 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14805 !(dependency & TNG_PARTICLE_DEPENDENT))
14807 tng_block_destroy(&block);
14808 tng_data->input_file = temp;
14810 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14811 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14812 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14813 return(TNG_FAILURE);
14816 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14818 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14819 tng_block_destroy(&block);
14820 return(TNG_CRITICAL);
14823 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14824 tng_data->input_file) == 0)
14826 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14827 tng_block_destroy(&block);
14828 return(TNG_CRITICAL);
14830 if(tng_data->output_endianness_swap_func_64)
14832 if(tng_data->output_endianness_swap_func_64(tng_data,
14833 &data.n_values_per_frame)
14836 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14837 __FILE__, __LINE__);
14841 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14842 tng_data->input_file) == 0)
14844 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14845 tng_block_destroy(&block);
14846 return(TNG_CRITICAL);
14848 if(tng_data->output_endianness_swap_func_64)
14850 if(tng_data->output_endianness_swap_func_64(tng_data,
14854 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14855 __FILE__, __LINE__);
14859 if(data.codec_id != TNG_UNCOMPRESSED)
14861 if(fread(&data.compression_multiplier,
14862 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14865 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14866 tng_block_destroy(&block);
14867 return(TNG_CRITICAL);
14870 if(tng_data->output_endianness_swap_func_64)
14872 if(tng_data->output_endianness_swap_func_64(tng_data,
14873 (int64_t *)&data.compression_multiplier)
14876 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14877 __FILE__, __LINE__);
14883 data.compression_multiplier = 1;
14888 if(fread(&data.first_frame_with_data,
14889 sizeof(data.first_frame_with_data),
14890 1, tng_data->input_file) == 0)
14892 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14893 tng_block_destroy(&block);
14894 return(TNG_CRITICAL);
14896 if(tng_data->output_endianness_swap_func_64)
14898 if(tng_data->output_endianness_swap_func_64(tng_data,
14899 &data.first_frame_with_data)
14902 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14903 __FILE__, __LINE__);
14907 if(fread(&data.stride_length, sizeof(data.stride_length),
14908 1, tng_data->input_file) == 0)
14910 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14911 tng_block_destroy(&block);
14912 return(TNG_CRITICAL);
14914 if(tng_data->output_endianness_swap_func_64)
14916 if(tng_data->output_endianness_swap_func_64(tng_data,
14917 &data.stride_length)
14920 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14921 __FILE__, __LINE__);
14927 data.first_frame_with_data = 0;
14928 data.stride_length = 1;
14930 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14932 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14933 tng_data->input_file) == 0)
14935 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14936 tng_block_destroy(&block);
14937 return(TNG_CRITICAL);
14939 if(tng_data->output_endianness_swap_func_64)
14941 if(tng_data->output_endianness_swap_func_64(tng_data,
14942 &num_first_particle)
14945 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14946 __FILE__, __LINE__);
14950 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14951 tng_data->input_file) == 0)
14953 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14954 tng_block_destroy(&block);
14955 return(TNG_CRITICAL);
14957 if(tng_data->output_endianness_swap_func_64)
14959 if(tng_data->output_endianness_swap_func_64(tng_data,
14960 &block_n_particles)
14963 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14964 __FILE__, __LINE__);
14969 tng_data->input_file = temp;
14971 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14972 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14973 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14976 switch(data.datatype)
14978 case(TNG_INT_DATA):
14979 size = sizeof(int64_t);
14981 case(TNG_FLOAT_DATA):
14982 size = sizeof(float);
14984 case(TNG_DOUBLE_DATA):
14985 size = sizeof(double);
14988 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14990 tng_block_destroy(&block);
14991 return(TNG_FAILURE);
14994 n_values_per_frame = data.n_values_per_frame;
14996 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14997 data.first_frame_with_data)) /
14998 data.stride_length;
14999 file_pos *= block_n_particles * size * n_values_per_frame;
15001 if(file_pos > contents_size)
15003 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
15005 tng_block_destroy(&block);
15006 return(TNG_FAILURE);
15009 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
15011 /* If the endianness is not big endian the data needs to be swapped */
15012 if((data.datatype == TNG_INT_DATA ||
15013 data.datatype == TNG_DOUBLE_DATA) &&
15014 tng_data->output_endianness_swap_func_64)
15016 copy = malloc(val_n_particles * n_values_per_frame * size);
15017 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15018 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15020 if(tng_data->output_endianness_swap_func_64(tng_data,
15021 (int64_t *) copy+i)
15024 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15025 __FILE__, __LINE__);
15028 fwrite(copy, val_n_particles * n_values_per_frame, size,
15029 tng_data->output_file);
15032 else if(data.datatype == TNG_FLOAT_DATA &&
15033 tng_data->output_endianness_swap_func_32)
15035 copy = malloc(val_n_particles * n_values_per_frame * size);
15036 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15037 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15039 if(tng_data->output_endianness_swap_func_32(tng_data,
15040 (int32_t *) copy+i)
15043 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15044 __FILE__, __LINE__);
15047 fwrite(copy, val_n_particles * n_values_per_frame, size,
15048 tng_data->output_file);
15054 fwrite(values, val_n_particles * n_values_per_frame, size,
15055 tng_data->output_file);
15057 fflush(tng_data->output_file);
15059 /* Update the number of written frames in the frame set. */
15060 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
15062 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
15065 /* If the last frame has been written update the hash */
15066 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
15067 data.first_frame_with_data) >=
15068 frame_set->n_frames)
15070 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
15074 tng_block_destroy(&block);
15075 return(TNG_SUCCESS);
15078 static tng_function_status tng_data_values_alloc
15079 (const tng_trajectory_t tng_data,
15080 union data_values ***values,
15081 const int64_t n_frames,
15082 const int64_t n_values_per_frame,
15086 tng_function_status stat;
15088 if(n_frames <= 0 || n_values_per_frame <= 0)
15090 return(TNG_FAILURE);
15095 stat = tng_data_values_free(tng_data, *values, n_frames,
15096 n_values_per_frame,
15098 if(stat != TNG_SUCCESS)
15100 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15101 __FILE__, __LINE__);
15105 *values = malloc(sizeof(union data_values *) * n_frames);
15108 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15109 sizeof(union data_values **) * n_frames,
15110 __FILE__, __LINE__);
15111 return(TNG_CRITICAL);
15115 for(i = 0; i < n_frames; i++)
15117 (*values)[i] = malloc(sizeof(union data_values) *
15118 n_values_per_frame);
15121 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15122 sizeof(union data_values) * n_values_per_frame,
15123 __FILE__, __LINE__);
15126 return(TNG_CRITICAL);
15129 return(TNG_SUCCESS);
15132 /* FIXME: This needs ***values */
15133 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15134 (const tng_trajectory_t tng_data,
15135 union data_values **values,
15136 const int64_t n_frames,
15137 const int64_t n_values_per_frame,
15145 for(i = 0; i < n_frames; i++)
15149 if(type == TNG_CHAR_DATA)
15151 for(j = 0; j < n_values_per_frame; j++)
15155 free(values[i][j].c);
15156 values[i][j].c = 0;
15168 return(TNG_SUCCESS);
15171 static tng_function_status tng_particle_data_values_alloc
15172 (const tng_trajectory_t tng_data,
15173 union data_values ****values,
15174 const int64_t n_frames,
15175 const int64_t n_particles,
15176 const int64_t n_values_per_frame,
15180 tng_function_status stat;
15182 if(n_particles == 0 || n_values_per_frame == 0)
15184 return(TNG_FAILURE);
15189 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15190 n_particles, n_values_per_frame,
15192 if(stat != TNG_SUCCESS)
15194 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15195 __FILE__, __LINE__);
15199 *values = malloc(sizeof(union data_values **) * n_frames);
15202 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15203 sizeof(union data_values **) * n_frames,
15204 __FILE__, __LINE__);
15205 return(TNG_CRITICAL);
15209 for(i = 0; i < n_frames; i++)
15211 (*values)[i] = malloc(sizeof(union data_values *) *
15215 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15216 sizeof(union data_values *) * n_particles,
15217 __FILE__, __LINE__);
15220 return(TNG_CRITICAL);
15222 for(j = 0; j < n_particles; j++)
15224 (*values)[i][j] = malloc(sizeof(union data_values) *
15225 n_values_per_frame);
15226 if(!(*values)[i][j])
15228 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15229 sizeof(union data_values *) * n_particles,
15230 __FILE__, __LINE__);
15231 tng_particle_data_values_free(tng_data, *values, n_frames,
15232 n_particles, n_values_per_frame,
15235 return(TNG_CRITICAL);
15239 return(TNG_SUCCESS);
15242 /* FIXME: This needs ****values */
15243 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15244 (const tng_trajectory_t tng_data,
15245 union data_values ***values,
15246 const int64_t n_frames,
15247 const int64_t n_particles,
15248 const int64_t n_values_per_frame,
15256 for(i = 0; i < n_frames; i++)
15260 for(j = 0; j < n_particles; j++)
15262 if(type == TNG_CHAR_DATA)
15264 for(k = 0; k < n_values_per_frame; k++)
15266 if(values[i][j][k].c)
15268 free(values[i][j][k].c);
15269 values[i][j][k].c = 0;
15273 free(values[i][j]);
15284 return(TNG_SUCCESS);
15288 tng_function_status DECLSPECDLLEXPORT tng_data_get
15289 (tng_trajectory_t tng_data,
15290 const int64_t block_id,
15291 union data_values ***values,
15293 int64_t *n_values_per_frame,
15296 int64_t i, j, file_pos, block_index;
15299 tng_non_particle_data_t data;
15300 tng_trajectory_frame_set_t frame_set;
15301 tng_gen_block_t block;
15302 tng_function_status stat;
15304 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15305 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15306 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15307 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15309 frame_set = &tng_data->current_trajectory_frame_set;
15314 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15316 tng_block_init(&block);
15317 file_pos = ftello(tng_data->input_file);
15318 /* Read all blocks until next frame set block */
15319 stat = tng_block_header_read(tng_data, block);
15320 while(file_pos < tng_data->input_file_len &&
15321 stat != TNG_CRITICAL &&
15322 block->id != TNG_TRAJECTORY_FRAME_SET &&
15325 /* Use hash by default */
15326 stat = tng_block_read_next(tng_data, block,
15328 if(stat != TNG_CRITICAL)
15330 file_pos = ftello(tng_data->input_file);
15331 if(file_pos < tng_data->input_file_len)
15333 stat = tng_block_header_read(tng_data, block);
15337 tng_block_destroy(&block);
15338 if(stat == TNG_CRITICAL)
15340 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15341 file_pos, __FILE__, __LINE__);
15345 for(i = 0; i < frame_set->n_data_blocks; i++)
15347 data = &frame_set->tr_data[i];
15348 if(data->block_id == block_id)
15354 if(block_index < 0)
15356 return(TNG_FAILURE);
15360 *n_frames = tng_max_i64(1, data->n_frames);
15361 *n_values_per_frame = data->n_values_per_frame;
15362 *type = data->datatype;
15366 if(tng_data_values_alloc(tng_data, values, *n_frames,
15367 *n_values_per_frame,
15371 return(TNG_CRITICAL);
15377 case TNG_CHAR_DATA:
15378 for(i = 0; i < *n_frames; i++)
15380 for(j = 0; j < *n_values_per_frame; j++)
15382 len = strlen(data->strings[i][j]) + 1;
15383 (*values)[i][j].c = malloc(len);
15384 strncpy((*values)[i][j].c, data->strings[i][j], len);
15389 size = sizeof(int);
15390 for(i = 0; i < *n_frames; i++)
15392 for(j = 0; j < *n_values_per_frame; j++)
15394 (*values)[i][j].i = *(int *)((char *)data->values + size *
15395 (i*(*n_values_per_frame) + j));
15399 case TNG_FLOAT_DATA:
15400 size = sizeof(float);
15401 for(i = 0; i < *n_frames; i++)
15403 for(j = 0; j < *n_values_per_frame; j++)
15405 (*values)[i][j].f = *(float *)((char *)data->values + size *
15406 (i*(*n_values_per_frame) + j));
15410 case TNG_DOUBLE_DATA:
15412 size = sizeof(double);
15413 for(i = 0; i < *n_frames; i++)
15415 for(j = 0; j < *n_values_per_frame; j++)
15417 (*values)[i][j].d = *(double *)((char *)data->values + size *
15418 (i*(*n_values_per_frame) + j));
15423 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15425 return(TNG_SUCCESS);
15428 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15429 const int64_t block_id,
15432 int64_t *stride_length,
15433 int64_t *n_values_per_frame,
15436 int64_t file_pos, data_size, n_frames_div, block_index;
15438 tng_non_particle_data_t data;
15439 tng_trajectory_frame_set_t frame_set;
15440 tng_gen_block_t block;
15442 tng_function_status stat;
15444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15445 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15446 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15447 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15448 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15450 frame_set = &tng_data->current_trajectory_frame_set;
15455 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15457 tng_block_init(&block);
15458 file_pos = ftello(tng_data->input_file);
15459 /* Read all blocks until next frame set block */
15460 stat = tng_block_header_read(tng_data, block);
15461 while(file_pos < tng_data->input_file_len &&
15462 stat != TNG_CRITICAL &&
15463 block->id != TNG_TRAJECTORY_FRAME_SET &&
15466 /* Use hash by default */
15467 stat = tng_block_read_next(tng_data, block,
15469 if(stat != TNG_CRITICAL)
15471 file_pos = ftello(tng_data->input_file);
15472 if(file_pos < tng_data->input_file_len)
15474 stat = tng_block_header_read(tng_data, block);
15478 tng_block_destroy(&block);
15479 if(stat == TNG_CRITICAL)
15481 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15482 file_pos, __FILE__, __LINE__);
15486 for(i = 0; i < frame_set->n_data_blocks; i++)
15488 data = &frame_set->tr_data[i];
15489 if(data->block_id == block_id)
15495 if(block_index < 0)
15497 return(TNG_FAILURE);
15501 *type = data->datatype;
15505 case TNG_CHAR_DATA:
15506 return(TNG_FAILURE);
15508 size = sizeof(int64_t);
15510 case TNG_FLOAT_DATA:
15511 size = sizeof(float);
15513 case TNG_DOUBLE_DATA:
15515 size = sizeof(double);
15518 *n_frames = data->n_frames;
15519 *n_values_per_frame = data->n_values_per_frame;
15520 *stride_length = data->stride_length;
15521 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15522 *n_frames / *stride_length;
15524 data_size = n_frames_div * size *
15525 *n_values_per_frame;
15527 temp = realloc(*values, data_size);
15530 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15531 data_size, __FILE__, __LINE__);
15534 return(TNG_CRITICAL);
15539 memcpy(*values, data->values, data_size);
15541 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15543 return(TNG_SUCCESS);
15546 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15547 (tng_trajectory_t tng_data,
15548 const int64_t block_id,
15549 const int64_t start_frame_nr,
15550 const int64_t end_frame_nr,
15551 const char hash_mode,
15552 union data_values ***values,
15553 int64_t *n_values_per_frame,
15556 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15557 int64_t block_index;
15560 tng_non_particle_data_t data;
15561 tng_trajectory_frame_set_t frame_set;
15562 tng_gen_block_t block;
15563 tng_function_status stat;
15565 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15566 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15567 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15568 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15572 frame_set = &tng_data->current_trajectory_frame_set;
15573 first_frame = frame_set->first_frame;
15575 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15576 if(stat != TNG_SUCCESS)
15582 /* Do not re-read the frame set. */
15583 if(first_frame != frame_set->first_frame ||
15584 frame_set->n_data_blocks <= 0)
15586 tng_block_init(&block);
15587 file_pos = ftello(tng_data->input_file);
15588 /* Read all blocks until next frame set block */
15589 stat = tng_block_header_read(tng_data, block);
15590 while(file_pos < tng_data->input_file_len &&
15591 stat != TNG_CRITICAL &&
15592 block->id != TNG_TRAJECTORY_FRAME_SET &&
15595 stat = tng_block_read_next(tng_data, block,
15597 if(stat != TNG_CRITICAL)
15599 file_pos = ftello(tng_data->input_file);
15600 if(file_pos < tng_data->input_file_len)
15602 stat = tng_block_header_read(tng_data, block);
15606 tng_block_destroy(&block);
15607 if(stat == TNG_CRITICAL)
15609 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15610 file_pos, __FILE__, __LINE__);
15616 /* See if there is a data block of this ID.
15617 * Start checking the last read frame set */
15618 for(i = 0; i < frame_set->n_data_blocks; i++)
15620 data = &frame_set->tr_data[i];
15621 if(data->block_id == block_id)
15628 if(block_index < 0)
15630 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15631 block_id, __FILE__, __LINE__);
15632 return(TNG_FAILURE);
15635 n_frames = end_frame_nr - start_frame_nr + 1;
15636 *n_values_per_frame = data->n_values_per_frame;
15637 *type = data->datatype;
15641 if(tng_data_values_alloc(tng_data, values, n_frames,
15642 *n_values_per_frame,
15643 *type) != TNG_SUCCESS)
15645 return(TNG_CRITICAL);
15649 current_frame_pos = start_frame_nr - frame_set->first_frame;
15650 /* It's not very elegant to reuse so much of the code in the different case
15651 * statements, but it's unnecessarily slow to have the switch-case block
15652 * inside the for loops. */
15655 case TNG_CHAR_DATA:
15656 for(i=0; i<n_frames; i++)
15658 if(current_frame_pos == frame_set->n_frames)
15660 stat = tng_frame_set_read_next(tng_data, hash_mode);
15661 if(stat != TNG_SUCCESS)
15665 current_frame_pos = 0;
15667 for(j = 0; j < *n_values_per_frame; j++)
15669 len = strlen(data->strings[current_frame_pos][j]) + 1;
15670 (*values)[i][j].c = malloc(len);
15671 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15673 current_frame_pos++;
15677 size = sizeof(int);
15678 for(i=0; i<n_frames; i++)
15680 if(current_frame_pos == frame_set->n_frames)
15682 stat = tng_frame_set_read_next(tng_data, hash_mode);
15683 if(stat != TNG_SUCCESS)
15687 current_frame_pos = 0;
15689 for(j = 0; j < *n_values_per_frame; j++)
15691 (*values)[i][j].i = *(int *)((char *)data->values + size *
15692 (current_frame_pos *
15693 (*n_values_per_frame) + j));
15695 current_frame_pos++;
15698 case TNG_FLOAT_DATA:
15699 size = sizeof(float);
15700 for(i=0; i<n_frames; i++)
15702 if(current_frame_pos == frame_set->n_frames)
15704 stat = tng_frame_set_read_next(tng_data, hash_mode);
15705 if(stat != TNG_SUCCESS)
15709 current_frame_pos = 0;
15711 for(j = 0; j < *n_values_per_frame; j++)
15713 (*values)[i][j].f = *(float *)((char *)data->values + size *
15714 (current_frame_pos *
15715 (*n_values_per_frame) + j));
15717 current_frame_pos++;
15720 case TNG_DOUBLE_DATA:
15722 size = sizeof(double);
15723 for(i=0; i<n_frames; i++)
15725 if(current_frame_pos == frame_set->n_frames)
15727 stat = tng_frame_set_read_next(tng_data, hash_mode);
15728 if(stat != TNG_SUCCESS)
15732 current_frame_pos = 0;
15734 for(j = 0; j < *n_values_per_frame; j++)
15736 (*values)[i][j].d = *(double *)((char *)data->values + size *
15737 (current_frame_pos *
15738 (*n_values_per_frame) + j));
15740 current_frame_pos++;
15744 data->last_retrieved_frame = end_frame_nr;
15746 return(TNG_SUCCESS);
15749 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15750 (tng_trajectory_t tng_data,
15751 const int64_t block_id,
15752 const int64_t start_frame_nr,
15753 const int64_t end_frame_nr,
15754 const char hash_mode,
15756 int64_t *stride_length,
15757 int64_t *n_values_per_frame,
15760 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15761 int64_t file_pos, current_frame_pos, data_size, frame_size;
15762 int64_t last_frame_pos;
15764 tng_trajectory_frame_set_t frame_set;
15765 tng_non_particle_data_t np_data;
15766 tng_gen_block_t block;
15767 void *current_values = 0, *temp;
15768 tng_function_status stat;
15770 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15771 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15772 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15773 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15774 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15776 frame_set = &tng_data->current_trajectory_frame_set;
15777 first_frame = frame_set->first_frame;
15779 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15780 if(stat != TNG_SUCCESS)
15785 /* Do not re-read the frame set and only need the requested block. */
15786 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15787 stat = tng_data_find(tng_data, block_id, &np_data);
15788 if(first_frame != frame_set->first_frame ||
15789 stat != TNG_SUCCESS)
15791 tng_block_init(&block);
15792 if(stat != TNG_SUCCESS)
15794 fseeko(tng_data->input_file,
15795 tng_data->current_trajectory_frame_set_input_file_pos,
15797 stat = tng_block_header_read(tng_data, block);
15798 if(stat != TNG_SUCCESS)
15800 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15801 __FILE__, __LINE__);
15805 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15807 file_pos = ftello(tng_data->input_file);
15808 /* Read until next frame set block */
15809 stat = tng_block_header_read(tng_data, block);
15810 while(file_pos < tng_data->input_file_len &&
15811 stat != TNG_CRITICAL &&
15812 block->id != TNG_TRAJECTORY_FRAME_SET &&
15815 if(block->id == block_id)
15817 stat = tng_block_read_next(tng_data, block,
15819 if(stat != TNG_CRITICAL)
15821 file_pos = ftello(tng_data->input_file);
15822 if(file_pos < tng_data->input_file_len)
15824 stat = tng_block_header_read(tng_data, block);
15830 file_pos += block->block_contents_size + block->header_contents_size;
15831 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15832 if(file_pos < tng_data->input_file_len)
15834 stat = tng_block_header_read(tng_data, block);
15838 tng_block_destroy(&block);
15839 if(stat == TNG_CRITICAL)
15841 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15842 file_pos, __FILE__, __LINE__);
15847 stat = tng_data_find(tng_data, block_id, &np_data);
15848 if(stat != TNG_SUCCESS)
15853 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15854 &n_frames, stride_length,
15855 n_values_per_frame, type);
15857 if(stat != TNG_SUCCESS)
15861 free(current_values);
15866 if(n_frames == 1 && n_frames < frame_set->n_frames)
15872 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15877 case TNG_CHAR_DATA:
15878 return(TNG_FAILURE);
15880 size = sizeof(int64_t);
15882 case TNG_FLOAT_DATA:
15883 size = sizeof(float);
15885 case TNG_DOUBLE_DATA:
15887 size = sizeof(double);
15890 n_frames_div = (tot_n_frames % *stride_length) ?
15891 tot_n_frames / *stride_length + 1:
15892 tot_n_frames / *stride_length;
15893 data_size = n_frames_div * size * (*n_values_per_frame);
15895 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15896 size, n_frames_div, data_size);
15898 temp = realloc(*values, data_size);
15901 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15902 data_size, __FILE__, __LINE__);
15905 return(TNG_CRITICAL);
15910 if( n_frames == 1 && n_frames < frame_set->n_frames)
15912 memcpy(*values, current_values, size * (*n_values_per_frame));
15916 current_frame_pos = start_frame_nr - frame_set->first_frame;
15918 frame_size = size * (*n_values_per_frame);
15920 last_frame_pos = tng_min_i64(n_frames,
15921 end_frame_nr - start_frame_nr);
15923 n_frames_div = current_frame_pos / *stride_length;
15924 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15925 last_frame_pos / *stride_length + 1:
15926 last_frame_pos / *stride_length;
15927 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15929 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15930 n_frames_div_2 * frame_size);
15932 current_frame_pos += n_frames - current_frame_pos;
15934 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15936 stat = tng_frame_set_read_next(tng_data, hash_mode);
15937 if(stat != TNG_SUCCESS)
15941 free(current_values);
15948 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15949 &n_frames, stride_length,
15950 n_values_per_frame, type);
15952 if(stat != TNG_SUCCESS)
15956 free(current_values);
15963 last_frame_pos = tng_min_i64(n_frames,
15964 end_frame_nr - current_frame_pos);
15966 n_frames_div = current_frame_pos / *stride_length;
15967 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15968 last_frame_pos / *stride_length + 1:
15969 last_frame_pos / *stride_length;
15970 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15972 memcpy(((char *)*values) + n_frames_div * frame_size,
15974 n_frames_div_2 * frame_size);
15976 current_frame_pos += n_frames;
15982 free(current_values);
15985 np_data->last_retrieved_frame = end_frame_nr;
15987 return(TNG_SUCCESS);
15990 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15991 (tng_trajectory_t tng_data,
15992 const int64_t block_id,
15993 union data_values ****values,
15995 int64_t *n_particles,
15996 int64_t *n_values_per_frame,
15999 int64_t i, j, k, mapping, file_pos, i_step, block_index;
16002 tng_particle_data_t data;
16003 tng_trajectory_frame_set_t frame_set;
16004 tng_gen_block_t block;
16005 char block_type_flag;
16006 tng_function_status stat;
16008 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16009 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
16010 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16011 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16012 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16014 frame_set = &tng_data->current_trajectory_frame_set;
16019 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16021 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16023 block_type_flag = TNG_TRAJECTORY_BLOCK;
16027 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16030 tng_block_init(&block);
16031 file_pos = ftello(tng_data->input_file);
16032 /* Read all blocks until next frame set block */
16033 stat = tng_block_header_read(tng_data, block);
16034 while(file_pos < tng_data->input_file_len &&
16035 stat != TNG_CRITICAL &&
16036 block->id != TNG_TRAJECTORY_FRAME_SET &&
16039 /* Use hash by default */
16040 stat = tng_block_read_next(tng_data, block,
16042 if(stat != TNG_CRITICAL)
16044 file_pos = ftello(tng_data->input_file);
16045 if(file_pos < tng_data->input_file_len)
16047 stat = tng_block_header_read(tng_data, block);
16051 tng_block_destroy(&block);
16052 if(stat == TNG_CRITICAL)
16054 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16055 file_pos, __FILE__, __LINE__);
16059 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16061 data = &frame_set->tr_particle_data[i];
16062 if(data->block_id == block_id)
16065 block_type_flag = TNG_TRAJECTORY_BLOCK;
16069 if(block_index < 0)
16071 return(TNG_FAILURE);
16076 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16078 block_type_flag = TNG_TRAJECTORY_BLOCK;
16082 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16086 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16087 tng_data->var_num_atoms_flag)
16089 *n_particles = frame_set->n_particles;
16093 *n_particles = tng_data->n_particles;
16096 *n_frames = tng_max_i64(1, data->n_frames);
16097 *n_values_per_frame = data->n_values_per_frame;
16098 *type = data->datatype;
16102 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16103 *n_particles, *n_values_per_frame,
16107 return(TNG_CRITICAL);
16111 /* It's not very elegant to reuse so much of the code in the different case
16112 * statements, but it's unnecessarily slow to have the switch-case block
16113 * inside the for loops. */
16116 case TNG_CHAR_DATA:
16117 for(i = 0; i < *n_frames; i++)
16119 for(j = 0; j < *n_particles; j++)
16121 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16122 for(k = 0; k < *n_values_per_frame; k++)
16124 len = strlen(data->strings[i][j][k]) + 1;
16125 (*values)[i][mapping][k].c = malloc(len);
16126 strncpy((*values)[i][mapping][k].c,
16127 data->strings[i][j][k], len);
16133 size = sizeof(int);
16134 i_step = (*n_particles) * (*n_values_per_frame);
16135 for(i = 0; i < *n_frames; i++)
16137 for(j = 0; j < *n_particles; j++)
16139 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16140 for(k = 0; k < *n_values_per_frame; k++)
16142 (*values)[i][mapping][k].i = *(int *)
16143 ((char *)data->values + size *
16145 (*n_values_per_frame) + k));
16150 case TNG_FLOAT_DATA:
16151 size = sizeof(float);
16152 i_step = (*n_particles) * (*n_values_per_frame);
16153 for(i = 0; i < *n_frames; i++)
16155 for(j = 0; j < *n_particles; j++)
16157 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16158 for(k = 0; k < *n_values_per_frame; k++)
16160 (*values)[i][mapping][k].f = *(float *)
16161 ((char *)data->values + size *
16163 (*n_values_per_frame) + k));
16168 case TNG_DOUBLE_DATA:
16170 size = sizeof(double);
16171 i_step = (*n_particles) * (*n_values_per_frame);
16172 for(i = 0; i < *n_frames; i++)
16174 for(j = 0; j < *n_particles; j++)
16176 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16177 for(k = 0; k < *n_values_per_frame; k++)
16179 (*values)[i][mapping][k].d = *(double *)
16180 ((char *)data->values + size *
16182 (*n_values_per_frame) + k));
16188 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16190 return(TNG_SUCCESS);
16193 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16194 (tng_trajectory_t tng_data,
16195 const int64_t block_id,
16198 int64_t *stride_length,
16199 int64_t *n_particles,
16200 int64_t *n_values_per_frame,
16203 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16204 int64_t block_index;
16206 tng_particle_data_t data;
16207 tng_trajectory_frame_set_t frame_set;
16208 tng_gen_block_t block;
16210 char block_type_flag;
16211 tng_function_status stat;
16213 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16214 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16215 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16216 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16217 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16219 frame_set = &tng_data->current_trajectory_frame_set;
16224 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16226 tng_block_init(&block);
16227 file_pos = ftello(tng_data->input_file);
16228 /* Read all blocks until next frame set block */
16229 stat = tng_block_header_read(tng_data, block);
16230 while(file_pos < tng_data->input_file_len &&
16231 stat != TNG_CRITICAL &&
16232 block->id != TNG_TRAJECTORY_FRAME_SET &&
16235 /* Use hash by default */
16236 stat = tng_block_read_next(tng_data, block,
16238 if(stat != TNG_CRITICAL)
16240 file_pos = ftello(tng_data->input_file);
16241 if(file_pos < tng_data->input_file_len)
16243 stat = tng_block_header_read(tng_data, block);
16247 tng_block_destroy(&block);
16248 if(stat == TNG_CRITICAL)
16250 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16251 file_pos, __FILE__, __LINE__);
16255 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16257 data = &frame_set->tr_particle_data[i];
16258 if(data->block_id == block_id)
16264 if(block_index < 0)
16266 return(TNG_FAILURE);
16270 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16272 block_type_flag = TNG_TRAJECTORY_BLOCK;
16276 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16279 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16280 tng_data->var_num_atoms_flag)
16282 *n_particles = frame_set->n_particles;
16286 *n_particles = tng_data->n_particles;
16289 *type = data->datatype;
16293 case TNG_CHAR_DATA:
16294 return(TNG_FAILURE);
16296 size = sizeof(int64_t);
16298 case TNG_FLOAT_DATA:
16299 size = sizeof(float);
16301 case TNG_DOUBLE_DATA:
16303 size = sizeof(double);
16306 *n_frames = tng_max_i64(1, data->n_frames);
16307 *n_values_per_frame = data->n_values_per_frame;
16308 *stride_length = data->stride_length;
16310 n_frames_div = (*n_frames % *stride_length) ?
16311 *n_frames / *stride_length + 1:
16312 *n_frames / *stride_length;
16314 data_size = n_frames_div * size * (*n_particles) *
16315 (*n_values_per_frame);
16317 temp = realloc(*values, data_size);
16320 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16321 data_size, __FILE__, __LINE__);
16324 return(TNG_CRITICAL);
16329 if(frame_set->n_mapping_blocks <= 0)
16331 memcpy(*values, data->values, data_size);
16335 i_step = (*n_particles) * (*n_values_per_frame);
16336 for(i = 0; i < *n_frames; i++)
16338 for(j = 0; j < *n_particles; j++)
16340 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16341 memcpy(((char *)*values) + size * (i * i_step + mapping *
16342 (*n_values_per_frame)),
16343 (char *)data->values + size *
16344 (i * i_step + j * (*n_values_per_frame)),
16345 size * (*n_values_per_frame));
16350 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16352 return(TNG_SUCCESS);
16355 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16356 (tng_trajectory_t tng_data,
16357 const int64_t block_id,
16358 const int64_t start_frame_nr,
16359 const int64_t end_frame_nr,
16360 const char hash_mode,
16361 union data_values ****values,
16362 int64_t *n_particles,
16363 int64_t *n_values_per_frame,
16366 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16367 int64_t first_frame, block_index;
16370 tng_particle_data_t data;
16371 tng_trajectory_frame_set_t frame_set;
16372 tng_gen_block_t block;
16373 char block_type_flag;
16374 tng_function_status stat;
16376 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16377 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16378 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16379 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16380 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16384 frame_set = &tng_data->current_trajectory_frame_set;
16385 first_frame = frame_set->first_frame;
16387 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16388 if(stat != TNG_SUCCESS)
16393 /* Do not re-read the frame set. */
16394 if(first_frame != frame_set->first_frame ||
16395 frame_set->n_particle_data_blocks <= 0)
16397 tng_block_init(&block);
16398 file_pos = ftello(tng_data->input_file);
16399 /* Read all blocks until next frame set block */
16400 stat = tng_block_header_read(tng_data, block);
16401 while(file_pos < tng_data->input_file_len &&
16402 stat != TNG_CRITICAL &&
16403 block->id != TNG_TRAJECTORY_FRAME_SET &&
16406 stat = tng_block_read_next(tng_data, block,
16408 if(stat != TNG_CRITICAL)
16410 file_pos = ftello(tng_data->input_file);
16411 if(file_pos < tng_data->input_file_len)
16413 stat = tng_block_header_read(tng_data, block);
16417 tng_block_destroy(&block);
16418 if(stat == TNG_CRITICAL)
16420 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16421 file_pos, __FILE__, __LINE__);
16426 /* See if there is already a data block of this ID.
16427 * Start checking the last read frame set */
16428 for(i = frame_set->n_particle_data_blocks; i-- ;)
16430 data = &frame_set->tr_particle_data[i];
16431 if(data->block_id == block_id)
16434 block_type_flag = TNG_TRAJECTORY_BLOCK;
16439 if(block_index < 0)
16441 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16442 block_id, __FILE__, __LINE__);
16443 return(TNG_FAILURE);
16446 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16447 tng_data->var_num_atoms_flag)
16449 *n_particles = frame_set->n_particles;
16453 *n_particles = tng_data->n_particles;
16456 n_frames = end_frame_nr - start_frame_nr + 1;
16457 *n_values_per_frame = data->n_values_per_frame;
16458 *type = data->datatype;
16462 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16463 *n_particles, *n_values_per_frame,
16467 return(TNG_CRITICAL);
16471 current_frame_pos = start_frame_nr - frame_set->first_frame;
16472 /* It's not very elegant to reuse so much of the code in the different case
16473 * statements, but it's unnecessarily slow to have the switch-case block
16474 * inside the for loops. */
16477 case TNG_CHAR_DATA:
16478 for(i=0; i<n_frames; i++)
16480 if(current_frame_pos == frame_set->n_frames)
16482 stat = tng_frame_set_read_next(tng_data, hash_mode);
16483 if(stat != TNG_SUCCESS)
16487 current_frame_pos = 0;
16489 for(j = 0; j < *n_particles; j++)
16491 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16492 for(k = 0; k < *n_values_per_frame; k++)
16494 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16495 (*values)[i][mapping][k].c = malloc(len);
16496 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16499 current_frame_pos++;
16503 size = sizeof(int);
16504 i_step = (*n_particles) * (*n_values_per_frame);
16505 for(i=0; i<n_frames; i++)
16507 if(current_frame_pos == frame_set->n_frames)
16509 stat = tng_frame_set_read_next(tng_data, hash_mode);
16510 if(stat != TNG_SUCCESS)
16514 current_frame_pos = 0;
16516 for(j = 0; j < *n_particles; j++)
16518 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16519 for(k = 0; k < *n_values_per_frame; k++)
16521 (*values)[i][mapping][k].i = *(int *)
16522 ((char *)data->values + size *
16523 (current_frame_pos *
16525 (*n_values_per_frame) + k));
16528 current_frame_pos++;
16531 case TNG_FLOAT_DATA:
16532 size = sizeof(float);
16533 i_step = (*n_particles) * (*n_values_per_frame);
16534 for(i=0; i<n_frames; i++)
16536 if(current_frame_pos == frame_set->n_frames)
16538 stat = tng_frame_set_read_next(tng_data, hash_mode);
16539 if(stat != TNG_SUCCESS)
16543 current_frame_pos = 0;
16545 for(j=0; j<*n_particles; j++)
16547 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16548 for(k=0; k<*n_values_per_frame; k++)
16550 (*values)[i][mapping][k].f = *(float *)
16551 ((char *)data->values + size *
16552 (current_frame_pos *
16554 (*n_values_per_frame) + k));
16557 current_frame_pos++;
16560 case TNG_DOUBLE_DATA:
16562 size = sizeof(double);
16563 i_step = (*n_particles) * (*n_values_per_frame);
16564 for(i=0; i<n_frames; i++)
16566 if(current_frame_pos == frame_set->n_frames)
16568 stat = tng_frame_set_read_next(tng_data, hash_mode);
16569 if(stat != TNG_SUCCESS)
16573 current_frame_pos = 0;
16575 for(j=0; j<*n_particles; j++)
16577 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16578 for(k=0; k<*n_values_per_frame; k++)
16580 (*values)[i][mapping][k].d = *(double *)
16581 ((char *)data->values + size *
16582 (current_frame_pos *
16584 (*n_values_per_frame) + k));
16587 current_frame_pos++;
16591 data->last_retrieved_frame = end_frame_nr;
16593 return(TNG_SUCCESS);
16596 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16597 (tng_trajectory_t tng_data,
16598 const int64_t block_id,
16599 const int64_t start_frame_nr,
16600 const int64_t end_frame_nr,
16601 const char hash_mode,
16603 int64_t *n_particles,
16604 int64_t *stride_length,
16605 int64_t *n_values_per_frame,
16608 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16609 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16611 tng_trajectory_frame_set_t frame_set;
16612 tng_particle_data_t p_data;
16613 tng_gen_block_t block;
16614 void *current_values = 0, *temp;
16615 tng_function_status stat;
16617 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16618 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16619 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16620 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16621 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16622 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16624 frame_set = &tng_data->current_trajectory_frame_set;
16625 first_frame = frame_set->first_frame;
16627 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16628 if(stat != TNG_SUCCESS)
16633 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16634 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16635 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16636 if(first_frame != frame_set->first_frame ||
16637 stat != TNG_SUCCESS)
16639 tng_block_init(&block);
16640 if(stat != TNG_SUCCESS)
16642 fseeko(tng_data->input_file,
16643 tng_data->current_trajectory_frame_set_input_file_pos,
16645 stat = tng_block_header_read(tng_data, block);
16646 if(stat != TNG_SUCCESS)
16648 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16649 __FILE__, __LINE__);
16653 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16655 file_pos = ftello(tng_data->input_file);
16656 /* Read until next frame set block */
16657 stat = tng_block_header_read(tng_data, block);
16658 while(file_pos < tng_data->input_file_len &&
16659 stat != TNG_CRITICAL &&
16660 block->id != TNG_TRAJECTORY_FRAME_SET &&
16663 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16665 stat = tng_block_read_next(tng_data, block,
16667 if(stat != TNG_CRITICAL)
16669 file_pos = ftello(tng_data->input_file);
16670 if(file_pos < tng_data->input_file_len)
16672 stat = tng_block_header_read(tng_data, block);
16678 file_pos += block->block_contents_size + block->header_contents_size;
16679 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16680 if(file_pos < tng_data->input_file_len)
16682 stat = tng_block_header_read(tng_data, block);
16686 tng_block_destroy(&block);
16687 if(stat == TNG_CRITICAL)
16689 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16690 file_pos, __FILE__, __LINE__);
16694 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16695 if(stat != TNG_SUCCESS)
16700 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16701 &n_frames, stride_length, n_particles,
16702 n_values_per_frame, type);
16704 if(stat != TNG_SUCCESS || *n_particles == 0)
16708 free(current_values);
16713 if(n_frames == 1 && n_frames < frame_set->n_frames)
16719 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16724 case TNG_CHAR_DATA:
16725 return(TNG_FAILURE);
16727 size = sizeof(int64_t);
16729 case TNG_FLOAT_DATA:
16730 size = sizeof(float);
16732 case TNG_DOUBLE_DATA:
16734 size = sizeof(double);
16737 n_frames_div = (tot_n_frames % *stride_length) ?
16738 tot_n_frames / *stride_length + 1:
16739 tot_n_frames / *stride_length;
16741 data_size = n_frames_div * size * (*n_particles) *
16742 (*n_values_per_frame);
16744 temp = realloc(*values, data_size);
16747 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16748 data_size, __FILE__, __LINE__);
16751 return(TNG_CRITICAL);
16756 if( n_frames == 1 && n_frames < frame_set->n_frames)
16758 memcpy(*values, current_values, size * (*n_particles) *
16759 (*n_values_per_frame));
16763 current_frame_pos = start_frame_nr - frame_set->first_frame;
16765 frame_size = size * (*n_particles) * (*n_values_per_frame);
16767 last_frame_pos = tng_min_i64(n_frames,
16768 end_frame_nr - start_frame_nr);
16770 n_frames_div = current_frame_pos / *stride_length;
16771 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16772 last_frame_pos / *stride_length + 1:
16773 last_frame_pos / *stride_length;
16774 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16776 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16777 n_frames_div_2 * frame_size);
16779 current_frame_pos += n_frames - current_frame_pos;
16781 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16783 stat = tng_frame_set_read_next(tng_data, hash_mode);
16784 if(stat != TNG_SUCCESS)
16788 free(current_values);
16795 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16796 &n_frames, stride_length, n_particles,
16797 n_values_per_frame, type);
16799 if(stat != TNG_SUCCESS)
16803 free(current_values);
16810 last_frame_pos = tng_min_i64(n_frames,
16811 end_frame_nr - current_frame_pos);
16813 n_frames_div = current_frame_pos / *stride_length;
16814 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16815 last_frame_pos / *stride_length + 1:
16816 last_frame_pos / *stride_length;
16817 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16819 memcpy(((char *)*values) + n_frames_div * frame_size,
16821 n_frames_div_2 * frame_size);
16823 current_frame_pos += n_frames;
16829 free(current_values);
16832 p_data->last_retrieved_frame = end_frame_nr;
16834 return(TNG_SUCCESS);
16837 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16838 (const tng_trajectory_t tng_data,
16839 const int64_t block_id,
16841 int64_t *stride_length)
16843 tng_function_status stat;
16844 tng_non_particle_data_t np_data;
16845 tng_particle_data_t p_data;
16846 int64_t orig_file_pos, file_pos;
16847 int is_particle_data;
16849 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16856 stat = tng_frame_set_of_frame_find(tng_data, frame);
16857 if(stat != TNG_SUCCESS)
16862 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16863 stat = tng_data_find(tng_data, block_id, &np_data);
16864 if(stat != TNG_SUCCESS)
16866 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16867 if(stat != TNG_SUCCESS)
16869 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16870 /* If no specific frame was required read until this data block is found */
16873 file_pos = ftello(tng_data->input_file);
16874 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16876 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16877 file_pos = ftello(tng_data->input_file);
16880 if(stat != TNG_SUCCESS)
16882 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16886 stat = tng_data_find(tng_data, block_id, &np_data);
16887 if(stat != TNG_SUCCESS)
16889 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16890 if(stat != TNG_SUCCESS)
16892 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16898 is_particle_data = 1;
16903 is_particle_data = 0;
16908 is_particle_data = 1;
16913 is_particle_data = 0;
16915 if(is_particle_data)
16917 *stride_length = p_data->stride_length;
16921 *stride_length = np_data->stride_length;
16923 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16925 return(TNG_SUCCESS);
16928 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16929 (const tng_trajectory_t tng_data,
16932 struct tm *time_data;
16935 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16936 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16938 secs = tng_data->time;
16940 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16941 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16942 "%4d-%02d-%02d %02d:%02d:%02d",
16943 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16944 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16946 return(TNG_SUCCESS);
16950 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16951 (const char *filename,
16953 tng_trajectory_t *tng_data_p)
16955 tng_function_status stat;
16957 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16959 if(mode != 'r' && mode != 'w' && mode != 'a')
16961 return(TNG_FAILURE);
16964 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16966 tng_trajectory_destroy(tng_data_p);
16967 return(TNG_CRITICAL);
16970 if(mode == 'r' || mode == 'a')
16972 tng_input_file_set(*tng_data_p, filename);
16974 /* Read the file headers */
16975 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16977 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16979 if(stat != TNG_SUCCESS)
16987 tng_output_file_set(*tng_data_p, filename);
16989 else if(mode == 'a')
16991 if((*tng_data_p)->output_file)
16993 fclose((*tng_data_p)->output_file);
16995 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
16996 fseeko((*tng_data_p)->input_file,
16997 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
17000 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
17001 if(stat != TNG_SUCCESS)
17003 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
17004 __FILE__, __LINE__);
17006 (*tng_data_p)->output_file = 0;
17008 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
17009 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
17010 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
17011 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
17012 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
17013 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
17014 if((*tng_data_p)->input_file)
17016 fclose((*tng_data_p)->input_file);
17017 (*tng_data_p)->input_file = 0;
17019 if((*tng_data_p)->input_file_path)
17021 free((*tng_data_p)->input_file_path);
17022 (*tng_data_p)->input_file_path = 0;
17024 tng_output_append_file_set(*tng_data_p, filename);
17026 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
17029 return(TNG_SUCCESS);
17032 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
17033 (tng_trajectory_t *tng_data_p)
17035 tng_trajectory_frame_set_t frame_set;
17037 if(tng_data_p == 0)
17039 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
17040 __FILE__, __LINE__);
17041 return(TNG_FAILURE);
17044 if(*tng_data_p == 0)
17046 return(TNG_SUCCESS);
17049 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
17051 if(frame_set->n_unwritten_frames > 0)
17053 frame_set->n_frames = frame_set->n_unwritten_frames;
17054 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
17057 return(tng_trajectory_destroy(tng_data_p));
17060 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
17061 (tng_trajectory_t tng_data,
17062 const int64_t frame_nr,
17065 int64_t first_frame;
17066 tng_trajectory_frame_set_t frame_set;
17067 tng_function_status stat;
17069 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17070 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
17072 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
17073 if(stat != TNG_SUCCESS)
17075 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
17076 frame_nr, __FILE__, __LINE__);
17080 frame_set = &tng_data->current_trajectory_frame_set;
17081 first_frame = frame_set->first_frame;
17083 if(tng_data->time_per_frame <= 0)
17085 return(TNG_FAILURE);
17088 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
17090 return(TNG_SUCCESS);
17094 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17095 (tng_trajectory_t tng_data,
17097 int64_t **molecule_cnt_list,
17098 tng_molecule_t *mols)
17100 tng_trajectory_frame_set_t frame_set;
17102 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17103 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17105 *n_mols = tng_data->n_molecules;
17107 frame_set = &tng_data->current_trajectory_frame_set;
17108 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17110 *molecule_cnt_list = frame_set->molecule_cnt_list;
17114 *molecule_cnt_list = tng_data->molecule_cnt_list;
17117 *mols = tng_data->molecules;
17119 return(TNG_SUCCESS);
17123 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17124 (tng_trajectory_t tng_data,
17127 tng_molecule_t *mol)
17129 tng_function_status stat;
17131 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17132 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17134 stat = tng_molecule_add(tng_data, name, mol);
17135 if(stat != TNG_SUCCESS)
17139 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17144 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17145 (tng_trajectory_t tng_data,
17146 const tng_molecule_t mol,
17147 int64_t *n_particles,
17152 char ***chain_names,
17153 int64_t **chain_ids)
17161 *n_particles = mol->n_atoms;
17163 *names = malloc(sizeof(char *) * *n_particles);
17164 *types = malloc(sizeof(char *) * *n_particles);
17165 *res_names = malloc(sizeof(char *) * *n_particles);
17166 *chain_names = malloc(sizeof(char *) * *n_particles);
17167 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17168 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17170 for(i = 0; i < *n_particles; i++)
17172 atom = &mol->atoms[i];
17173 res = atom->residue;
17174 chain = res->chain;
17175 (*names)[i] = malloc(strlen(atom->name));
17176 strcpy(*names[i], atom->name);
17177 (*types)[i] = malloc(strlen(atom->atom_type));
17178 strcpy(*types[i], atom->atom_type);
17179 (*res_names)[i] = malloc(strlen(res->name));
17180 strcpy(*res_names[i], res->name);
17181 (*chain_names)[i] = malloc(strlen(chain->name));
17182 strcpy(*chain_names[i], chain->name);
17183 (*res_ids)[i] = res->id;
17184 (*chain_ids)[i] = chain->id;
17187 return(TNG_SUCCESS);
17190 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17191 (tng_trajectory_t tng_data,
17192 tng_molecule_t mol,
17193 const int64_t n_particles,
17194 const char **names,
17195 const char **types,
17196 const char **res_names,
17197 const int64_t *res_ids,
17198 const char **chain_names,
17199 const int64_t *chain_ids)
17203 tng_residue_t residue;
17205 tng_function_status stat;
17207 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17208 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17209 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17210 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17211 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17212 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17213 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17215 for(i = 0; i < n_particles; i++)
17217 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17218 &chain) == TNG_FAILURE)
17220 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17222 if(stat != TNG_SUCCESS)
17227 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17228 &residue) == TNG_FAILURE)
17230 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17232 if(stat != TNG_SUCCESS)
17237 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17238 if(stat != TNG_SUCCESS)
17243 return(TNG_SUCCESS);
17246 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17247 (tng_trajectory_t tng_data,
17248 float **positions, int64_t *stride_length)
17250 int64_t n_frames, n_particles, n_values_per_frame;
17252 tng_function_status stat;
17254 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17255 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17256 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17258 stat = tng_num_frames_get(tng_data, &n_frames);
17259 if(stat != TNG_SUCCESS)
17264 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17265 0, n_frames - 1, TNG_USE_HASH,
17266 (void **)positions,
17269 &n_values_per_frame,
17275 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17276 (tng_trajectory_t tng_data,
17277 float **velocities, int64_t *stride_length)
17279 int64_t n_frames, n_particles, n_values_per_frame;
17281 tng_function_status stat;
17283 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17284 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17285 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17287 stat = tng_num_frames_get(tng_data, &n_frames);
17288 if(stat != TNG_SUCCESS)
17293 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17294 0, n_frames - 1, TNG_USE_HASH,
17295 (void **)velocities,
17298 &n_values_per_frame,
17304 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17305 (tng_trajectory_t tng_data,
17306 float **forces, int64_t *stride_length)
17308 int64_t n_frames, n_particles, n_values_per_frame;
17310 tng_function_status stat;
17312 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17313 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17314 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17316 stat = tng_num_frames_get(tng_data, &n_frames);
17317 if(stat != TNG_SUCCESS)
17322 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17323 0, n_frames - 1, TNG_USE_HASH,
17327 &n_values_per_frame,
17333 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17334 (tng_trajectory_t tng_data,
17336 int64_t *stride_length)
17338 int64_t n_frames, n_values_per_frame;
17340 tng_function_status stat;
17342 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17343 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17344 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17346 stat = tng_num_frames_get(tng_data, &n_frames);
17347 if(stat != TNG_SUCCESS)
17352 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17353 0, n_frames - 1, TNG_USE_HASH,
17354 (void **)box_shape,
17356 &n_values_per_frame,
17362 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17363 (tng_trajectory_t tng_data,
17364 const int64_t block_id,
17367 int64_t *retrieved_frame_number,
17368 double *retrieved_time)
17370 tng_trajectory_frame_set_t frame_set;
17371 tng_particle_data_t data = 0;
17372 tng_function_status stat;
17374 int64_t i, data_size, n_particles, file_pos;
17377 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17378 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17379 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17380 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17381 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17383 frame_set = &tng_data->current_trajectory_frame_set;
17385 stat = tng_particle_data_find(tng_data, block_id, &data);
17386 if(stat != TNG_SUCCESS)
17388 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17389 file_pos = ftello(tng_data->input_file);
17390 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17392 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17393 file_pos = ftello(tng_data->input_file);
17395 if(stat != TNG_SUCCESS)
17399 stat = tng_particle_data_find(tng_data, block_id, &data);
17400 if(stat != TNG_SUCCESS)
17405 if(data->last_retrieved_frame < 0)
17407 fseeko(tng_data->input_file,
17408 tng_data->first_trajectory_frame_set_input_file_pos,
17410 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17411 if(stat != TNG_SUCCESS)
17415 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17416 if(stat != TNG_SUCCESS)
17421 i = data->first_frame_with_data;
17425 if(data->n_frames == 1)
17427 i = data->last_retrieved_frame + 1;
17431 i = data->last_retrieved_frame + data->stride_length;
17433 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17435 stat = tng_frame_set_of_frame_find(tng_data, i);
17436 if(stat != TNG_SUCCESS)
17438 /* If the frame set search found the frame set after the starting
17439 * frame set there is a gap in the frame sets. So, even if the frame
17440 * was not found the next frame with data is still in the found
17442 if(stat == TNG_CRITICAL)
17446 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17448 return(TNG_FAILURE);
17450 i = frame_set->first_frame;
17453 if(data->last_retrieved_frame < frame_set->first_frame)
17455 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17456 if(stat != TNG_SUCCESS)
17462 data->last_retrieved_frame = i;
17463 *retrieved_frame_number = i;
17464 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17466 *retrieved_time = frame_set->first_frame_time +
17467 (i - frame_set->first_frame) *
17468 tng_data->time_per_frame;
17472 *retrieved_time = 0;
17475 if(data->stride_length > 1)
17477 i = (i - data->first_frame_with_data) / data->stride_length;
17481 i = (i - frame_set->first_frame);
17484 tng_num_particles_get(tng_data, &n_particles);
17486 *data_type = data->datatype;
17490 case TNG_CHAR_DATA:
17491 return(TNG_FAILURE);
17493 size = sizeof(int64_t);
17495 case TNG_FLOAT_DATA:
17496 size = sizeof(float);
17498 case TNG_DOUBLE_DATA:
17500 size = sizeof(double);
17503 data_size = size * n_particles * data->n_values_per_frame;
17505 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17506 // i, data_size, size, n_particles, data->n_values_per_frame);
17508 temp = realloc(*values, data_size);
17511 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17512 data_size, __FILE__, __LINE__);
17515 return(TNG_CRITICAL);
17520 memcpy(*values, (char *)data->values + i * data_size, data_size);
17522 return(TNG_SUCCESS);
17525 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17526 (tng_trajectory_t tng_data,
17527 const int64_t block_id,
17530 int64_t *retrieved_frame_number,
17531 double *retrieved_time)
17533 tng_trajectory_frame_set_t frame_set;
17534 tng_non_particle_data_t data = 0;
17535 tng_function_status stat;
17537 int64_t i, data_size, file_pos;
17540 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17541 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17542 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17543 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17544 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17546 frame_set = &tng_data->current_trajectory_frame_set;
17548 stat = tng_data_find(tng_data, block_id, &data);
17549 if(stat != TNG_SUCCESS)
17551 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17552 file_pos = ftello(tng_data->input_file);
17553 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17555 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17556 file_pos = ftello(tng_data->input_file);
17558 if(stat != TNG_SUCCESS)
17562 stat = tng_data_find(tng_data, block_id, &data);
17563 if(stat != TNG_SUCCESS)
17568 if(data->last_retrieved_frame < 0)
17570 fseeko(tng_data->input_file,
17571 tng_data->first_trajectory_frame_set_input_file_pos,
17573 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17574 if(stat != TNG_SUCCESS)
17578 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17579 if(stat != TNG_SUCCESS)
17584 i = data->first_frame_with_data;
17588 if(data->n_frames == 1)
17590 i = data->last_retrieved_frame + 1;
17594 i = data->last_retrieved_frame + data->stride_length;
17596 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17598 stat = tng_frame_set_of_frame_find(tng_data, i);
17599 if(stat != TNG_SUCCESS)
17601 /* If the frame set search found the frame set after the starting
17602 * frame set there is a gap in the frame sets. So, even if the frame
17603 * was not found the next frame with data is still in the found
17605 if(stat == TNG_CRITICAL)
17609 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17611 return(TNG_FAILURE);
17613 i = frame_set->first_frame;
17616 if(data->last_retrieved_frame < frame_set->first_frame)
17618 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17619 if(stat != TNG_SUCCESS)
17625 data->last_retrieved_frame = i;
17626 *retrieved_frame_number = i;
17627 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17629 *retrieved_time = frame_set->first_frame_time +
17630 (i - frame_set->first_frame) *
17631 tng_data->time_per_frame;
17635 *retrieved_time = 0;
17638 if(data->stride_length > 1)
17640 i = (i - data->first_frame_with_data) / data->stride_length;
17644 i = (i - frame_set->first_frame);
17647 *data_type = data->datatype;
17651 case TNG_CHAR_DATA:
17652 return(TNG_FAILURE);
17654 size = sizeof(int64_t);
17656 case TNG_FLOAT_DATA:
17657 size = sizeof(float);
17659 case TNG_DOUBLE_DATA:
17661 size = sizeof(double);
17664 data_size = size * data->n_values_per_frame;
17666 temp = realloc(*values, data_size);
17669 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17670 data_size, __FILE__, __LINE__);
17673 return(TNG_CRITICAL);
17678 memcpy(*values, (char *)data->values + i * data_size, data_size);
17680 return(TNG_SUCCESS);
17683 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17684 (tng_trajectory_t tng_data,
17685 const int64_t first_frame,
17686 const int64_t last_frame,
17688 int64_t *stride_length)
17690 int64_t n_particles, n_values_per_frame;
17692 tng_function_status stat;
17694 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17695 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17696 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17697 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17699 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17700 first_frame, last_frame,
17702 (void **)positions,
17705 &n_values_per_frame,
17711 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17712 (tng_trajectory_t tng_data,
17713 const int64_t first_frame,
17714 const int64_t last_frame,
17715 float **velocities,
17716 int64_t *stride_length)
17718 int64_t n_particles, n_values_per_frame;
17720 tng_function_status stat;
17722 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17723 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17724 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17725 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17727 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17728 first_frame, last_frame,
17730 (void **)velocities,
17733 &n_values_per_frame,
17739 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17740 (tng_trajectory_t tng_data,
17741 const int64_t first_frame,
17742 const int64_t last_frame,
17744 int64_t *stride_length)
17746 int64_t n_particles, n_values_per_frame;
17748 tng_function_status stat;
17750 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17751 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17752 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17753 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17755 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17756 first_frame, last_frame,
17761 &n_values_per_frame,
17767 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17768 (tng_trajectory_t tng_data,
17769 const int64_t first_frame,
17770 const int64_t last_frame,
17772 int64_t *stride_length)
17774 int64_t n_values_per_frame;
17776 tng_function_status stat;
17778 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17779 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17780 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17781 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17783 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17784 first_frame, last_frame,
17786 (void **)box_shape,
17788 &n_values_per_frame,
17794 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17795 (tng_trajectory_t tng_data,
17797 const int64_t n_values_per_frame,
17798 const int64_t block_id,
17799 const char *block_name,
17800 const char particle_dependency,
17801 const char compression)
17803 tng_trajectory_frame_set_t frame_set;
17804 tng_particle_data_t p_data;
17805 tng_non_particle_data_t np_data;
17806 int64_t n_particles, n_frames;
17807 tng_function_status stat;
17809 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17810 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17814 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17815 i, __FILE__, __LINE__);
17816 return(TNG_FAILURE);
17819 frame_set = &tng_data->current_trajectory_frame_set;
17821 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17823 n_frames = tng_data->frame_set_n_frames;
17825 stat = tng_frame_set_new(tng_data, 0, n_frames);
17826 if(stat != TNG_SUCCESS)
17828 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17835 n_frames = frame_set->n_frames;
17838 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17840 tng_num_particles_get(tng_data, &n_particles);
17841 if(n_particles <= 0)
17843 return(TNG_FAILURE);
17846 if(tng_particle_data_find(tng_data, block_id, &p_data)
17849 stat = tng_particle_data_block_add(tng_data, block_id,
17852 TNG_TRAJECTORY_BLOCK,
17853 n_frames, n_values_per_frame, i,
17856 if(stat != TNG_SUCCESS)
17858 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17859 __FILE__, __LINE__);
17862 p_data = &frame_set->tr_particle_data[frame_set->
17863 n_particle_data_blocks - 1];
17864 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17866 n_values_per_frame);
17867 if(stat != TNG_SUCCESS)
17869 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17870 __FILE__, __LINE__);
17876 if(p_data->stride_length != i)
17878 p_data->stride_length = i;
17879 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17881 n_values_per_frame);
17882 if(stat != TNG_SUCCESS)
17884 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17885 __FILE__, __LINE__);
17893 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17895 stat = tng_data_block_add(tng_data, block_id, block_name,
17896 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17897 n_frames, n_values_per_frame,
17898 i, compression, 0);
17899 if(stat != TNG_SUCCESS)
17901 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17902 __FILE__, __LINE__);
17905 np_data = &frame_set->tr_data[frame_set->
17906 n_data_blocks - 1];
17907 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17908 i, n_values_per_frame);
17909 if(stat != TNG_SUCCESS)
17911 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17912 __FILE__, __LINE__);
17918 if(np_data->stride_length != i)
17920 np_data->stride_length = i;
17921 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17922 i, n_values_per_frame);
17923 if(stat != TNG_SUCCESS)
17925 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17926 __FILE__, __LINE__);
17933 return(TNG_SUCCESS);
17936 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17937 (tng_trajectory_t tng_data,
17939 const int64_t n_values_per_frame,
17940 const int64_t block_id,
17941 const char *block_name,
17942 const char particle_dependency,
17943 const char compression)
17945 tng_trajectory_frame_set_t frame_set;
17946 tng_particle_data_t p_data;
17947 tng_non_particle_data_t np_data;
17948 int64_t n_particles, n_frames;
17949 tng_function_status stat;
17951 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17952 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17956 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17957 i, __FILE__, __LINE__);
17958 return(TNG_FAILURE);
17961 frame_set = &tng_data->current_trajectory_frame_set;
17963 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17965 n_frames = tng_data->frame_set_n_frames;
17967 stat = tng_frame_set_new(tng_data, 0, n_frames);
17968 if(stat != TNG_SUCCESS)
17970 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17977 n_frames = frame_set->n_frames;
17980 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17982 tng_num_particles_get(tng_data, &n_particles);
17984 if(n_particles <= 0)
17986 return(TNG_FAILURE);
17989 if(tng_particle_data_find(tng_data, block_id, &p_data)
17992 stat = tng_particle_data_block_add(tng_data, block_id,
17995 TNG_TRAJECTORY_BLOCK,
17996 n_frames, n_values_per_frame, i,
17999 if(stat != TNG_SUCCESS)
18001 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18002 __FILE__, __LINE__);
18005 p_data = &frame_set->tr_particle_data[frame_set->
18006 n_particle_data_blocks - 1];
18007 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18009 n_values_per_frame);
18010 if(stat != TNG_SUCCESS)
18012 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18013 __FILE__, __LINE__);
18019 p_data->stride_length = i;
18024 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18026 stat = tng_data_block_add(tng_data, block_id, block_name,
18027 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
18028 n_frames, n_values_per_frame,
18029 i, compression, 0);
18030 if(stat != TNG_SUCCESS)
18032 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18033 __FILE__, __LINE__);
18036 np_data = &frame_set->tr_data[frame_set->
18037 n_data_blocks - 1];
18038 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18039 i, n_values_per_frame);
18040 if(stat != TNG_SUCCESS)
18042 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18043 __FILE__, __LINE__);
18049 np_data->stride_length = i;
18053 return(TNG_SUCCESS);
18056 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
18057 (tng_trajectory_t tng_data,
18059 const int64_t n_values_per_frame,
18060 const int64_t block_id,
18061 const char *block_name,
18062 const char particle_dependency,
18063 const char compression)
18065 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
18066 "See documentation. %s: %d", __FILE__, __LINE__);
18067 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
18068 block_id, block_name,
18069 particle_dependency,
18072 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18073 (tng_trajectory_t tng_data,
18076 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18077 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18079 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18080 TNG_TRAJ_POSITIONS,
18082 TNG_PARTICLE_BLOCK_DATA,
18083 TNG_TNG_COMPRESSION));
18086 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18087 (tng_trajectory_t tng_data,
18090 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18091 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18093 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18094 TNG_TRAJ_POSITIONS,
18096 TNG_PARTICLE_BLOCK_DATA,
18097 TNG_TNG_COMPRESSION));
18100 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18101 (tng_trajectory_t tng_data,
18104 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18105 "See documentation. %s: %d", __FILE__, __LINE__);
18106 return(tng_util_pos_write_interval_set(tng_data, i));
18109 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18110 (tng_trajectory_t tng_data,
18113 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18114 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18116 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18117 TNG_TRAJ_VELOCITIES,
18119 TNG_PARTICLE_BLOCK_DATA,
18120 TNG_TNG_COMPRESSION));
18123 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18124 (tng_trajectory_t tng_data,
18127 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18128 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18130 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18131 TNG_TRAJ_VELOCITIES,
18133 TNG_PARTICLE_BLOCK_DATA,
18134 TNG_TNG_COMPRESSION));
18137 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18138 (tng_trajectory_t tng_data,
18141 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18142 "See documentation. %s: %d", __FILE__, __LINE__);
18143 return(tng_util_vel_write_interval_set(tng_data, i));
18146 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18147 (tng_trajectory_t tng_data,
18150 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18151 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18153 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18156 TNG_PARTICLE_BLOCK_DATA,
18157 TNG_GZIP_COMPRESSION));
18160 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18161 (tng_trajectory_t tng_data,
18164 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18165 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18167 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18170 TNG_PARTICLE_BLOCK_DATA,
18171 TNG_GZIP_COMPRESSION));
18174 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18175 (tng_trajectory_t tng_data,
18178 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18179 "See documentation. %s: %d", __FILE__, __LINE__);
18180 return(tng_util_force_write_interval_set(tng_data, i));
18183 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18184 (tng_trajectory_t tng_data,
18187 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18188 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18190 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18191 TNG_TRAJ_BOX_SHAPE,
18193 TNG_NON_PARTICLE_BLOCK_DATA,
18194 TNG_GZIP_COMPRESSION));
18197 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18198 (tng_trajectory_t tng_data,
18201 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18202 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18204 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18205 TNG_TRAJ_BOX_SHAPE,
18207 TNG_NON_PARTICLE_BLOCK_DATA,
18208 TNG_GZIP_COMPRESSION));
18211 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18212 (tng_trajectory_t tng_data,
18215 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18216 "See documentation. %s: %d", __FILE__, __LINE__);
18217 return(tng_util_box_shape_write_interval_set(tng_data, i));
18220 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18221 (tng_trajectory_t tng_data,
18222 const int64_t frame_nr,
18223 const float *values,
18224 const int64_t n_values_per_frame,
18225 const int64_t block_id,
18226 const char *block_name,
18227 const char particle_dependency,
18228 const char compression)
18230 tng_trajectory_frame_set_t frame_set;
18231 tng_particle_data_t p_data;
18232 tng_non_particle_data_t np_data;
18233 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18234 int64_t last_frame;
18235 int is_first_frame_flag = 0;
18236 char block_type_flag;
18237 tng_function_status stat;
18239 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18240 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18241 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18243 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18245 tng_num_particles_get(tng_data, &n_particles);
18246 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18251 return(TNG_FAILURE);
18254 frame_set = &tng_data->current_trajectory_frame_set;
18258 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18259 n_frames = stride_length = 1;
18263 block_type_flag = TNG_TRAJECTORY_BLOCK;
18265 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18267 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18268 if(stat != TNG_SUCCESS)
18270 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18275 last_frame = frame_set->first_frame +
18276 frame_set->n_frames - 1;
18277 if(frame_nr > last_frame)
18279 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18280 if(stat != TNG_SUCCESS)
18282 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18286 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18288 last_frame = frame_nr - 1;
18290 stat = tng_frame_set_new(tng_data, last_frame + 1,
18291 tng_data->frame_set_n_frames);
18292 if(stat != TNG_SUCCESS)
18294 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18299 if(frame_set->n_unwritten_frames == 0)
18301 is_first_frame_flag = 1;
18303 frame_set->n_unwritten_frames = frame_nr -
18304 frame_set->first_frame + 1;
18306 n_frames = frame_set->n_frames;
18309 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18311 if(tng_particle_data_find(tng_data, block_id, &p_data)
18314 stat = tng_particle_data_block_add(tng_data, block_id,
18318 n_frames, n_values_per_frame,
18322 if(stat != TNG_SUCCESS)
18324 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18325 __FILE__, __LINE__);
18328 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18330 p_data = &frame_set->tr_particle_data[frame_set->
18331 n_particle_data_blocks - 1];
18335 p_data = &tng_data->non_tr_particle_data[tng_data->
18336 n_particle_data_blocks - 1];
18338 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18339 stride_length, n_particles,
18340 n_values_per_frame);
18341 if(stat != TNG_SUCCESS)
18343 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18344 __FILE__, __LINE__);
18349 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18351 stride_length = p_data->stride_length;
18353 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18355 p_data->first_frame_with_data = frame_nr;
18360 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18363 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18364 n_values_per_frame, values, sizeof(float) *
18365 n_particles * n_values_per_frame);
18369 memcpy(p_data->values, values, sizeof(float) * n_particles *
18370 n_values_per_frame);
18375 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18377 stat = tng_data_block_add(tng_data, block_id, block_name,
18378 TNG_FLOAT_DATA, block_type_flag,
18379 n_frames, n_values_per_frame,
18380 stride_length, compression, 0);
18381 if(stat != TNG_SUCCESS)
18383 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18384 __FILE__, __LINE__);
18387 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18389 np_data = &frame_set->tr_data[frame_set->
18390 n_data_blocks - 1];
18394 np_data = &tng_data->non_tr_data[tng_data->
18395 n_data_blocks - 1];
18397 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18398 stride_length, n_values_per_frame);
18399 if(stat != TNG_SUCCESS)
18401 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18402 __FILE__, __LINE__);
18407 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18409 stride_length = np_data->stride_length;
18411 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18413 np_data->first_frame_with_data = frame_nr;
18418 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18421 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18422 n_values_per_frame, values, sizeof(float) *
18423 n_values_per_frame);
18427 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18431 return(TNG_SUCCESS);
18434 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18435 (tng_trajectory_t tng_data,
18436 const int64_t frame_nr,
18437 const double *values,
18438 const int64_t n_values_per_frame,
18439 const int64_t block_id,
18440 const char *block_name,
18441 const char particle_dependency,
18442 const char compression)
18444 tng_trajectory_frame_set_t frame_set;
18445 tng_particle_data_t p_data;
18446 tng_non_particle_data_t np_data;
18447 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18448 int64_t last_frame;
18449 int is_first_frame_flag = 0;
18450 char block_type_flag;
18451 tng_function_status stat;
18453 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18454 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18455 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18457 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18459 tng_num_particles_get(tng_data, &n_particles);
18460 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18465 return(TNG_FAILURE);
18468 frame_set = &tng_data->current_trajectory_frame_set;
18472 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18473 n_frames = stride_length = 1;
18477 block_type_flag = TNG_TRAJECTORY_BLOCK;
18479 n_frames = tng_data->frame_set_n_frames;
18481 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18483 stat = tng_frame_set_new(tng_data, 0, n_frames);
18484 if(stat != TNG_SUCCESS)
18486 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18493 n_frames = frame_set->n_frames;
18495 last_frame = frame_set->first_frame +
18496 frame_set->n_frames - 1;
18497 if(frame_nr > last_frame)
18499 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18500 if(stat != TNG_SUCCESS)
18502 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18506 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18508 last_frame = frame_nr - 1;
18510 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18511 if(stat != TNG_SUCCESS)
18513 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18518 if(frame_set->n_unwritten_frames == 0)
18520 is_first_frame_flag = 1;
18522 frame_set->n_unwritten_frames = frame_nr -
18523 frame_set->first_frame + 1;
18526 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18528 if(tng_particle_data_find(tng_data, block_id, &p_data)
18531 stat = tng_particle_data_block_add(tng_data, block_id,
18535 n_frames, n_values_per_frame,
18539 if(stat != TNG_SUCCESS)
18541 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18542 __FILE__, __LINE__);
18545 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18547 p_data = &frame_set->tr_particle_data[frame_set->
18548 n_particle_data_blocks - 1];
18552 p_data = &tng_data->non_tr_particle_data[tng_data->
18553 n_particle_data_blocks - 1];
18555 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18556 stride_length, n_particles,
18557 n_values_per_frame);
18558 if(stat != TNG_SUCCESS)
18560 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18561 __FILE__, __LINE__);
18566 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18568 stride_length = p_data->stride_length;
18570 if(is_first_frame_flag)
18572 p_data->first_frame_with_data = frame_nr;
18577 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18580 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18581 n_values_per_frame, values, sizeof(double) *
18582 n_particles * n_values_per_frame);
18586 memcpy(p_data->values, values, sizeof(double) * n_particles *
18587 n_values_per_frame);
18592 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18594 stat = tng_data_block_add(tng_data, block_id, block_name,
18595 TNG_DOUBLE_DATA, block_type_flag,
18596 n_frames, n_values_per_frame,
18597 stride_length, compression, 0);
18598 if(stat != TNG_SUCCESS)
18600 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18601 __FILE__, __LINE__);
18604 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18606 np_data = &frame_set->tr_data[frame_set->
18607 n_data_blocks - 1];
18611 np_data = &tng_data->non_tr_data[tng_data->
18612 n_data_blocks - 1];
18614 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18615 stride_length, n_values_per_frame);
18616 if(stat != TNG_SUCCESS)
18618 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18619 __FILE__, __LINE__);
18624 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18626 stride_length = np_data->stride_length;
18628 if(is_first_frame_flag)
18630 np_data->first_frame_with_data = frame_nr;
18635 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18638 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18639 n_values_per_frame, values, sizeof(double) *
18640 n_values_per_frame);
18644 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18648 return(TNG_SUCCESS);
18651 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18652 (tng_trajectory_t tng_data,
18653 const int64_t frame_nr,
18654 const float *positions)
18656 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18657 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18658 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18660 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18661 TNG_TRAJ_POSITIONS, "POSITIONS",
18662 TNG_PARTICLE_BLOCK_DATA,
18663 TNG_TNG_COMPRESSION));
18666 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18667 (tng_trajectory_t tng_data,
18668 const int64_t frame_nr,
18669 const double *positions)
18671 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18672 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18673 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18675 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18676 TNG_TRAJ_POSITIONS, "POSITIONS",
18677 TNG_PARTICLE_BLOCK_DATA,
18678 TNG_TNG_COMPRESSION));
18681 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18682 (tng_trajectory_t tng_data,
18683 const int64_t frame_nr,
18684 const float *velocities)
18686 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18687 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18688 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18690 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18691 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18692 TNG_PARTICLE_BLOCK_DATA,
18693 TNG_TNG_COMPRESSION));
18696 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18697 (tng_trajectory_t tng_data,
18698 const int64_t frame_nr,
18699 const double *velocities)
18701 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18702 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18703 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18705 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18706 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18707 TNG_PARTICLE_BLOCK_DATA,
18708 TNG_TNG_COMPRESSION));
18711 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18712 (tng_trajectory_t tng_data,
18713 const int64_t frame_nr,
18714 const float *forces)
18716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18717 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18718 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18720 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18721 TNG_TRAJ_FORCES, "FORCES",
18722 TNG_PARTICLE_BLOCK_DATA,
18723 TNG_GZIP_COMPRESSION));
18726 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18727 (tng_trajectory_t tng_data,
18728 const int64_t frame_nr,
18729 const double *forces)
18731 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18732 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18733 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18735 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18736 TNG_TRAJ_FORCES, "FORCES",
18737 TNG_PARTICLE_BLOCK_DATA,
18738 TNG_GZIP_COMPRESSION));
18741 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18742 (tng_trajectory_t tng_data,
18743 const int64_t frame_nr,
18744 const float *box_shape)
18746 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18747 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18748 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18750 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18751 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18752 TNG_NON_PARTICLE_BLOCK_DATA,
18753 TNG_GZIP_COMPRESSION));
18756 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18757 (tng_trajectory_t tng_data,
18758 const int64_t frame_nr,
18759 const double *box_shape)
18761 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18762 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18763 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18765 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18766 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18767 TNG_NON_PARTICLE_BLOCK_DATA,
18768 TNG_GZIP_COMPRESSION));
18771 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18772 (tng_trajectory_t tng_data,
18773 const int64_t frame_nr,
18775 const float *values,
18776 const int64_t n_values_per_frame,
18777 const int64_t block_id,
18778 const char *block_name,
18779 const char particle_dependency,
18780 const char compression)
18782 tng_trajectory_frame_set_t frame_set;
18783 tng_function_status stat;
18785 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18786 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18787 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18788 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18790 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18791 block_id, block_name,
18792 particle_dependency,
18795 if(stat != TNG_SUCCESS)
18800 frame_set = &tng_data->current_trajectory_frame_set;
18802 /* first_frame_time is -1 when it is not yet set. */
18803 if(frame_set->first_frame_time < -0.1)
18805 if(frame_nr > frame_set->first_frame)
18807 stat = tng_frame_set_first_frame_time_set(tng_data,
18810 frame_set->first_frame) *
18811 tng_data->time_per_frame);
18815 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18821 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18822 (tng_trajectory_t tng_data,
18823 const int64_t frame_nr,
18825 const double *values,
18826 const int64_t n_values_per_frame,
18827 const int64_t block_id,
18828 const char *block_name,
18829 const char particle_dependency,
18830 const char compression)
18832 tng_trajectory_frame_set_t frame_set;
18833 tng_function_status stat;
18835 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18836 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18837 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18838 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18840 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18841 block_id, block_name,
18842 particle_dependency,
18845 if(stat != TNG_SUCCESS)
18850 frame_set = &tng_data->current_trajectory_frame_set;
18852 /* first_frame_time is -1 when it is not yet set. */
18853 if(frame_set->first_frame_time < -0.1)
18855 if(frame_nr > frame_set->first_frame)
18857 stat = tng_frame_set_first_frame_time_set(tng_data,
18860 frame_set->first_frame) *
18861 tng_data->time_per_frame);
18865 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18871 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18872 (tng_trajectory_t tng_data,
18873 const int64_t frame_nr,
18875 const float *positions)
18877 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18878 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18879 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18880 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18882 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18883 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18884 TNG_PARTICLE_BLOCK_DATA,
18885 TNG_TNG_COMPRESSION));
18888 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18889 (tng_trajectory_t tng_data,
18890 const int64_t frame_nr,
18892 const double *positions)
18894 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18895 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18896 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18897 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18899 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18901 TNG_TRAJ_POSITIONS,
18903 TNG_PARTICLE_BLOCK_DATA,
18904 TNG_TNG_COMPRESSION));
18907 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18908 (tng_trajectory_t tng_data,
18909 const int64_t frame_nr,
18911 const float *velocities)
18913 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18914 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18915 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18916 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18918 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18920 TNG_TRAJ_VELOCITIES,
18922 TNG_PARTICLE_BLOCK_DATA,
18923 TNG_TNG_COMPRESSION));
18926 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18927 (tng_trajectory_t tng_data,
18928 const int64_t frame_nr,
18930 const double *velocities)
18932 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18933 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18934 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18935 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18937 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18939 TNG_TRAJ_VELOCITIES,
18941 TNG_PARTICLE_BLOCK_DATA,
18942 TNG_TNG_COMPRESSION));
18945 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18946 (tng_trajectory_t tng_data,
18947 const int64_t frame_nr,
18949 const float *forces)
18951 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18952 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18953 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18954 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18956 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18957 3, TNG_TRAJ_FORCES, "FORCES",
18958 TNG_PARTICLE_BLOCK_DATA,
18959 TNG_GZIP_COMPRESSION));
18962 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18963 (tng_trajectory_t tng_data,
18964 const int64_t frame_nr,
18966 const double *forces)
18968 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18969 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18970 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18971 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18973 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18975 TNG_TRAJ_FORCES, "FORCES",
18976 TNG_PARTICLE_BLOCK_DATA,
18977 TNG_GZIP_COMPRESSION));
18980 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18981 (tng_trajectory_t tng_data,
18982 const int64_t frame_nr,
18984 const float *box_shape)
18986 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18987 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18988 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18989 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18991 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18992 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18993 TNG_NON_PARTICLE_BLOCK_DATA,
18994 TNG_GZIP_COMPRESSION));
18997 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18998 (tng_trajectory_t tng_data,
18999 const int64_t frame_nr,
19001 const double *box_shape)
19003 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19004 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
19005 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
19006 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
19008 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
19009 time, box_shape, 9,
19010 TNG_TRAJ_BOX_SHAPE,
19012 TNG_NON_PARTICLE_BLOCK_DATA,
19013 TNG_GZIP_COMPRESSION));
19016 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
19017 (tng_trajectory_t tng_data,
19018 const int64_t block_id,
19022 tng_trajectory_frame_set_t frame_set;
19023 tng_particle_data_t p_data = 0;
19024 tng_non_particle_data_t np_data = 0;
19025 tng_function_status stat;
19027 int block_type = -1;
19029 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19030 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
19031 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
19033 frame_set = &tng_data->current_trajectory_frame_set;
19035 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19036 if(stat == TNG_SUCCESS)
19038 block_type = TNG_PARTICLE_BLOCK_DATA;
19042 stat = tng_data_find(tng_data, block_id, &np_data);
19043 if(stat == TNG_SUCCESS)
19045 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19049 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19050 if(stat != TNG_SUCCESS)
19054 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19055 if(stat == TNG_SUCCESS)
19057 block_type = TNG_PARTICLE_BLOCK_DATA;
19061 stat = tng_data_find(tng_data, block_id, &np_data);
19062 if(stat == TNG_SUCCESS)
19064 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19073 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19075 if(p_data->last_retrieved_frame < 0)
19077 i = p_data->first_frame_with_data;
19081 i = p_data->last_retrieved_frame;
19084 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19086 if(np_data->last_retrieved_frame < 0)
19088 i = np_data->first_frame_with_data;
19092 i = np_data->last_retrieved_frame;
19097 return(TNG_FAILURE);
19099 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
19101 stat = tng_frame_set_of_frame_find(tng_data, i);
19102 if(stat != TNG_SUCCESS)
19106 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19107 if(stat != TNG_SUCCESS)
19109 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19110 __FILE__, __LINE__);
19114 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19116 *codec_id = p_data->codec_id;
19117 *factor = p_data->compression_multiplier;
19119 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19121 *codec_id = np_data->codec_id;
19122 *factor = np_data->compression_multiplier;
19124 return(TNG_SUCCESS);
19127 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19128 (tng_trajectory_t tng_data,
19129 int64_t current_frame,
19130 const int64_t n_requested_data_block_ids,
19131 const int64_t *requested_data_block_ids,
19132 int64_t *next_frame,
19133 int64_t *n_data_blocks_in_next_frame,
19134 int64_t **data_block_ids_in_next_frame)
19136 tng_trajectory_frame_set_t frame_set;
19137 tng_function_status stat;
19138 tng_particle_data_t p_data;
19139 tng_non_particle_data_t np_data;
19140 tng_gen_block_t block;
19141 int64_t i, j, block_id, *temp;
19142 int64_t data_frame, frame_diff, min_diff;
19143 int64_t size, frame_set_file_pos, file_pos;
19144 int found, read_all = 0;
19146 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19147 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19148 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19149 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19151 if(n_requested_data_block_ids)
19153 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.");
19154 size = sizeof(int64_t) * n_requested_data_block_ids;
19155 temp = realloc(*data_block_ids_in_next_frame, size);
19158 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19159 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19160 __FILE__, __LINE__);
19161 free(*data_block_ids_in_next_frame);
19162 *data_block_ids_in_next_frame = 0;
19163 return(TNG_CRITICAL);
19165 *data_block_ids_in_next_frame = temp;
19168 frame_set = &tng_data->current_trajectory_frame_set;
19170 current_frame += 1;
19172 if(current_frame < frame_set->first_frame ||
19173 current_frame >= frame_set->first_frame + frame_set->n_frames)
19175 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19176 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19177 if(stat != TNG_SUCCESS)
19179 /* If the frame set search found the frame set after the starting
19180 * frame set there is a gap in the frame sets. So, even if the frame
19181 * was not found the next frame with data is still in the found
19183 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19184 frame_set_file_pos)
19188 current_frame = frame_set->first_frame;
19192 /* Check for data blocks only if they have not already been found. */
19193 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19195 file_pos = ftello(tng_data->input_file);
19196 if(file_pos < tng_data->input_file_len)
19198 tng_block_init(&block);
19199 stat = tng_block_header_read(tng_data, block);
19200 while(file_pos < tng_data->input_file_len &&
19201 stat != TNG_CRITICAL &&
19202 block->id != TNG_TRAJECTORY_FRAME_SET &&
19205 stat = tng_block_read_next(tng_data, block,
19207 if(stat != TNG_CRITICAL)
19209 file_pos = ftello(tng_data->input_file);
19210 if(file_pos < tng_data->input_file_len)
19212 stat = tng_block_header_read(tng_data, block);
19216 tng_block_destroy(&block);
19217 if(stat == TNG_CRITICAL)
19219 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
19220 file_pos, __FILE__, __LINE__);
19229 *n_data_blocks_in_next_frame = 0;
19231 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19233 p_data = &frame_set->tr_particle_data[i];
19234 block_id = p_data->block_id;
19236 if(n_requested_data_block_ids > 0)
19239 for(j = 0; j < n_requested_data_block_ids; j++)
19241 if(block_id == requested_data_block_ids[j])
19253 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19254 p_data->last_retrieved_frame >=
19255 frame_set->first_frame + frame_set->n_frames))
19257 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19258 TNG_USE_HASH, block_id);
19259 if(stat == TNG_CRITICAL)
19261 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19262 __FILE__, __LINE__);
19265 if(stat == TNG_FAILURE)
19270 if(frame_set->first_frame != current_frame &&
19271 p_data->last_retrieved_frame >= 0)
19273 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19277 data_frame = p_data->first_frame_with_data;
19279 frame_diff = data_frame - current_frame;
19284 if(min_diff == -1 || frame_diff <= min_diff)
19286 if(frame_diff < min_diff)
19288 *n_data_blocks_in_next_frame = 1;
19292 *n_data_blocks_in_next_frame += 1;
19294 if(n_requested_data_block_ids <= 0)
19296 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19297 temp = realloc(*data_block_ids_in_next_frame, size);
19300 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19301 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19302 __FILE__, __LINE__);
19303 free(*data_block_ids_in_next_frame);
19304 *data_block_ids_in_next_frame = 0;
19305 return(TNG_CRITICAL);
19307 *data_block_ids_in_next_frame = temp;
19311 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19313 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19315 min_diff = frame_diff;
19318 for(i = 0; i < frame_set->n_data_blocks; i++)
19320 np_data = &frame_set->tr_data[i];
19321 block_id = np_data->block_id;
19323 if(n_requested_data_block_ids > 0)
19326 for(j = 0; j < n_requested_data_block_ids; j++)
19328 if(block_id == requested_data_block_ids[j])
19340 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19341 np_data->last_retrieved_frame >=
19342 frame_set->first_frame + frame_set->n_frames))
19344 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19345 TNG_USE_HASH, block_id);
19346 if(stat == TNG_CRITICAL)
19348 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19349 __FILE__, __LINE__);
19352 if(stat == TNG_FAILURE)
19357 if(frame_set->first_frame != current_frame &&
19358 np_data->last_retrieved_frame >= 0)
19360 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19364 data_frame = np_data->first_frame_with_data;
19366 frame_diff = data_frame - current_frame;
19371 if(min_diff == -1 || frame_diff <= min_diff)
19373 if(frame_diff < min_diff)
19375 *n_data_blocks_in_next_frame = 1;
19379 *n_data_blocks_in_next_frame += 1;
19381 if(n_requested_data_block_ids <= 0)
19383 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19384 temp = realloc(*data_block_ids_in_next_frame, size);
19387 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19388 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19389 __FILE__, __LINE__);
19390 free(*data_block_ids_in_next_frame);
19391 *data_block_ids_in_next_frame = 0;
19392 return(TNG_CRITICAL);
19394 *data_block_ids_in_next_frame = temp;
19398 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19400 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19402 min_diff = frame_diff;
19407 return(TNG_FAILURE);
19409 *next_frame = current_frame + min_diff;
19411 return(TNG_SUCCESS);
19415 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19416 (tng_trajectory_t tng_data,
19417 int64_t *n_data_blocks,
19418 int64_t **data_block_ids,
19419 char ***data_block_names,
19420 int64_t **stride_lengths,
19421 int64_t **n_values_per_frame,
19422 char **block_types,
19423 char **dependencies,
19424 char **compressions)
19426 tng_gen_block_t block;
19427 int64_t orig_file_pos, file_pos;
19429 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19430 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19431 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19432 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19433 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19435 orig_file_pos = ftello(tng_data->input_file);
19437 if(!tng_data->input_file_len)
19439 fseeko(tng_data->input_file, 0, SEEK_END);
19440 tng_data->input_file_len = ftello(tng_data->input_file);
19443 fseeko(tng_data->input_file, 0, SEEK_SET);
19446 *n_data_blocks = 0;
19448 tng_block_init(&block);
19450 while(file_pos < tng_data->input_file_len &&
19451 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19453 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19457 file_pos += (block->block_contents_size + block->header_contents_size);
19458 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
19461 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
19463 return(TNG_SUCCESS);
19466 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19467 (tng_trajectory_t tng_data,
19468 const int64_t prev_frame)
19470 tng_function_status stat;
19471 FILE *temp = tng_data->input_file;
19473 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19474 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19476 tng_data->input_file = tng_data->output_file;
19478 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19479 if(stat != TNG_SUCCESS)
19484 tng_data->current_trajectory_frame_set_output_file_pos =
19485 tng_data->current_trajectory_frame_set_input_file_pos;
19487 tng_data->input_file = temp;
19489 return(TNG_SUCCESS);