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"
37 #if defined( _WIN32 ) || defined( _WIN64 )
39 #define fseeko _fseeki64
43 #define ftello ftello64
45 #define ftello _ftelli64
51 /** One of the atoms of the bond */
53 /** The other atom of the bond */
58 /** The residue containing this atom */
59 tng_residue_t residue;
60 /** A unique (per molecule) ID number of the atom */
62 /** The atom_type (depending on the forcefield) */
64 /** The name of the atom */
69 /** The chain containing this residue */
71 /** A unique (per chain) ID number of the residue */
73 /** The name of the residue */
75 /** The number of atoms in the residue */
77 /** A list of atoms in the residue */
82 /** The molecule containing this chain */
83 tng_molecule_t molecule;
84 /** A unique (per molecule) ID number of the chain */
86 /** The name of the chain */
88 /** The number of residues in the chain */
90 /** A list of residues in the chain */
91 tng_residue_t residues;
95 /** A unique ID number of the molecule */
97 /** Quaternary structure of the molecule.
102 int64_t quaternary_str;
103 /** The number of chains in the molecule */
105 /** The number of residues in the molecule */
107 /** The number of atoms in the molecule */
109 /** The number of bonds in the molecule. If the bonds are not specified this
112 /** The name of the molecule */
114 /** A list of chains in the molecule */
116 /** A list of residues in the molecule */
117 tng_residue_t residues;
118 /** A list of the atoms in the molecule */
120 /** A list of the bonds in the molecule */
124 struct tng_gen_block {
125 /** The size of the block header in bytes */
126 int64_t header_contents_size;
127 /** The size of the block contents in bytes */
128 int64_t block_contents_size;
129 /** The ID of the block to determine its type */
131 /** The MD5 hash of the block to verify integrity */
132 char md5_hash[TNG_MD5_HASH_LEN];
133 /** The name of the block */
135 /** The library version used to write the block */
136 int64_t block_version;
137 int64_t alt_hash_type;
138 int64_t alt_hash_len;
140 int64_t signature_type;
141 int64_t signature_len;
143 /** The full block header contents */
144 char *header_contents;
145 /** The full block contents */
146 char *block_contents;
149 struct tng_particle_mapping {
150 /** The index number of the first particle in this mapping block */
151 int64_t num_first_particle;
152 /** The number of particles list in this mapping block */
154 /** the mapping of index numbers to the real particle numbers in the
155 * trajectory. real_particle_numbers[0] is the real particle number
156 * (as it is numbered in the molecular system) of the first particle
157 * in the data blocks covered by this particle mapping block */
158 int64_t *real_particle_numbers;
161 struct tng_trajectory_frame_set {
162 /** The number of different particle mapping blocks present. */
163 int64_t n_mapping_blocks;
164 /** The atom mappings of this frame set */
165 struct tng_particle_mapping *mappings;
166 /** The first frame of this frame set */
168 /** The number of frames in this frame set */
170 /** The number of written frames in this frame set (used when writing one
171 * frame at a time). */
172 int64_t n_written_frames;
173 /** The number of frames not yet written to file in this frame set
174 * (used from the utility functions to finish the writing properly. */
175 int64_t n_unwritten_frames;
178 /** A list of the number of each molecule type - only used when using
179 * variable number of atoms */
180 int64_t *molecule_cnt_list;
181 /** The number of particles/atoms - only used when using variable number
184 /** The file position of the next frame set */
185 int64_t next_frame_set_file_pos;
186 /** The file position of the previous frame set */
187 int64_t prev_frame_set_file_pos;
188 /** The file position of the frame set one long stride step ahead */
189 int64_t medium_stride_next_frame_set_file_pos;
190 /** The file position of the frame set one long stride step behind */
191 int64_t medium_stride_prev_frame_set_file_pos;
192 /** The file position of the frame set one long stride step ahead */
193 int64_t long_stride_next_frame_set_file_pos;
194 /** The file position of the frame set one long stride step behind */
195 int64_t long_stride_prev_frame_set_file_pos;
196 /** Time stamp (in seconds) of first frame in frame set */
197 double first_frame_time;
199 /* The data blocks in a frame set are trajectory data blocks */
200 /** The number of trajectory data blocks of particle dependent data */
201 int n_particle_data_blocks;
202 /** A list of data blocks containing particle dependent data */
203 struct tng_particle_data *tr_particle_data;
204 /** The number of trajectory data blocks independent of particles */
206 /** A list of data blocks containing particle indepdendent data */
207 struct tng_non_particle_data *tr_data;
210 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
211 /* FIXME: Make only one data block struct */
212 struct tng_particle_data {
213 /** The block ID of the data block containing this particle data.
214 * This is used to determine the kind of data that is stored */
216 /** The name of the data block. This is used to determine the kind of
217 * data that is stored */
219 /** The type of data stored. */
221 /** The frame number of the first data value */
222 int64_t first_frame_with_data;
223 /** The number of frames in this frame set */
225 /** The number of values stored per frame */
226 int64_t n_values_per_frame;
227 /** The number of frames between each data point - e.g. when
228 * storing sparse data. */
229 int64_t stride_length;
230 /** ID of the CODEC used for compression 0 == no compression. */
232 /** If reading one frame at a time this is the last read frame */
233 int64_t last_retrieved_frame;
234 /** The multiplier used for getting integer values for compression */
235 double compression_multiplier;
236 /** A 1-dimensional array of values of length
237 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
239 /** If storing character data store it in a 3-dimensional array */
243 struct tng_non_particle_data {
244 /** The ID of the data block */
246 /** The name of the data block. This is used to determine the kind of
247 * data that is stored */
249 /** The type of data stored. */
251 /** The first frame number of the first data value */
252 int64_t first_frame_with_data;
253 /** The number of frames in this data block */
255 /** The number of values stored per frame */
256 int64_t n_values_per_frame;
257 /** The number of frames between each data value, e.g. if storing data
258 * that is not saved every frame. */
259 int64_t stride_length;
260 /** ID of the CODEC used for compression. 0 == no compression. */
262 /** If reading one frame at a time this is the last read frame */
263 int64_t last_retrieved_frame;
264 /** Compressed data is stored as integers. This compression multiplier is
265 * the multiplication factor to convert from integer to float/double */
266 double compression_multiplier;
267 /** A 1-dimensional array of values of length
268 * [sizeof (datatype)] * n_frames * n_values_per_frame */
270 /** If storing character data store it in a 2-dimensional array */
276 struct tng_trajectory {
277 /** The path of the input trajectory file */
278 char *input_file_path;
279 /** A handle to the input file */
281 /** The length of the input file */
282 int64_t input_file_len;
283 /** The path of the output trajectory file */
284 char *output_file_path;
285 /** A handle to the output file */
287 /** Function to swap 32 bit values to and from the endianness of the
289 tng_function_status (*input_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
290 /** Function to swap 64 bit values to and from the endianness of the
292 tng_function_status (*input_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
293 /** Function to swap 32 bit values to and from the endianness of the
295 tng_function_status (*output_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
296 /** Function to swap 64 bit values to and from the endianness of the
298 tng_function_status (*output_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
299 /** The endianness of 32 bit values of the current computer */
301 /** The endianness of 64 bit values of the current computer */
304 /** The name of the program producing this trajectory */
305 char *first_program_name;
306 /** The forcefield used in the simulations */
307 char *forcefield_name;
308 /** The name of the user running the simulations */
309 char *first_user_name;
310 /** The name of the computer on which the simulations were performed */
311 char *first_computer_name;
312 /** The PGP signature of the user creating the file. */
313 char *first_pgp_signature;
314 /** The name of the program used when making last modifications to the
316 char *last_program_name;
317 /** The name of the user making the last modifications to the file */
318 char *last_user_name;
319 /** The name of the computer on which the last modifications were made */
320 char *last_computer_name;
321 /** The PGP signature of the user making the last modifications to the
323 char *last_pgp_signature;
324 /** The time (n seconds since 1970) when the file was created */
326 /** The exponential of the value of the distance unit used. The default
327 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
328 * the measurements are in Ã… the distance_unit_exponential = -10. */
329 int64_t distance_unit_exponential;
331 /** A flag indicating if the number of atoms can vary throughout the
332 * simulation, e.g. using a grand canonical ensemble */
333 char var_num_atoms_flag;
334 /** The number of frames in a frame set. It is allowed to have frame sets
335 * with fewer frames, but this will help searching for specific frames */
336 int64_t frame_set_n_frames;
337 /** The number of frame sets in a medium stride step */
338 int64_t medium_stride_length;
339 /** The number of frame sets in a long stride step */
340 int64_t long_stride_length;
341 /** The current (can change from one frame set to another) time length
342 * (in seconds) of one frame */
343 double time_per_frame;
345 /** The number of different kinds of molecules in the trajectory */
347 /** A list of molecules in the trajectory */
348 tng_molecule_t molecules;
349 /** A list of the count of each molecule - if using variable number of
350 * particles this will be specified in each frame set */
351 int64_t *molecule_cnt_list;
352 /** The total number of particles/atoms. If using variable number of
353 * particles this will be specified in each frame set */
356 /** The pos in the src file of the first frame set */
357 int64_t first_trajectory_frame_set_input_file_pos;
358 /** The pos in the dest file of the first frame set */
359 int64_t first_trajectory_frame_set_output_file_pos;
360 /** The pos in the src file of the last frame set */
361 int64_t last_trajectory_frame_set_input_file_pos;
362 /** The pos in the dest file of the last frame set */
363 int64_t last_trajectory_frame_set_output_file_pos;
364 /** The currently active frame set */
365 struct tng_trajectory_frame_set current_trajectory_frame_set;
366 /** The pos in the src file of the current frame set */
367 int64_t current_trajectory_frame_set_input_file_pos;
368 /** The pos in the dest file of the current frame set */
369 int64_t current_trajectory_frame_set_output_file_pos;
370 /** The number of frame sets in the trajectory N.B. Not saved in file and
371 * cannot be trusted to be up-to-date */
372 int64_t n_trajectory_frame_sets;
374 /* These data blocks are non-trajectory data blocks */
375 /** The number of non-frame dependent particle dependent data blocks */
376 int n_particle_data_blocks;
377 /** A list of data blocks containing particle dependent data */
378 struct tng_particle_data *non_tr_particle_data;
380 /** The number of frame and particle independent data blocks */
382 /** A list of frame and particle indepdendent data blocks */
383 struct tng_non_particle_data *non_tr_data;
385 /** TNG compression algorithm for compressing positions */
386 int *compress_algo_pos;
387 /** TNG compression algorithm for compressing velocities */
388 int *compress_algo_vel;
389 /** The precision used for lossy compression */
390 double compression_precision;
394 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
396 #endif /* win32... */
397 #endif /* not defined USE_WINDOWS */
400 #define TNG_INLINE __inline
401 #define TNG_SNPRINTF _snprintf
403 #define TNG_INLINE inline
404 #define TNG_SNPRINTF snprintf
407 static TNG_INLINE int tng_min_i(int a, int b)
409 return (a < b ? a : b);
413 static TNG_INLINE int tng_max_i(int a, int b)
415 return (a > b ? a : b);
418 static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
420 return (a < b ? a : b);
423 static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
425 return (a > b ? a : b);
429 static TNG_INLINE float tng_min_f(float a, float b)
431 return (a < b ? a : b);
434 static TNG_INLINE float tng_max_f(float a, float b)
436 return (a > b ? a : b);
439 static TNG_INLINE double tng_min_d(double a, double b)
441 return (a < b ? a : b);
444 static TNG_INLINE double tng_max_d(double a, double b)
446 return (a > b ? a : b);
450 /** This function swaps the byte order of a 32 bit numerical variable
452 * It does not only work with integer, but e.g. floats need casting.
453 * If the byte order is already big endian no change is needed.
454 * @param tng_data is a trajectory data container.
455 * @param v is a pointer to a 32 bit numerical value (float or integer).
456 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
457 * byte order is not recognised.
459 static tng_function_status tng_swap_byte_order_big_endian_32
460 (const tng_trajectory_t tng_data, int32_t *v)
462 switch(tng_data->endianness_32)
464 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
465 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
466 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
467 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
468 ((*v & 0x000000FF) << 24); /* Move last byte to first */
472 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
473 *v = ((*v & 0xFFFF0000) >> 16) |
474 ((*v & 0x0000FFFF) << 16);
478 case TNG_BIG_ENDIAN_32: /* Already correct */
486 /** This function swaps the byte order of a 64 bit numerical variable
488 * It does not only work with integer, but e.g. floats need casting.
489 * The byte order swapping routine can convert four different byte
490 * orders to big endian.
491 * If the byte order is already big endian no change is needed.
492 * @param tng_data is a trajectory data container.
493 * @param v is a pointer to a 64 bit numerical value (double or integer).
494 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
495 * byte order is not recognised.
497 static tng_function_status tng_swap_byte_order_big_endian_64
498 (const tng_trajectory_t tng_data, int64_t *v)
500 switch(tng_data->endianness_64)
502 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
503 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
504 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
505 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
506 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
507 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
508 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
509 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
510 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
514 case TNG_QUAD_SWAP_64: /* Byte quad swap */
515 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
516 ((*v & 0x00000000FFFFFFFFLL) << 32);
520 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
521 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
522 ((*v & 0x0000FFFF0000FFFFLL) << 16);
526 case TNG_BYTE_SWAP_64: /* Byte swap */
527 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
528 ((*v & 0x00FF00FF00FF00FFLL) << 8);
532 case TNG_BIG_ENDIAN_64: /* Already correct */
540 /** This function swaps the byte order of a 32 bit numerical variable
542 * It does not only work with integer, but e.g. floats need casting.
543 * If the byte order is already little endian no change is needed.
544 * @param tng_data is a trajectory data container.
545 * @param v is a pointer to a 32 bit numerical value (float or integer).
546 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
547 * byte order is not recognised.
549 static tng_function_status tng_swap_byte_order_little_endian_32
550 (const tng_trajectory_t tng_data, int32_t *v)
552 switch(tng_data->endianness_32)
554 case TNG_LITTLE_ENDIAN_32: /* Already correct */
557 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
558 *v = ((*v & 0xFF00FF00) >> 8) |
559 ((*v & 0x00FF00FF) << 8);
563 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
564 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
565 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
566 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
567 ((*v & 0x000000FF) << 24); /* Move last byte to first */
576 /** This function swaps the byte order of a 64 bit numerical variable
578 * It does not only work with integer, but e.g. floats need casting.
579 * The byte order swapping routine can convert four different byte
580 * orders to little endian.
581 * If the byte order is already little endian no change is needed.
582 * @param tng_data is a trajectory data container.
583 * @param v is a pointer to a 64 bit numerical value (double or integer).
584 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
585 * byte order is not recognised.
587 static tng_function_status tng_swap_byte_order_little_endian_64
588 (const tng_trajectory_t tng_data, int64_t *v)
590 switch(tng_data->endianness_64)
592 case TNG_LITTLE_ENDIAN_64: /* Already correct */
595 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
596 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
597 ((*v & 0x00FF000000FF0000LL) >> 8) |
598 ((*v & 0x0000FF000000FF00LL) << 8) |
599 ((*v & 0x000000FF000000FFLL) << 24);
603 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
604 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
605 ((*v & 0x00FF00FF00000000LL) >> 24) |
606 ((*v & 0x00000000FF00FF00LL) << 24) |
607 ((*v & 0x0000000000FF00FFLL) << 40);
611 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
612 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
613 ((*v & 0x0000FFFF00000000LL) >> 16) |
614 ((*v & 0x00000000FFFF0000LL) << 16) |
615 ((*v & 0x000000000000FFFFLL) << 48);
619 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
620 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
621 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
622 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
623 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
624 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
625 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
626 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
627 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
635 /** Generate the md5 hash of a block.
636 * The hash is created based on the actual block contents.
637 * @param block is a general block container.
638 * @return TNG_SUCCESS (0) if successful.
640 static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
642 md5_state_t md5_state;
644 md5_init(&md5_state);
645 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
646 (int)block->block_contents_size);
647 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
652 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
653 * calculated from the current contents.
654 * If the current md5 hash is not set skip the comparison.
655 * @param block is a general block container.
656 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
657 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
658 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
661 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
664 md5_state_t md5_state;
665 char hash[TNG_MD5_HASH_LEN];
667 TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
670 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
674 md5_init(&md5_state);
675 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
676 (int)block->block_contents_size);
677 md5_finish(&md5_state, (md5_byte_t *)hash);
679 if(strncmp(block->md5_hash, hash, 16) != 0)
681 *results = TNG_FALSE;
687 /** Open the input file if it is not already opened.
688 * @param tng_data is a trajectory data container.
689 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
692 static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
694 if(!tng_data->input_file)
696 if(!tng_data->input_file_path)
698 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
700 return(TNG_CRITICAL);
702 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
703 if(!tng_data->input_file)
705 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
706 tng_data->input_file_path, __FILE__, __LINE__);
707 return(TNG_CRITICAL);
713 /** Open the output file if it is not already opened
714 * @param tng_data is a trajectory data container.
715 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
718 static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
720 if(!tng_data->output_file)
722 if(!tng_data->output_file_path)
724 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
726 return(TNG_CRITICAL);
729 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
731 if(!tng_data->output_file)
733 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
734 tng_data->output_file_path, __FILE__, __LINE__);
735 return(TNG_CRITICAL);
741 /** Setup a file block container.
742 * @param block_p a pointer to memory to initialise as a file block container.
743 * @details Memory is allocated during initialisation.
744 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
747 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
749 tng_gen_block_t block;
751 *block_p = malloc(sizeof(struct tng_gen_block));
754 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
755 sizeof(struct tng_gen_block), __FILE__, __LINE__);
756 return(TNG_CRITICAL);
762 /* Reset the md5_hash */
763 memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
765 block->block_version = TNG_API_VERSION;
766 block->header_contents = 0;
767 block->header_contents_size = 0;
768 block->block_contents = 0;
769 block->block_contents_size = 0;
775 * @brief Clean up a file block container.
776 * @param block_p a pointer to the file block container to destroy.
777 * @details All allocated memory in the data structure is freed, as well as
779 * @return TNG_SUCCESS (0) if successful.
781 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
783 tng_gen_block_t block = *block_p;
790 /* fprintf(stderr, "TNG library: Destroying block\n"); */
796 if(block->header_contents)
798 free(block->header_contents);
799 block->header_contents = 0;
801 if(block->block_contents)
803 free(block->block_contents);
804 block->block_contents = 0;
813 /** Read the header of a data block, regardless of its type
814 * @param tng_data is a trajectory data container.
815 * @param block is a general block container.
816 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
817 * error has occured (not able to read the header size, thus skipping
818 * the block) or TNG_CRITICAL (2) if a major error has occured.
820 static tng_function_status tng_block_header_read
821 (tng_trajectory_t tng_data, tng_gen_block_t block)
826 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
828 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
830 return(TNG_CRITICAL);
833 /* First read the header size to be able to read the whole header. */
834 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
835 1, tng_data->input_file) == 0)
837 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
839 return(TNG_CRITICAL);
842 if(block->header_contents_size == 0)
848 /* If this was the size of the general info block check the endianness */
849 if(ftello(tng_data->input_file) < 9)
851 /* File is little endian */
852 if ( *((const char*)&block->header_contents_size) != 0x00 &&
853 *((const char*)(&block->header_contents_size) + 7) == 0x00)
855 /* If the architecture endianness is little endian no byte swap
856 * will be needed. Otherwise use the functions to swap to little
858 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
860 tng_data->input_endianness_swap_func_32 = 0;
864 tng_data->input_endianness_swap_func_32 =
865 &tng_swap_byte_order_little_endian_32;
867 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
869 tng_data->input_endianness_swap_func_64 = 0;
873 tng_data->input_endianness_swap_func_64 =
874 &tng_swap_byte_order_little_endian_64;
877 /* File is big endian */
880 /* If the architecture endianness is big endian no byte swap
881 * will be needed. Otherwise use the functions to swap to big
883 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
885 tng_data->input_endianness_swap_func_32 = 0;
889 tng_data->input_endianness_swap_func_32 =
890 &tng_swap_byte_order_big_endian_32;
892 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
894 tng_data->input_endianness_swap_func_64 = 0;
898 tng_data->input_endianness_swap_func_64 =
899 &tng_swap_byte_order_big_endian_64;
904 if(tng_data->input_endianness_swap_func_64)
906 if(tng_data->input_endianness_swap_func_64(tng_data,
907 &block->header_contents_size)
910 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
915 /* Move the reading position to the beginning of the header. */
916 fseeko(tng_data->input_file, -(int64_t)sizeof(block->header_contents_size),
919 /* If there is already memory allocated for the contents free it (we do not
920 * know if the size is correct). */
921 if(block->header_contents)
923 free(block->header_contents);
926 block->header_contents = malloc(block->header_contents_size);
927 if(!block->header_contents)
929 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
930 block->header_contents_size, __FILE__, __LINE__);
931 return(TNG_CRITICAL);
934 /* Read the whole header into header_contents. This way it can be saved
935 * even if it cannot be interpreted
936 * for one reason or another. */
937 if(fread(block->header_contents, block->header_contents_size, 1,
938 tng_data->input_file) == 0)
940 fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
941 return(TNG_CRITICAL);
944 /* The header contents size has already been read. Skip ahead. */
945 offset = sizeof(block->header_contents_size);
948 /* Copy the respective parameters from the header contents block */
949 memcpy(&block->block_contents_size, block->header_contents+offset,
950 sizeof(block->block_contents_size));
951 if(tng_data->input_endianness_swap_func_64)
953 if(tng_data->input_endianness_swap_func_64(tng_data,
954 &block->block_contents_size)
957 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
962 offset += sizeof(block->block_contents_size);
964 memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
965 if(tng_data->input_endianness_swap_func_64)
967 if(tng_data->input_endianness_swap_func_64(tng_data,
971 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
976 offset += sizeof(block->id);
978 memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
979 offset += TNG_MD5_HASH_LEN;
981 if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
986 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
989 block->name = malloc(len);
992 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
994 return(TNG_CRITICAL);
996 strncpy(block->name, block->header_contents+offset, len);
1000 memcpy(&block->block_version, block->header_contents+offset,
1001 sizeof(block->block_version));
1002 if(tng_data->input_endianness_swap_func_64)
1004 if(tng_data->input_endianness_swap_func_64(tng_data,
1005 &block->block_version)
1008 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1009 __FILE__, __LINE__);
1013 return(TNG_SUCCESS);
1016 /** Write a whole block, both header and contents, regardless of it type
1017 * @param tng_data is a trajectory data container.
1018 * @param block is a general block container.
1019 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1020 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1022 /* Disabled until it is used.*/
1024 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1025 // tng_gen_block_t block)
1027 // if(!block->header_contents)
1029 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1030 // return(TNG_FAILURE);
1032 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1033 // tng_data->output_file) != 1)
1035 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1036 // __FILE__, __LINE__);
1037 // return(TNG_CRITICAL);
1040 // if(!block->block_contents)
1042 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1043 // __FILE__, __LINE__);
1044 // return(TNG_FAILURE);
1046 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1047 // tng_data->output_file) != 1)
1049 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1050 // __FILE__, __LINE__);
1051 // return(TNG_CRITICAL);
1053 // return(TNG_SUCCESS);
1057 /** Update the md5 hash of a block already written to the file
1058 * @param tng_data is a trajectory data container.
1059 * @param block is the block, of which to update the md5 hash.
1060 * @param header_start_pos is the file position where the block header starts.
1061 * @param contents_start_pos is the file position where the block contents
1063 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1064 * error has occured.
1066 static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
1067 tng_gen_block_t block,
1068 const int64_t header_start_pos,
1069 const int64_t contents_start_pos)
1071 if(block->block_contents)
1073 free(block->block_contents);
1076 block->block_contents = malloc(block->block_contents_size);
1077 if(!block->block_contents)
1079 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1080 block->block_contents_size, __FILE__, __LINE__);
1081 return(TNG_CRITICAL);
1084 fseeko(tng_data->output_file, contents_start_pos, SEEK_SET);
1085 if(fread(block->block_contents, block->block_contents_size, 1,
1086 tng_data->output_file) == 0)
1088 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1089 return(TNG_CRITICAL);
1092 tng_block_md5_hash_generate(block);
1094 fseeko(tng_data->output_file, header_start_pos + 3 * sizeof(int64_t),
1096 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
1098 return(TNG_SUCCESS);
1101 /** Update the frame set pointers in the file header (general info block),
1102 * already written to disk
1103 * @param tng_data is a trajectory data container.
1104 * @param hash_mode specifies whether to update the block md5 hash when
1105 * updating the pointers.
1106 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1107 * error has occured.
1109 static tng_function_status tng_header_pointers_update
1110 (tng_trajectory_t tng_data, const char hash_mode)
1112 tng_gen_block_t block;
1113 FILE *temp = tng_data->input_file;
1114 int64_t output_file_pos, pos, contents_start_pos;
1116 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1118 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1119 __FILE__, __LINE__);
1120 return(TNG_CRITICAL);
1123 tng_data->input_file = tng_data->output_file;
1125 tng_block_init(&block);
1127 output_file_pos = ftello(tng_data->output_file);
1128 fseeko(tng_data->output_file, 0, SEEK_SET);
1130 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1132 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
1133 __FILE__, __LINE__);
1134 tng_data->input_file = temp;
1135 tng_block_destroy(&block);
1136 return(TNG_CRITICAL);
1139 contents_start_pos = ftello(tng_data->output_file);
1141 fseeko(tng_data->output_file, block->block_contents_size - 5 *
1142 sizeof(int64_t), SEEK_CUR);
1144 tng_data->input_file = temp;
1146 pos = tng_data->first_trajectory_frame_set_output_file_pos;
1148 if(tng_data->input_endianness_swap_func_64)
1150 if(tng_data->input_endianness_swap_func_64(tng_data,
1154 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1155 __FILE__, __LINE__);
1159 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1161 tng_block_destroy(&block);
1162 return(TNG_CRITICAL);
1165 pos = tng_data->last_trajectory_frame_set_output_file_pos;
1167 if(tng_data->input_endianness_swap_func_64)
1169 if(tng_data->input_endianness_swap_func_64(tng_data,
1173 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1174 __FILE__, __LINE__);
1179 sizeof(int64_t), 1, tng_data->output_file) != 1)
1181 tng_block_destroy(&block);
1182 return(TNG_CRITICAL);
1185 if(hash_mode == TNG_USE_HASH)
1187 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
1190 tng_block_destroy(&block);
1192 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1194 return(TNG_SUCCESS);
1197 /** Update the frame set pointers in the current frame set block, already
1198 * written to disk. It also updates the pointers of the blocks pointing to
1199 * the current frame set block.
1200 * @param tng_data is a trajectory data container.
1201 * @param hash_mode specifies whether to update the block md5 hash when
1202 * updating the pointers.
1203 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1204 * error has occured.
1206 static tng_function_status tng_frame_set_pointers_update
1207 (tng_trajectory_t tng_data, const char hash_mode)
1209 tng_gen_block_t block;
1210 tng_trajectory_frame_set_t frame_set;
1211 FILE *temp = tng_data->input_file;
1212 int64_t pos, output_file_pos, contents_start_pos;
1214 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1216 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1217 __FILE__, __LINE__);
1218 return(TNG_CRITICAL);
1221 tng_block_init(&block);
1222 output_file_pos = ftello(tng_data->output_file);
1224 tng_data->input_file = tng_data->output_file;
1226 frame_set = &tng_data->current_trajectory_frame_set;
1228 pos = tng_data->current_trajectory_frame_set_output_file_pos;
1230 /* Update next frame set */
1231 if(frame_set->next_frame_set_file_pos > 0)
1233 fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos,
1236 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1238 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1239 __FILE__, __LINE__);
1240 tng_data->input_file = temp;
1241 tng_block_destroy(&block);
1242 return(TNG_CRITICAL);
1245 contents_start_pos = ftello(tng_data->output_file);
1247 fseeko(tng_data->output_file, block->block_contents_size - (5 *
1248 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1250 if(tng_data->input_endianness_swap_func_64)
1252 if(tng_data->input_endianness_swap_func_64(tng_data,
1256 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1257 __FILE__, __LINE__);
1261 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1263 tng_data->input_file = temp;
1264 tng_block_destroy(&block);
1265 return(TNG_CRITICAL);
1268 if(hash_mode == TNG_USE_HASH)
1270 tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
1271 contents_start_pos);
1273 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1275 /* Update previous frame set */
1276 if(frame_set->prev_frame_set_file_pos > 0)
1278 fseeko(tng_data->output_file, frame_set->prev_frame_set_file_pos,
1281 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1283 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1284 __FILE__, __LINE__);
1285 tng_data->input_file = temp;
1286 tng_block_destroy(&block);
1287 return(TNG_CRITICAL);
1290 contents_start_pos = ftello(tng_data->output_file);
1292 fseeko(tng_data->output_file, block->block_contents_size - (6 *
1293 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1295 if(tng_data->input_endianness_swap_func_64)
1297 if(tng_data->input_endianness_swap_func_64(tng_data,
1301 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1302 __FILE__, __LINE__);
1306 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1308 tng_data->input_file = temp;
1309 tng_block_destroy(&block);
1310 return(TNG_CRITICAL);
1313 if(hash_mode == TNG_USE_HASH)
1315 tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
1316 contents_start_pos);
1318 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1321 /* Update the frame set one medium stride step after */
1322 if(frame_set->medium_stride_next_frame_set_file_pos > 0)
1324 fseeko(tng_data->output_file,
1325 frame_set->medium_stride_next_frame_set_file_pos,
1328 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1330 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1331 __FILE__, __LINE__);
1332 tng_data->input_file = temp;
1333 tng_block_destroy(&block);
1334 return(TNG_CRITICAL);
1337 contents_start_pos = ftello(tng_data->output_file);
1339 fseeko(tng_data->output_file, block->block_contents_size - (3 *
1340 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1342 if(tng_data->input_endianness_swap_func_64)
1344 if(tng_data->input_endianness_swap_func_64(tng_data,
1348 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1349 __FILE__, __LINE__);
1353 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1355 tng_data->input_file = temp;
1356 tng_block_destroy(&block);
1357 return(TNG_CRITICAL);
1360 if(hash_mode == TNG_USE_HASH)
1362 tng_md5_hash_update(tng_data, block,
1363 frame_set->medium_stride_next_frame_set_file_pos,
1364 contents_start_pos);
1367 /* Update the frame set one medium stride step before */
1368 if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
1370 fseeko(tng_data->output_file,
1371 frame_set->medium_stride_prev_frame_set_file_pos,
1374 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1376 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1377 __FILE__, __LINE__);
1378 tng_data->input_file = temp;
1379 tng_block_destroy(&block);
1380 return(TNG_CRITICAL);
1383 contents_start_pos = ftello(tng_data->output_file);
1385 fseeko(tng_data->output_file, block->block_contents_size - (4 *
1386 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1388 if(tng_data->input_endianness_swap_func_64)
1390 if(tng_data->input_endianness_swap_func_64(tng_data,
1394 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1395 __FILE__, __LINE__);
1399 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1401 tng_data->input_file = temp;
1402 tng_block_destroy(&block);
1403 return(TNG_CRITICAL);
1406 if(hash_mode == TNG_USE_HASH)
1408 tng_md5_hash_update(tng_data, block,
1409 frame_set->medium_stride_prev_frame_set_file_pos,
1410 contents_start_pos);
1414 /* Update the frame set one long stride step after */
1415 if(frame_set->long_stride_next_frame_set_file_pos > 0)
1417 fseeko(tng_data->output_file,
1418 frame_set->long_stride_next_frame_set_file_pos,
1421 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1423 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1424 __FILE__, __LINE__);
1425 tng_data->input_file = temp;
1426 tng_block_destroy(&block);
1427 return(TNG_CRITICAL);
1430 contents_start_pos = ftello(tng_data->output_file);
1432 fseeko(tng_data->output_file, block->block_contents_size - (1 *
1433 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1435 if(tng_data->input_endianness_swap_func_64)
1437 if(tng_data->input_endianness_swap_func_64(tng_data,
1441 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1442 __FILE__, __LINE__);
1446 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1448 tng_data->input_file = temp;
1449 tng_block_destroy(&block);
1450 return(TNG_CRITICAL);
1453 if(hash_mode == TNG_USE_HASH)
1455 tng_md5_hash_update(tng_data, block,
1456 frame_set->long_stride_next_frame_set_file_pos,
1457 contents_start_pos);
1460 /* Update the frame set one long stride step before */
1461 if(frame_set->long_stride_prev_frame_set_file_pos > 0)
1463 fseeko(tng_data->output_file,
1464 frame_set->long_stride_prev_frame_set_file_pos,
1467 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1469 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1470 __FILE__, __LINE__);
1471 tng_data->input_file = temp;
1472 tng_block_destroy(&block);
1473 return(TNG_CRITICAL);
1476 contents_start_pos = ftello(tng_data->output_file);
1478 fseeko(tng_data->output_file, block->block_contents_size - (2 *
1479 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1481 if(tng_data->input_endianness_swap_func_64)
1483 if(tng_data->input_endianness_swap_func_64(tng_data,
1487 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1488 __FILE__, __LINE__);
1492 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1494 tng_data->input_file = temp;
1495 tng_block_destroy(&block);
1496 return(TNG_CRITICAL);
1499 if(hash_mode == TNG_USE_HASH)
1501 tng_md5_hash_update(tng_data, block,
1502 frame_set->long_stride_prev_frame_set_file_pos,
1503 contents_start_pos);
1507 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1509 tng_data->input_file = temp;
1511 tng_block_destroy(&block);
1513 return(TNG_SUCCESS);
1516 static tng_function_status tng_reread_frame_set_at_file_pos
1517 (tng_trajectory_t tng_data,
1520 tng_gen_block_t block;
1521 tng_function_status stat;
1523 tng_block_init(&block);
1525 fseeko(tng_data->input_file, pos, SEEK_SET);
1528 stat = tng_block_header_read(tng_data, block);
1529 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1531 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
1532 __FILE__, __LINE__);
1533 tng_block_destroy(&block);
1534 return(TNG_FAILURE);
1537 if(tng_block_read_next(tng_data, block,
1538 TNG_SKIP_HASH) != TNG_SUCCESS)
1540 tng_block_destroy(&block);
1541 return(TNG_CRITICAL);
1545 tng_block_destroy(&block);
1547 return(TNG_SUCCESS);
1550 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1551 (tng_trajectory_t tng_data,
1554 int64_t orig_pos, curr_frame_set_pos;
1555 tng_gen_block_t block;
1556 tng_function_status stat;
1557 tng_trajectory_frame_set_t frame_set =
1558 &tng_data->current_trajectory_frame_set;
1560 orig_pos = ftello(tng_data->input_file);
1561 curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
1563 *pos = tng_data->first_trajectory_frame_set_input_file_pos;
1567 return(TNG_SUCCESS);
1570 fseeko(tng_data->input_file, *pos, SEEK_SET);
1572 tng_block_init(&block);
1573 /* Read block headers first to see that a frame set block is found. */
1574 stat = tng_block_header_read(tng_data, block);
1575 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1577 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1578 __FILE__, __LINE__);
1579 tng_block_destroy(&block);
1580 return(TNG_FAILURE);
1583 if(tng_block_read_next(tng_data, block,
1584 TNG_SKIP_HASH) != TNG_SUCCESS)
1586 tng_block_destroy(&block);
1587 return(TNG_CRITICAL);
1590 /* Read all frame set blocks (not the blocks between them) */
1591 while(frame_set->next_frame_set_file_pos > 0)
1593 fseeko(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1594 stat = tng_block_header_read(tng_data, block);
1595 if(stat == TNG_CRITICAL)
1597 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1598 __FILE__, __LINE__);
1599 tng_block_destroy(&block);
1600 return(TNG_CRITICAL);
1602 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1604 return(TNG_FAILURE);
1607 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
1608 if(stat != TNG_SUCCESS)
1610 tng_block_destroy(&block);
1613 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1614 if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
1615 tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
1617 *pos = tng_data->current_trajectory_frame_set_input_file_pos;
1621 /* Re-read the frame set that used to be the current one */
1622 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1624 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1626 tng_block_destroy(&block);
1628 return(TNG_SUCCESS);
1631 static tng_function_status tng_frame_set_complete_migrate
1632 (tng_trajectory_t tng_data,
1633 int64_t block_start_pos,
1638 tng_bool updated = TNG_FALSE;
1642 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1644 return(TNG_CRITICAL);
1647 fseeko(tng_data->input_file, block_start_pos, SEEK_SET);
1649 contents = malloc(block_len);
1652 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1653 block_len, __FILE__, __LINE__);
1654 return(TNG_CRITICAL);
1657 if(fread(contents, block_len, 1, tng_data->input_file) == 0)
1659 fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1660 __FILE__, __LINE__);
1662 return(TNG_CRITICAL);
1664 fseeko(tng_data->output_file, new_pos, SEEK_SET);
1666 if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
1668 fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1669 __FILE__, __LINE__);
1671 return(TNG_CRITICAL);
1674 tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
1676 tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
1678 /* Update the general info block if needed */
1679 if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
1681 tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
1684 if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
1686 tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
1691 tng_header_pointers_update(tng_data, TNG_USE_HASH);
1694 /* Fill the block with NULL to avoid confusion. */
1695 for(i = 0; i < block_len; i++)
1699 fseeko(tng_data->output_file, block_start_pos, SEEK_SET);
1701 /* FIXME: casting block_len to size_t is dangerous */
1702 fwrite(contents, 1, block_len, tng_data->output_file);
1706 return(TNG_SUCCESS);
1709 static tng_function_status tng_length_of_current_frame_set_contents_get
1710 (tng_trajectory_t tng_data,
1713 int64_t orig_pos, pos, curr_frame_set_pos;
1714 tng_gen_block_t block;
1715 tng_function_status stat;
1717 orig_pos = ftello(tng_data->input_file);
1718 curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
1722 fseeko(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
1724 tng_block_init(&block);
1725 /* Read block headers first to see that a frame set block is found. */
1726 stat = tng_block_header_read(tng_data, block);
1727 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1729 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
1730 curr_frame_set_pos, __FILE__, __LINE__);
1731 tng_block_destroy(&block);
1732 return(TNG_FAILURE);
1735 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1736 while(stat == TNG_SUCCESS)
1738 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
1739 *len += block->header_contents_size + block->block_contents_size;
1740 pos += block->header_contents_size + block->block_contents_size;
1741 if(pos >= tng_data->input_file_len)
1745 stat = tng_block_header_read(tng_data, block);
1746 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1752 /* Re-read the frame set that used to be the current one */
1753 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1755 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1757 tng_block_destroy(&block);
1759 return(TNG_SUCCESS);
1762 /** Migrate blocks in the file to make room for new data in a block. This
1763 * is required e.g. when adding data to a block or extending strings in a
1765 * @param tng_data is a trajectory data container.
1766 * @param start_pos is the position from which to start moving data, usually
1767 * the byte after the end of the block to which data was added.
1768 * @param offset is the number of bytes that were inserted.
1769 * @details Trajectory blocks (frame sets and their related blocks) are moved
1770 * to the end of the file (if needed) in order to make room for non-trajectory
1773 static tng_function_status tng_migrate_data_in_file
1774 (tng_trajectory_t tng_data,
1778 int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
1779 tng_gen_block_t block;
1780 tng_function_status stat;
1785 return(TNG_SUCCESS);
1788 temp = tng_data->input_file;
1790 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1791 if(stat != TNG_SUCCESS)
1793 tng_data->input_file = temp;
1797 tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
1799 empty_space = traj_start_pos - (start_pos - 1);
1801 if(empty_space >= offset)
1803 return(TNG_SUCCESS);
1806 orig_file_pos = ftello(tng_data->input_file);
1807 tng_block_init(&block);
1809 while(empty_space < offset)
1811 fseeko(tng_data->input_file, traj_start_pos, SEEK_SET);
1812 stat = tng_block_header_read(tng_data, block);
1813 if(stat == TNG_CRITICAL)
1815 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
1816 __FILE__, __LINE__);
1817 tng_block_destroy(&block);
1818 tng_data->input_file = temp;
1819 return(TNG_CRITICAL);
1821 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1823 tng_data->input_file = temp;
1824 tng_block_destroy(&block);
1825 return(TNG_FAILURE);
1827 stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
1828 if(stat != TNG_SUCCESS)
1830 tng_data->input_file = temp;
1831 tng_block_destroy(&block);
1834 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1835 frame_set_length, tng_data->input_file_len);
1836 if(stat != TNG_SUCCESS)
1838 tng_data->input_file = temp;
1839 tng_block_destroy(&block);
1843 empty_space += frame_set_length;
1845 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
1846 tng_block_destroy(&block);
1848 return(TNG_SUCCESS);
1851 static tng_function_status tng_block_header_len_calculate
1852 (const tng_trajectory_t tng_data,
1853 tng_gen_block_t block,
1859 /* If the string is unallocated allocate memory for just string
1863 block->name = malloc(1);
1866 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1867 __FILE__, __LINE__);
1868 return(TNG_CRITICAL);
1873 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1875 /* Calculate the size of the header to write */
1876 *len = sizeof(block->header_contents_size) +
1877 sizeof(block->block_contents_size) +
1879 sizeof(block->block_version) +
1883 return (TNG_SUCCESS);
1886 /** Write the header of a data block, regardless of its type
1887 * @param tng_data is a trajectory data container.
1888 * @param block is a general block container.
1889 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1890 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1891 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1892 * error has occured.
1894 static tng_function_status tng_block_header_write
1895 (tng_trajectory_t tng_data,
1896 tng_gen_block_t block,
1897 const char hash_mode)
1899 int name_len, offset = 0;
1901 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1903 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1905 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1906 __FILE__, __LINE__);
1907 return(TNG_CRITICAL);
1910 if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
1913 fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
1914 __FILE__, __LINE__);
1915 return(TNG_CRITICAL);
1918 if(hash_mode == TNG_USE_HASH)
1920 tng_block_md5_hash_generate(block);
1923 if(block->header_contents)
1925 free(block->header_contents);
1928 block->header_contents = malloc(block->header_contents_size);
1929 if(!block->header_contents)
1931 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1932 block->header_contents_size, __FILE__, __LINE__);
1933 return(TNG_CRITICAL);
1936 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1938 /* First copy all data into the header_contents block and finally write
1939 * the whole block at once. */
1940 memcpy(block->header_contents, &block->header_contents_size,
1941 sizeof(block->header_contents_size));
1942 if(tng_data->output_endianness_swap_func_64)
1944 if(tng_data->output_endianness_swap_func_64(tng_data,
1945 (int64_t *)block->header_contents+offset)
1948 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1949 __FILE__, __LINE__);
1952 offset += sizeof(block->header_contents_size);
1954 memcpy(block->header_contents+offset, &block->block_contents_size,
1955 sizeof(block->block_contents_size));
1956 if(tng_data->output_endianness_swap_func_64)
1958 if(tng_data->output_endianness_swap_func_64(tng_data,
1959 (int64_t *)block->header_contents+offset)
1962 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1963 __FILE__, __LINE__);
1966 offset += sizeof(block->block_contents_size);
1968 memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
1969 if(tng_data->output_endianness_swap_func_64)
1971 if(tng_data->output_endianness_swap_func_64(tng_data,
1972 (int64_t *)block->header_contents+offset)
1975 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1976 __FILE__, __LINE__);
1979 offset += sizeof(block->id);
1981 memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
1982 offset += TNG_MD5_HASH_LEN;
1984 strncpy(block->header_contents+offset, block->name, name_len);
1987 memcpy(block->header_contents+offset, &block->block_version,
1988 sizeof(block->block_version));
1989 if(tng_data->output_endianness_swap_func_64)
1991 if(tng_data->output_endianness_swap_func_64(tng_data,
1992 (int64_t *)block->header_contents+offset)
1995 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1996 __FILE__, __LINE__);
2000 if(fwrite(block->header_contents, block->header_contents_size,
2001 1, tng_data->output_file) != 1)
2003 fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
2004 return(TNG_CRITICAL);
2006 return(TNG_SUCCESS);
2009 static tng_function_status tng_general_info_block_len_calculate
2010 (tng_trajectory_t tng_data,
2013 int first_program_name_len, first_user_name_len;
2014 int first_computer_name_len, first_pgp_signature_len;
2015 int last_program_name_len, last_user_name_len;
2016 int last_computer_name_len, last_pgp_signature_len;
2017 int forcefield_name_len;
2019 /* If the strings are unallocated allocate memory for just string
2021 if(!tng_data->first_program_name)
2023 tng_data->first_program_name = malloc(1);
2024 if(!tng_data->first_program_name)
2026 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2027 __FILE__, __LINE__);
2028 return(TNG_CRITICAL);
2030 tng_data->first_program_name[0] = 0;
2032 if(!tng_data->last_program_name)
2034 tng_data->last_program_name = malloc(1);
2035 if(!tng_data->last_program_name)
2037 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2038 __FILE__, __LINE__);
2039 return(TNG_CRITICAL);
2041 tng_data->last_program_name[0] = 0;
2043 if(!tng_data->first_user_name)
2045 tng_data->first_user_name = malloc(1);
2046 if(!tng_data->first_user_name)
2048 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2049 __FILE__, __LINE__);
2050 return(TNG_CRITICAL);
2052 tng_data->first_user_name[0] = 0;
2054 if(!tng_data->last_user_name)
2056 tng_data->last_user_name = malloc(1);
2057 if(!tng_data->last_user_name)
2059 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2060 __FILE__, __LINE__);
2061 return(TNG_CRITICAL);
2063 tng_data->last_user_name[0] = 0;
2065 if(!tng_data->first_computer_name)
2067 tng_data->first_computer_name = malloc(1);
2068 if(!tng_data->first_computer_name)
2070 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2071 __FILE__, __LINE__);
2072 return(TNG_CRITICAL);
2074 tng_data->first_computer_name[0] = 0;
2076 if(!tng_data->last_computer_name)
2078 tng_data->last_computer_name = malloc(1);
2079 if(!tng_data->last_computer_name)
2081 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2082 __FILE__, __LINE__);
2083 return(TNG_CRITICAL);
2085 tng_data->last_computer_name[0] = 0;
2087 if(!tng_data->first_pgp_signature)
2089 tng_data->first_pgp_signature = malloc(1);
2090 if(!tng_data->first_pgp_signature)
2092 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2093 __FILE__, __LINE__);
2094 return(TNG_CRITICAL);
2096 tng_data->first_pgp_signature[0] = 0;
2098 if(!tng_data->last_pgp_signature)
2100 tng_data->last_pgp_signature = malloc(1);
2101 if(!tng_data->last_pgp_signature)
2103 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2104 __FILE__, __LINE__);
2105 return(TNG_CRITICAL);
2107 tng_data->last_pgp_signature[0] = 0;
2109 if(!tng_data->forcefield_name)
2111 tng_data->forcefield_name = malloc(1);
2112 if(!tng_data->forcefield_name)
2114 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2115 __FILE__, __LINE__);
2116 return(TNG_CRITICAL);
2118 tng_data->forcefield_name[0] = 0;
2121 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2123 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2125 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2127 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2129 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2131 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2133 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2135 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2137 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2140 *len = sizeof(tng_data->time) +
2141 sizeof(tng_data->var_num_atoms_flag) +
2142 sizeof(tng_data->frame_set_n_frames) +
2143 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
2144 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
2145 sizeof(tng_data->medium_stride_length) +
2146 sizeof(tng_data->long_stride_length) +
2147 sizeof(tng_data->distance_unit_exponential) +
2148 first_program_name_len +
2149 last_program_name_len +
2150 first_user_name_len +
2151 last_user_name_len +
2152 first_computer_name_len +
2153 last_computer_name_len +
2154 first_pgp_signature_len +
2155 last_pgp_signature_len +
2156 forcefield_name_len;
2158 return(TNG_SUCCESS);
2161 /** Read a general info block. This is the first block of a TNG file.
2162 * Populate the fields in tng_data.
2163 * @param tng_data is a trajectory data container.
2164 * @param block is a general block container.
2165 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2166 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2167 * compared to the md5 hash of the read contents to ensure valid data.
2168 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2169 * error has occured.
2171 static tng_function_status tng_general_info_block_read
2172 (tng_trajectory_t tng_data, tng_gen_block_t block,
2173 const char hash_mode)
2175 int len, offset = 0;
2180 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2182 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2184 return(TNG_CRITICAL);
2187 temp = realloc(block->block_contents, block->block_contents_size);
2190 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2191 block->block_contents_size, __FILE__, __LINE__);
2192 free(block->block_contents);
2193 block->block_contents = 0;
2194 return(TNG_CRITICAL);
2196 block->block_contents = temp;
2198 /* Read the whole block into block_contents to be able to write it to disk
2199 * even if it cannot be interpreted. */
2200 if(fread(block->block_contents, block->block_contents_size, 1,
2201 tng_data->input_file) == 0)
2203 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
2204 return(TNG_CRITICAL);
2207 /* FIXME: Does not check if the size of the contents matches the expected
2208 * size or if the contents can be read. */
2210 if(hash_mode == TNG_USE_HASH)
2212 tng_md5_hash_match_verify(block, &same_hash);
2213 if(same_hash != TNG_TRUE)
2215 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
2217 __FILE__, __LINE__);
2218 /* return(TNG_FAILURE); */
2222 len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
2223 temp = realloc(tng_data->first_program_name, len);
2226 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2227 __FILE__, __LINE__);
2228 free(tng_data->first_program_name);
2229 tng_data->first_program_name = 0;
2230 return(TNG_CRITICAL);
2232 tng_data->first_program_name = temp;
2233 strncpy(tng_data->first_program_name, block->block_contents, len);
2236 len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
2237 temp = realloc(tng_data->last_program_name, len);
2240 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2241 __FILE__, __LINE__);
2242 free(tng_data->last_program_name);
2243 tng_data->last_program_name = 0;
2244 return(TNG_CRITICAL);
2246 tng_data->last_program_name = temp;
2247 strncpy(tng_data->last_program_name, block->block_contents + offset, len);
2250 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2251 temp = realloc(tng_data->first_user_name, len);
2254 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2255 __FILE__, __LINE__);
2256 free(tng_data->first_user_name);
2257 tng_data->first_user_name = 0;
2258 return(TNG_CRITICAL);
2260 tng_data->first_user_name = temp;
2261 strncpy(tng_data->first_user_name, block->block_contents+offset, len);
2264 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2265 temp = realloc(tng_data->last_user_name, len);
2268 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2269 __FILE__, __LINE__);
2270 free(tng_data->last_user_name);
2271 tng_data->last_user_name = 0;
2272 return(TNG_CRITICAL);
2274 tng_data->last_user_name = temp;
2275 strncpy(tng_data->last_user_name, block->block_contents+offset, len);
2278 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2279 temp = realloc(tng_data->first_computer_name, len);
2282 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2283 __FILE__, __LINE__);
2284 free(tng_data->first_computer_name);
2285 tng_data->first_computer_name = 0;
2286 return(TNG_CRITICAL);
2288 tng_data->first_computer_name = temp;
2289 strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
2292 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2293 temp = realloc(tng_data->last_computer_name, len);
2296 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2297 __FILE__, __LINE__);
2298 free(tng_data->last_computer_name);
2299 tng_data->last_computer_name = 0;
2300 return(TNG_CRITICAL);
2302 tng_data->last_computer_name = temp;
2303 strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
2306 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2307 temp = realloc(tng_data->first_pgp_signature, len);
2310 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2311 __FILE__, __LINE__);
2312 free(tng_data->first_pgp_signature);
2313 tng_data->first_pgp_signature = 0;
2314 return(TNG_CRITICAL);
2316 tng_data->first_pgp_signature = temp;
2317 strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
2320 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2321 temp = realloc(tng_data->last_pgp_signature, len);
2324 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2325 __FILE__, __LINE__);
2326 free(tng_data->last_pgp_signature);
2327 tng_data->last_pgp_signature = 0;
2328 return(TNG_CRITICAL);
2330 tng_data->last_pgp_signature = temp;
2331 strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
2334 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2335 temp = realloc(tng_data->forcefield_name, len);
2338 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2339 __FILE__, __LINE__);
2340 free(tng_data->forcefield_name);
2341 tng_data->forcefield_name = 0;
2342 return(TNG_CRITICAL);
2344 tng_data->forcefield_name = temp;
2345 strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
2348 memcpy(&tng_data->time, block->block_contents+offset,
2349 sizeof(tng_data->time));
2350 if(tng_data->input_endianness_swap_func_64)
2352 if(tng_data->input_endianness_swap_func_64(tng_data,
2356 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2357 __FILE__, __LINE__);
2360 offset += sizeof(tng_data->time);
2362 memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
2363 sizeof(tng_data->var_num_atoms_flag));
2364 offset += sizeof(tng_data->var_num_atoms_flag);
2366 memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
2367 sizeof(tng_data->frame_set_n_frames));
2368 if(tng_data->input_endianness_swap_func_64)
2370 if(tng_data->input_endianness_swap_func_64(tng_data,
2371 &tng_data->frame_set_n_frames)
2374 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2375 __FILE__, __LINE__);
2378 offset += sizeof(tng_data->frame_set_n_frames);
2380 memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
2381 block->block_contents+offset,
2382 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
2383 if(tng_data->input_endianness_swap_func_64)
2385 if(tng_data->input_endianness_swap_func_64(tng_data,
2386 &tng_data->first_trajectory_frame_set_input_file_pos)
2389 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2390 __FILE__, __LINE__);
2393 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
2395 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
2396 tng_data->first_trajectory_frame_set_input_file_pos;
2399 memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
2400 block->block_contents+offset,
2401 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
2402 if(tng_data->input_endianness_swap_func_64)
2404 if(tng_data->input_endianness_swap_func_64(tng_data,
2405 &tng_data->last_trajectory_frame_set_input_file_pos)
2408 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2409 __FILE__, __LINE__);
2412 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
2414 memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
2415 sizeof(tng_data->medium_stride_length));
2416 if(tng_data->input_endianness_swap_func_64)
2418 if(tng_data->input_endianness_swap_func_64(tng_data,
2419 &tng_data->medium_stride_length)
2422 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2423 __FILE__, __LINE__);
2426 offset += sizeof(tng_data->medium_stride_length);
2428 memcpy(&tng_data->long_stride_length, block->block_contents+offset,
2429 sizeof(tng_data->long_stride_length));
2430 if(tng_data->input_endianness_swap_func_64)
2432 if(tng_data->input_endianness_swap_func_64(tng_data,
2433 &tng_data->long_stride_length)
2436 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2437 __FILE__, __LINE__);
2440 offset += sizeof(tng_data->long_stride_length);
2442 if(block->block_version >= 3)
2444 memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
2445 sizeof(tng_data->distance_unit_exponential));
2446 if(tng_data->input_endianness_swap_func_64)
2448 if(tng_data->input_endianness_swap_func_64(tng_data,
2449 &tng_data->distance_unit_exponential)
2452 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2453 __FILE__, __LINE__);
2458 return(TNG_SUCCESS);
2461 /** Write a general info block. This is the first block of a TNG file.
2462 * @param tng_data is a trajectory data container.
2463 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2464 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2465 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2466 * error has occured.
2468 static tng_function_status tng_general_info_block_write
2469 (tng_trajectory_t tng_data,
2470 const char hash_mode)
2472 int first_program_name_len, first_user_name_len;
2473 int first_computer_name_len, first_pgp_signature_len;
2474 int last_program_name_len, last_user_name_len;
2475 int last_computer_name_len, last_pgp_signature_len;
2476 int forcefield_name_len, name_len;
2478 tng_gen_block_t block;
2480 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2482 return(TNG_CRITICAL);
2485 fseeko(tng_data->output_file, 0, SEEK_SET);
2487 tng_block_init(&block);
2489 name_len = (int)strlen("GENERAL INFO");
2491 block->name = malloc(name_len + 1);
2494 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2495 name_len+1, __FILE__, __LINE__);
2496 tng_block_destroy(&block);
2497 return(TNG_CRITICAL);
2500 strcpy(block->name, "GENERAL INFO");
2501 block->id = TNG_GENERAL_INFO;
2503 if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
2506 fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2507 __FILE__, __LINE__);
2508 tng_block_destroy(&block);
2509 return(TNG_CRITICAL);
2512 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2514 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2516 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2518 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2520 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2522 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2524 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2526 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2528 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2531 if(block->block_contents)
2533 free(block->block_contents);
2535 block->block_contents = malloc(block->block_contents_size);
2536 if(!block->block_contents)
2538 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2539 block->block_contents_size, __FILE__, __LINE__);
2540 tng_block_destroy(&block);
2541 return(TNG_CRITICAL);
2544 strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
2545 offset += first_program_name_len;
2547 strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
2548 offset += last_program_name_len;
2550 strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
2551 offset += first_user_name_len;
2553 strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
2554 offset += last_user_name_len;
2556 strncpy(block->block_contents+offset, tng_data->first_computer_name,
2557 first_computer_name_len);
2558 offset += first_computer_name_len;
2560 strncpy(block->block_contents+offset, tng_data->last_computer_name,
2561 last_computer_name_len);
2562 offset += last_computer_name_len;
2564 strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
2565 first_pgp_signature_len);
2566 offset += first_pgp_signature_len;
2568 strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
2569 last_pgp_signature_len);
2570 offset += last_pgp_signature_len;
2572 strncpy(block->block_contents+offset, tng_data->forcefield_name,
2573 forcefield_name_len);
2574 offset += forcefield_name_len;
2576 memcpy(block->block_contents+offset, &tng_data->time,
2577 sizeof(tng_data->time));
2578 if(tng_data->output_endianness_swap_func_64)
2580 if(tng_data->output_endianness_swap_func_64(tng_data,
2581 (int64_t *)block->header_contents+offset)
2584 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2585 __FILE__, __LINE__);
2588 offset += sizeof(tng_data->time);
2590 memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
2591 sizeof(tng_data->var_num_atoms_flag));
2592 offset += sizeof(tng_data->var_num_atoms_flag);
2594 memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
2595 sizeof(tng_data->frame_set_n_frames));
2596 if(tng_data->output_endianness_swap_func_64)
2598 if(tng_data->output_endianness_swap_func_64(tng_data,
2599 (int64_t *)block->header_contents+offset)
2602 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2603 __FILE__, __LINE__);
2606 offset += sizeof(tng_data->frame_set_n_frames);
2608 memcpy(block->block_contents+offset,
2609 &tng_data->first_trajectory_frame_set_output_file_pos,
2610 sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
2611 if(tng_data->output_endianness_swap_func_64)
2613 if(tng_data->output_endianness_swap_func_64(tng_data,
2614 (int64_t *)block->header_contents+offset)
2617 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2618 __FILE__, __LINE__);
2621 offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
2623 memcpy(block->block_contents+offset,
2624 &tng_data->last_trajectory_frame_set_output_file_pos,
2625 sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
2626 if(tng_data->output_endianness_swap_func_64)
2628 if(tng_data->output_endianness_swap_func_64(tng_data,
2629 (int64_t *)block->header_contents+offset)
2632 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2633 __FILE__, __LINE__);
2636 offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
2638 memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
2639 sizeof(tng_data->medium_stride_length));
2640 if(tng_data->output_endianness_swap_func_64)
2642 if(tng_data->output_endianness_swap_func_64(tng_data,
2643 (int64_t *)block->header_contents+offset)
2646 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2647 __FILE__, __LINE__);
2650 offset += sizeof(tng_data->medium_stride_length);
2652 memcpy(block->block_contents+offset, &tng_data->long_stride_length,
2653 sizeof(tng_data->long_stride_length));
2654 if(tng_data->output_endianness_swap_func_64)
2656 if(tng_data->output_endianness_swap_func_64(tng_data,
2657 (int64_t *)block->header_contents+offset)
2660 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2661 __FILE__, __LINE__);
2664 offset += sizeof(tng_data->long_stride_length);
2666 memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
2667 sizeof(tng_data->distance_unit_exponential));
2668 if(tng_data->output_endianness_swap_func_64)
2670 if(tng_data->output_endianness_swap_func_64(tng_data,
2671 (int64_t *)block->header_contents+offset)
2674 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2675 __FILE__, __LINE__);
2679 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
2681 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2682 tng_data->output_file_path, __FILE__, __LINE__);
2683 tng_block_destroy(&block);
2684 return(TNG_CRITICAL);
2687 if(fwrite(block->block_contents, block->block_contents_size, 1,
2688 tng_data->output_file) != 1)
2690 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
2691 tng_block_destroy(&block);
2692 return(TNG_CRITICAL);
2695 tng_block_destroy(&block);
2697 return(TNG_SUCCESS);
2700 /** Read the chain data of a molecules block.
2701 * @param tng_data is a trajectory data container.
2702 * @param block is a general block container.
2703 * @param chain is the chain data container.
2704 * @param offset is the offset of the block input and is updated when reading.
2705 * @return TNG_SUCCESS(0) is successful.
2707 static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
2708 tng_gen_block_t block,
2714 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2716 memcpy(&chain->id, block->block_contents+*offset,
2718 if(tng_data->input_endianness_swap_func_64)
2720 if(tng_data->input_endianness_swap_func_64(tng_data,
2724 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2725 __FILE__, __LINE__);
2728 *offset += sizeof(chain->id);
2730 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2732 chain->name = malloc(len);
2733 strncpy(chain->name,
2734 block->block_contents+*offset, len);
2737 memcpy(&chain->n_residues, block->block_contents+*offset,
2738 sizeof(chain->n_residues));
2739 if(tng_data->input_endianness_swap_func_64)
2741 if(tng_data->input_endianness_swap_func_64(tng_data,
2745 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2746 __FILE__, __LINE__);
2749 *offset += sizeof(chain->n_residues);
2751 return(TNG_SUCCESS);
2754 /** Write the chain data of a molecules block.
2755 * @param tng_data is a trajectory data container.
2756 * @param block is a general block container.
2757 * @param chain is the chain data container.
2758 * @param offset is the offset of the block output and is updated when writing.
2759 * @return TNG_SUCCESS(0) is successful.
2761 static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
2762 tng_gen_block_t block,
2768 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2770 memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
2771 if(tng_data->output_endianness_swap_func_64)
2773 if(tng_data->output_endianness_swap_func_64(tng_data,
2774 (int64_t *)block->header_contents+*offset)
2777 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2778 __FILE__, __LINE__);
2781 *offset += sizeof(chain->id);
2783 len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2784 strncpy(block->block_contents + *offset, chain->name, len);
2787 memcpy(block->block_contents+*offset, &chain->n_residues,
2788 sizeof(chain->n_residues));
2789 if(tng_data->output_endianness_swap_func_64)
2791 if(tng_data->output_endianness_swap_func_64(tng_data,
2792 (int64_t *)block->header_contents+*offset)
2795 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2796 __FILE__, __LINE__);
2799 *offset += sizeof(chain->n_residues);
2801 return(TNG_SUCCESS);
2804 /** Read the residue data of a molecules block.
2805 * @param tng_data is a trajectory data container.
2806 * @param block is a general block container.
2807 * @param residue is the residue data container.
2808 * @param offset is the offset of the block input and is updated when reading.
2809 * @return TNG_SUCCESS(0) is successful.
2811 static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
2812 tng_gen_block_t block,
2813 tng_residue_t residue,
2818 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2820 memcpy(&residue->id, block->block_contents+*offset,
2821 sizeof(residue->id));
2822 if(tng_data->input_endianness_swap_func_64)
2824 if(tng_data->input_endianness_swap_func_64(tng_data,
2828 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2829 __FILE__, __LINE__);
2832 *offset += sizeof(residue->id);
2834 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2836 residue->name = malloc(len);
2837 strncpy(residue->name,
2838 block->block_contents+*offset, len);
2841 memcpy(&residue->n_atoms, block->block_contents+*offset,
2842 sizeof(residue->n_atoms));
2843 if(tng_data->input_endianness_swap_func_64)
2845 if(tng_data->input_endianness_swap_func_64(tng_data,
2849 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2850 __FILE__, __LINE__);
2853 *offset += sizeof(residue->n_atoms);
2855 return(TNG_SUCCESS);
2858 /** Write the residue data of a molecules block.
2859 * @param tng_data is a trajectory data container.
2860 * @param block is a general block container.
2861 * @param residue is the residue data container.
2862 * @param offset is the offset of the block output and is updated when writing.
2863 * @return TNG_SUCCESS(0) is successful.
2865 static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
2866 tng_gen_block_t block,
2867 tng_residue_t residue,
2872 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2874 memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
2875 if(tng_data->output_endianness_swap_func_64)
2877 if(tng_data->output_endianness_swap_func_64(tng_data,
2878 (int64_t *)block->header_contents+*offset)
2881 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2882 __FILE__, __LINE__);
2885 *offset += sizeof(residue->id);
2887 len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2888 strncpy(block->block_contents + *offset, residue->name, len);
2891 memcpy(block->block_contents+*offset, &residue->n_atoms,
2892 sizeof(residue->n_atoms));
2893 if(tng_data->output_endianness_swap_func_64)
2895 if(tng_data->output_endianness_swap_func_64(tng_data,
2896 (int64_t *)block->header_contents+*offset)
2899 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2900 __FILE__, __LINE__);
2903 *offset += sizeof(residue->n_atoms);
2905 return(TNG_SUCCESS);
2908 /** Read the atom data of a molecules block.
2909 * @param tng_data is a trajectory data container.
2910 * @param block is a general block container.
2911 * @param atom is the atom data container.
2912 * @param offset is the offset of the block input and is updated when reading.
2913 * @return TNG_SUCCESS(0) is successful.
2915 static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
2916 tng_gen_block_t block,
2922 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2924 memcpy(&atom->id, block->block_contents+*offset,
2926 if(tng_data->input_endianness_swap_func_64)
2928 if(tng_data->input_endianness_swap_func_64(tng_data,
2932 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2933 __FILE__, __LINE__);
2936 *offset += sizeof(atom->id);
2938 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2940 atom->name = malloc(len);
2942 block->block_contents+*offset, len);
2945 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2947 atom->atom_type = malloc(len);
2948 strncpy(atom->atom_type,
2949 block->block_contents+*offset, len);
2952 return(TNG_SUCCESS);
2955 /** Write the atom data of a molecules block.
2956 * @param tng_data is a trajectory data container.
2957 * @param block is a general block container.
2958 * @param atom is the atom data container.
2959 * @param offset is the offset of the block output and is updated when writing.
2960 * @return TNG_SUCCESS(0) is successful.
2962 static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
2963 tng_gen_block_t block,
2969 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2971 memcpy(block->block_contents+*offset, &atom->id,
2973 if(tng_data->output_endianness_swap_func_64)
2975 if(tng_data->output_endianness_swap_func_64(tng_data,
2976 (int64_t *)block->header_contents+*offset)
2979 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2980 __FILE__, __LINE__);
2983 *offset += sizeof(atom->id);
2985 len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2986 strncpy(block->block_contents + *offset, atom->name, len);
2989 len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2990 strncpy(block->block_contents + *offset, atom->atom_type, len);
2993 return(TNG_SUCCESS);
2996 static tng_function_status tng_molecules_block_len_calculate
2997 (const tng_trajectory_t tng_data,
3001 tng_molecule_t molecule;
3003 tng_residue_t residue;
3009 for(i = 0; i < tng_data->n_molecules; i++)
3011 molecule = &tng_data->molecules[i];
3014 molecule->name = malloc(1);
3017 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3018 __FILE__, __LINE__);
3019 return(TNG_CRITICAL);
3021 molecule->name[0] = 0;
3023 *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3025 chain = molecule->chains;
3026 for(j = 0; j < molecule->n_chains; j++)
3028 *len += sizeof(chain->id);
3032 chain->name = malloc(1);
3035 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3036 __FILE__, __LINE__);
3037 return(TNG_CRITICAL);
3041 *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
3043 *len += sizeof(chain->n_residues);
3048 residue = molecule->residues;
3049 for(j = 0; j < molecule->n_residues; j++)
3051 *len += sizeof(residue->id);
3055 residue->name = malloc(1);
3058 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3059 __FILE__, __LINE__);
3060 return(TNG_CRITICAL);
3062 residue->name[0] = 0;
3064 *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
3066 *len += sizeof(residue->n_atoms);
3071 atom = molecule->atoms;
3072 for(j = 0; j < molecule->n_atoms; j++)
3074 *len += sizeof(atom->id);
3077 atom->name = malloc(1);
3080 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3081 __FILE__, __LINE__);
3082 return(TNG_CRITICAL);
3086 *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
3088 if(!atom->atom_type)
3090 atom->atom_type = malloc(1);
3091 if(!atom->atom_type)
3093 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3094 __FILE__, __LINE__);
3095 return(TNG_CRITICAL);
3097 atom->atom_type[0] = 0;
3099 *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
3104 for(j = 0; j < molecule->n_bonds; j++)
3106 *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
3109 *len += sizeof(tng_data->n_molecules) +
3110 (sizeof(molecule->id) +
3111 sizeof(molecule->quaternary_str) +
3112 sizeof(molecule->n_chains) +
3113 sizeof(molecule->n_residues) +
3114 sizeof(molecule->n_atoms) +
3115 sizeof(molecule->n_bonds)) *
3116 tng_data->n_molecules;
3118 if(!tng_data->var_num_atoms_flag)
3120 *len += tng_data->n_molecules * sizeof(int64_t);
3123 return(TNG_SUCCESS);
3126 /** Read a molecules block. Contains chain, residue and atom data
3127 * @param tng_data is a trajectory data container.
3128 * @param block is a general block container.
3129 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3130 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3131 * compared to the md5 hash of the read contents to ensure valid data.
3132 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3133 * error has occured.
3135 static tng_function_status tng_molecules_block_read
3136 (tng_trajectory_t tng_data,
3137 tng_gen_block_t block,
3138 const char hash_mode)
3141 int len, offset = 0;
3142 tng_molecule_t molecule;
3144 tng_residue_t residue;
3149 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3151 return(TNG_CRITICAL);
3154 if(block->block_contents)
3156 free(block->block_contents);
3159 block->block_contents = malloc(block->block_contents_size);
3160 if(!block->block_contents)
3162 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3163 block->block_contents_size, __FILE__, __LINE__);
3164 return(TNG_CRITICAL);
3167 /* Read the whole block into block_contents to be able to write it to disk
3168 * even if it cannot be interpreted. */
3169 if(fread(block->block_contents, block->block_contents_size, 1,
3170 tng_data->input_file) == 0)
3172 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3175 /* FIXME: Does not check if the size of the contents matches the expected
3176 * size or if the contents can be read. */
3178 if(hash_mode == TNG_USE_HASH)
3180 tng_md5_hash_match_verify(block, &same_hash);
3181 if(same_hash != TNG_TRUE)
3183 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3185 __FILE__, __LINE__);
3189 if(tng_data->molecules)
3191 for(i=0; i<tng_data->n_molecules; i++)
3193 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
3195 free(tng_data->molecules);
3196 tng_data->molecules = 0;
3197 tng_data->n_molecules = 0;
3200 memcpy(&tng_data->n_molecules, block->block_contents,
3201 sizeof(tng_data->n_molecules));
3202 if(tng_data->input_endianness_swap_func_64)
3204 if(tng_data->input_endianness_swap_func_64(tng_data,
3205 &tng_data->n_molecules)
3208 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3209 __FILE__, __LINE__);
3212 offset += sizeof(tng_data->n_molecules);
3214 if(tng_data->molecules)
3216 free(tng_data->molecules);
3219 tng_data->n_particles = 0;
3221 tng_data->molecules = malloc(tng_data->n_molecules *
3222 sizeof(struct tng_molecule));
3223 if(!tng_data->molecules)
3225 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3226 tng_data->n_molecules * sizeof(struct tng_molecule),
3227 __FILE__, __LINE__);
3228 return(TNG_CRITICAL);
3231 if(!tng_data->var_num_atoms_flag)
3233 if(tng_data->molecule_cnt_list)
3235 free(tng_data->molecule_cnt_list);
3237 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
3238 tng_data->n_molecules);
3239 if(!tng_data->molecule_cnt_list)
3241 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3242 tng_data->n_molecules * sizeof(struct tng_molecule),
3243 __FILE__, __LINE__);
3244 return(TNG_CRITICAL);
3248 /* Read each molecule from file */
3249 for(i=0; i < tng_data->n_molecules; i++)
3251 molecule = &tng_data->molecules[i];
3253 memcpy(&molecule->id, block->block_contents+offset,
3254 sizeof(molecule->id));
3255 if(tng_data->input_endianness_swap_func_64)
3257 if(tng_data->input_endianness_swap_func_64(tng_data,
3261 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3262 __FILE__, __LINE__);
3265 offset += sizeof(molecule->id);
3267 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
3268 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
3269 molecule->name = malloc(len);
3270 strncpy(molecule->name, block->block_contents+offset, len);
3273 memcpy(&molecule->quaternary_str, block->block_contents+offset,
3274 sizeof(molecule->quaternary_str));
3275 if(tng_data->input_endianness_swap_func_64)
3277 if(tng_data->input_endianness_swap_func_64(tng_data,
3278 &molecule->quaternary_str)
3281 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3282 __FILE__, __LINE__);
3285 offset += sizeof(molecule->quaternary_str);
3287 if(!tng_data->var_num_atoms_flag)
3289 memcpy(&tng_data->molecule_cnt_list[i],
3290 block->block_contents+offset,
3292 if(tng_data->input_endianness_swap_func_64)
3294 if(tng_data->input_endianness_swap_func_64(tng_data,
3295 &tng_data->molecule_cnt_list[i])
3298 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3299 __FILE__, __LINE__);
3302 offset += sizeof(int64_t);
3306 memcpy(&molecule->n_chains, block->block_contents+offset,
3307 sizeof(molecule->n_chains));
3308 if(tng_data->input_endianness_swap_func_64)
3310 if(tng_data->input_endianness_swap_func_64(tng_data,
3311 &molecule->n_chains)
3314 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3315 __FILE__, __LINE__);
3318 offset += sizeof(molecule->n_chains);
3320 memcpy(&molecule->n_residues, block->block_contents+offset,
3321 sizeof(molecule->n_residues));
3322 if(tng_data->input_endianness_swap_func_64)
3324 if(tng_data->input_endianness_swap_func_64(tng_data,
3325 &molecule->n_residues)
3328 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3329 __FILE__, __LINE__);
3332 offset += sizeof(molecule->n_residues);
3334 memcpy(&molecule->n_atoms, block->block_contents+offset,
3335 sizeof(molecule->n_atoms));
3336 if(tng_data->input_endianness_swap_func_64)
3338 if(tng_data->input_endianness_swap_func_64(tng_data,
3342 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3343 __FILE__, __LINE__);
3346 offset += sizeof(molecule->n_atoms);
3348 tng_data->n_particles += molecule->n_atoms *
3349 tng_data->molecule_cnt_list[i];
3351 if(molecule->n_chains > 0)
3353 molecule->chains = malloc(molecule->n_chains *
3354 sizeof(struct tng_chain));
3355 if(!molecule->chains)
3357 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3358 molecule->n_chains * sizeof(struct tng_chain),
3359 __FILE__, __LINE__);
3360 return(TNG_CRITICAL);
3363 chain = molecule->chains;
3370 if(molecule->n_residues > 0)
3372 molecule->residues = malloc(molecule->n_residues *
3373 sizeof(struct tng_residue));
3374 if(!molecule->residues)
3376 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3377 molecule->n_residues * sizeof(struct tng_residue),
3378 __FILE__, __LINE__);
3379 if(molecule->chains)
3381 free(molecule->chains);
3382 molecule->chains = 0;
3384 return(TNG_CRITICAL);
3387 residue = molecule->residues;
3394 molecule->atoms = malloc(molecule->n_atoms *
3395 sizeof(struct tng_atom));
3396 if(!molecule->atoms)
3398 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3399 molecule->n_atoms * sizeof(struct tng_atom),
3400 __FILE__, __LINE__);
3401 if(molecule->chains)
3403 free(molecule->chains);
3404 molecule->chains = 0;
3406 if(molecule->residues)
3408 free(molecule->residues);
3409 molecule->residues = 0;
3411 return(TNG_CRITICAL);
3414 atom = molecule->atoms;
3416 if(molecule->n_chains > 0)
3418 /* Read the chains of the molecule */
3419 for(j=0; j<molecule->n_chains; j++)
3421 chain->molecule = molecule;
3423 tng_chain_data_read(tng_data, block, chain, &offset);
3425 chain->residues = molecule->residues;
3426 residue = chain->residues;
3428 /* Read the residues of the chain */
3429 for(k=0; k<chain->n_residues; k++)
3431 residue->chain = chain;
3433 tng_residue_data_read(tng_data, block, residue, &offset);
3435 residue->atoms_offset = atom - molecule->atoms;
3436 /* Read the atoms of the residue */
3437 for(l=0; l<residue->n_atoms; l++)
3439 atom->residue = residue;
3441 tng_atom_data_read(tng_data, block, atom, &offset);
3452 if(molecule->n_residues > 0)
3454 for(k=0; k<molecule->n_residues; k++)
3458 tng_residue_data_read(tng_data, block, residue, &offset);
3460 residue->atoms_offset = atom - molecule->atoms;
3461 /* Read the atoms of the residue */
3462 for(l=0; l<residue->n_atoms; l++)
3464 atom->residue = residue;
3466 tng_atom_data_read(tng_data, block, atom, &offset);
3475 for(l=0; l<molecule->n_atoms; l++)
3479 tng_atom_data_read(tng_data, block, atom, &offset);
3486 memcpy(&molecule->n_bonds, block->block_contents+offset,
3487 sizeof(molecule->n_bonds));
3488 if(tng_data->input_endianness_swap_func_64)
3490 if(tng_data->input_endianness_swap_func_64(tng_data,
3494 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3495 __FILE__, __LINE__);
3498 offset += sizeof(molecule->n_bonds);
3500 if(molecule->n_bonds > 0)
3502 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
3503 sizeof(struct tng_bond));
3504 if(!molecule->bonds)
3506 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3507 molecule->n_bonds * sizeof(struct tng_bond),
3508 __FILE__, __LINE__);
3509 if(molecule->chains)
3511 free(molecule->chains);
3512 molecule->chains = 0;
3514 if(molecule->residues)
3516 free(molecule->residues);
3517 molecule->residues = 0;
3521 free(molecule->atoms);
3522 molecule->atoms = 0;
3524 return(TNG_CRITICAL);
3527 bond = molecule->bonds;
3529 for(j=0; j<molecule->n_bonds; j++)
3531 memcpy(&bond->from_atom_id, block->block_contents+offset,
3532 sizeof(bond->from_atom_id));
3533 if(tng_data->input_endianness_swap_func_64)
3535 if(tng_data->input_endianness_swap_func_64(tng_data,
3536 &bond->from_atom_id)
3539 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3540 __FILE__, __LINE__);
3543 offset += sizeof(bond->from_atom_id);
3545 memcpy(&bond->to_atom_id, block->block_contents+offset,
3546 sizeof(bond->to_atom_id));
3547 if(tng_data->input_endianness_swap_func_64)
3549 if(tng_data->input_endianness_swap_func_64(tng_data,
3553 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3554 __FILE__, __LINE__);
3557 offset += sizeof(bond->to_atom_id);
3564 molecule->bonds = 0;
3568 return(TNG_SUCCESS);
3571 /** Write a molecules block.
3572 * @param tng_data is a trajectory data container.
3573 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3574 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3575 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3576 * error has occured.
3578 static tng_function_status tng_molecules_block_write
3579 (tng_trajectory_t tng_data,
3580 const char hash_mode)
3582 int len = 0, name_len, offset = 0;
3584 tng_molecule_t molecule;
3586 tng_residue_t residue;
3589 tng_gen_block_t block;
3591 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3593 return(TNG_CRITICAL);
3596 tng_block_init(&block);
3598 name_len = (int)strlen("MOLECULES");
3600 block->name = malloc(name_len + 1);
3603 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3604 name_len+1, __FILE__, __LINE__);
3605 tng_block_destroy(&block);
3606 return(TNG_CRITICAL);
3609 strcpy(block->name, "MOLECULES");
3610 block->id = TNG_MOLECULES;
3612 if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
3615 fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3616 __FILE__, __LINE__);
3617 tng_block_destroy(&block);
3618 return(TNG_CRITICAL);
3621 block->block_contents = malloc(block->block_contents_size);
3622 if(!block->block_contents)
3624 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3625 block->block_contents_size, __FILE__, __LINE__);
3626 tng_block_destroy(&block);
3627 return(TNG_CRITICAL);
3630 memcpy(block->block_contents+offset, &tng_data->n_molecules,
3631 sizeof(tng_data->n_molecules));
3632 if(tng_data->output_endianness_swap_func_64)
3634 if(tng_data->output_endianness_swap_func_64(tng_data,
3635 (int64_t *)block->header_contents+offset)
3638 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3639 __FILE__, __LINE__);
3642 offset += sizeof(tng_data->n_molecules);
3644 for(i = 0; i < tng_data->n_molecules; i++)
3646 molecule = &tng_data->molecules[i];
3647 memcpy(block->block_contents+offset, &molecule->id,
3648 sizeof(molecule->id));
3649 if(tng_data->output_endianness_swap_func_64)
3651 if(tng_data->output_endianness_swap_func_64(tng_data,
3652 (int64_t *)block->header_contents+offset)
3655 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3656 __FILE__, __LINE__);
3659 offset += sizeof(molecule->id);
3661 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
3662 len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3663 strncpy(block->block_contents + offset, molecule->name, len);
3666 memcpy(block->block_contents+offset, &molecule->quaternary_str,
3667 sizeof(molecule->quaternary_str));
3668 if(tng_data->output_endianness_swap_func_64)
3670 if(tng_data->output_endianness_swap_func_64(tng_data,
3671 (int64_t *)block->header_contents+offset)
3674 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3675 __FILE__, __LINE__);
3678 offset += sizeof(molecule->quaternary_str);
3680 if(!tng_data->var_num_atoms_flag)
3682 memcpy(block->block_contents+offset,
3683 &tng_data->molecule_cnt_list[i], sizeof(int64_t));
3684 if(tng_data->output_endianness_swap_func_64)
3686 if(tng_data->output_endianness_swap_func_64(tng_data,
3687 (int64_t *)block->header_contents+offset)
3690 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3691 __FILE__, __LINE__);
3694 offset += sizeof(int64_t);
3697 memcpy(block->block_contents+offset, &molecule->n_chains,
3698 sizeof(molecule->n_chains));
3699 if(tng_data->output_endianness_swap_func_64)
3701 if(tng_data->output_endianness_swap_func_64(tng_data,
3702 (int64_t *)block->header_contents+offset)
3705 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3706 __FILE__, __LINE__);
3709 offset += sizeof(molecule->n_chains);
3711 memcpy(block->block_contents+offset, &molecule->n_residues,
3712 sizeof(molecule->n_residues));
3713 if(tng_data->output_endianness_swap_func_64)
3715 if(tng_data->output_endianness_swap_func_64(tng_data,
3716 (int64_t *)block->header_contents+offset)
3719 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3720 __FILE__, __LINE__);
3723 offset += sizeof(molecule->n_residues);
3725 memcpy(block->block_contents+offset, &molecule->n_atoms,
3726 sizeof(molecule->n_atoms));
3727 if(tng_data->output_endianness_swap_func_64)
3729 if(tng_data->output_endianness_swap_func_64(tng_data,
3730 (int64_t *)block->header_contents+offset)
3733 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3734 __FILE__, __LINE__);
3737 offset += sizeof(molecule->n_atoms);
3739 if(molecule->n_chains > 0)
3741 chain = molecule->chains;
3742 for(j = 0; j < molecule->n_chains; j++)
3744 tng_chain_data_write(tng_data, block, chain, &offset);
3746 residue = chain->residues;
3747 for(k = 0; k < chain->n_residues; k++)
3749 tng_residue_data_write(tng_data, block, residue, &offset);
3751 atom = molecule->atoms + residue->atoms_offset;
3752 for(l = 0; l < residue->n_atoms; l++)
3754 tng_atom_data_write(tng_data, block, atom, &offset);
3765 if(molecule->n_residues > 0)
3767 residue = molecule->residues;
3768 for(k = 0; k < molecule->n_residues; k++)
3770 tng_residue_data_write(tng_data, block, residue, &offset);
3772 atom = molecule->atoms + residue->atoms_offset;
3773 for(l = 0; l < residue->n_atoms; l++)
3775 tng_atom_data_write(tng_data, block, atom, &offset);
3784 atom = molecule->atoms;
3785 for(l = 0; l < molecule->n_atoms; l++)
3787 tng_atom_data_write(tng_data, block, atom, &offset);
3794 memcpy(block->block_contents+offset, &molecule->n_bonds,
3795 sizeof(molecule->n_bonds));
3796 if(tng_data->output_endianness_swap_func_64)
3798 if(tng_data->output_endianness_swap_func_64(tng_data,
3799 (int64_t *)block->header_contents+offset)
3802 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3803 __FILE__, __LINE__);
3806 offset += sizeof(molecule->n_bonds);
3808 bond = molecule->bonds;
3809 for(j = 0; j < molecule->n_bonds; j++)
3811 memcpy(block->block_contents+offset, &bond->from_atom_id,
3812 sizeof(bond->from_atom_id));
3813 if(tng_data->output_endianness_swap_func_64)
3815 if(tng_data->output_endianness_swap_func_64(tng_data,
3816 (int64_t *)block->header_contents+offset)
3819 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3820 __FILE__, __LINE__);
3823 offset += sizeof(bond->from_atom_id);
3825 memcpy(block->block_contents+offset, &bond->to_atom_id,
3826 sizeof(bond->to_atom_id));
3827 if(tng_data->output_endianness_swap_func_64)
3829 if(tng_data->output_endianness_swap_func_64(tng_data,
3830 (int64_t *)block->header_contents+offset)
3833 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3834 __FILE__, __LINE__);
3837 offset += sizeof(bond->to_atom_id);
3843 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3845 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3846 tng_data->output_file_path, __FILE__, __LINE__);
3847 tng_block_destroy(&block);
3848 return(TNG_CRITICAL);
3851 if(fwrite(block->block_contents, block->block_contents_size, 1,
3852 tng_data->output_file) != 1)
3854 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
3855 __FILE__, __LINE__);
3856 tng_block_destroy(&block);
3857 return(TNG_CRITICAL);
3860 tng_block_destroy(&block);
3862 return(TNG_SUCCESS);
3865 static tng_function_status tng_frame_set_block_len_calculate
3866 (const tng_trajectory_t tng_data,
3869 *len = sizeof(int64_t) * 8;
3870 *len += sizeof(double) * 2;
3872 if(tng_data->var_num_atoms_flag)
3874 *len += sizeof(int64_t) * tng_data->n_molecules;
3876 return(TNG_SUCCESS);
3879 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
3880 * @param tng_data is a trajectory data container.
3881 * @param block is a general block container.
3882 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3883 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3884 * compared to the md5 hash of the read contents to ensure valid data.
3885 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3886 * error has occured.
3888 static tng_function_status tng_frame_set_block_read
3889 (tng_trajectory_t tng_data,
3890 tng_gen_block_t block,
3891 const char hash_mode)
3894 int64_t file_pos, i, prev_n_particles;
3896 tng_trajectory_frame_set_t frame_set =
3897 &tng_data->current_trajectory_frame_set;
3899 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3901 return(TNG_CRITICAL);
3904 if(block->block_contents)
3906 free(block->block_contents);
3909 block->block_contents = malloc(block->block_contents_size);
3910 if(!block->block_contents)
3912 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3913 block->block_contents_size, __FILE__, __LINE__);
3914 return(TNG_CRITICAL);
3917 /* Read the whole block into block_contents to be able to write it to
3918 * disk even if it cannot be interpreted. */
3919 if(fread(block->block_contents, block->block_contents_size, 1,
3920 tng_data->input_file) == 0)
3922 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3923 return(TNG_CRITICAL);
3926 /* FIXME: Does not check if the size of the contents matches the expected
3927 * size or if the contents can be read. */
3929 file_pos = (int64_t)ftello(tng_data->input_file) -
3930 (block->block_contents_size + block->header_contents_size);
3932 if(hash_mode == TNG_USE_HASH)
3934 tng_md5_hash_match_verify(block, &same_hash);
3935 if(same_hash != TNG_TRUE)
3937 fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %"PRId64" Hashes do not match. "
3939 file_pos, __FILE__, __LINE__);
3940 /* return(TNG_FAILURE); */
3944 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3946 tng_frame_set_particle_mapping_free(tng_data);
3948 if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
3950 tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
3952 /* FIXME: Should check the frame number instead of the file_pos, in case
3953 * frame sets are not in order */
3954 if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
3956 tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
3959 memcpy(&frame_set->first_frame, block->block_contents,
3960 sizeof(frame_set->first_frame));
3961 if(tng_data->input_endianness_swap_func_64)
3963 if(tng_data->input_endianness_swap_func_64(tng_data,
3964 &frame_set->first_frame)
3967 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3968 __FILE__, __LINE__);
3971 offset += sizeof(frame_set->first_frame);
3973 memcpy(&frame_set->n_frames, block->block_contents + offset,
3974 sizeof(frame_set->n_frames));
3975 if(tng_data->input_endianness_swap_func_64)
3977 if(tng_data->input_endianness_swap_func_64(tng_data,
3978 &frame_set->n_frames)
3981 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3982 __FILE__, __LINE__);
3985 offset += sizeof(frame_set->n_frames);
3987 if(tng_data->var_num_atoms_flag)
3989 prev_n_particles = frame_set->n_particles;
3990 frame_set->n_particles = 0;
3991 /* If the list of molecule counts has already been created assume that
3992 * it is of correct size. */
3993 if(!frame_set->molecule_cnt_list)
3995 frame_set->molecule_cnt_list =
3996 malloc(sizeof(int64_t) * tng_data->n_molecules);
3998 if(!frame_set->molecule_cnt_list)
4000 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
4001 sizeof(int64_t) * tng_data->n_molecules,
4002 __FILE__, __LINE__);
4003 return(TNG_CRITICAL);
4006 for(i = 0; i < tng_data->n_molecules; i++)
4008 memcpy(&frame_set->molecule_cnt_list[i],
4009 block->block_contents + offset,
4011 if(tng_data->input_endianness_swap_func_64)
4013 if(tng_data->input_endianness_swap_func_64(tng_data,
4014 &frame_set->molecule_cnt_list[i])
4017 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4018 __FILE__, __LINE__);
4021 offset += sizeof(int64_t);
4022 frame_set->n_particles += tng_data->molecules[i].n_atoms *
4023 frame_set->molecule_cnt_list[i];
4025 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
4027 /* FIXME: Particle dependent data memory management */
4031 memcpy(&frame_set->next_frame_set_file_pos,
4032 block->block_contents + offset,
4033 sizeof(frame_set->next_frame_set_file_pos));
4034 if(tng_data->input_endianness_swap_func_64)
4036 if(tng_data->input_endianness_swap_func_64(tng_data,
4037 &frame_set->next_frame_set_file_pos)
4040 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4041 __FILE__, __LINE__);
4044 offset += sizeof(frame_set->next_frame_set_file_pos);
4046 memcpy(&frame_set->prev_frame_set_file_pos,
4047 block->block_contents + offset,
4048 sizeof(frame_set->prev_frame_set_file_pos));
4049 if(tng_data->input_endianness_swap_func_64)
4051 if(tng_data->input_endianness_swap_func_64(tng_data,
4052 &frame_set->prev_frame_set_file_pos)
4055 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4056 __FILE__, __LINE__);
4059 offset += sizeof(frame_set->prev_frame_set_file_pos);
4061 memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
4062 block->block_contents + offset,
4063 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4064 if(tng_data->input_endianness_swap_func_64)
4066 if(tng_data->input_endianness_swap_func_64(tng_data,
4067 &frame_set->medium_stride_next_frame_set_file_pos)
4070 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4071 __FILE__, __LINE__);
4074 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4076 memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
4077 block->block_contents + offset,
4078 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4079 if(tng_data->input_endianness_swap_func_64)
4081 if(tng_data->input_endianness_swap_func_64(tng_data,
4082 &frame_set->medium_stride_prev_frame_set_file_pos)
4085 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4086 __FILE__, __LINE__);
4089 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4091 memcpy(&frame_set->long_stride_next_frame_set_file_pos,
4092 block->block_contents + offset,
4093 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4094 if(tng_data->input_endianness_swap_func_64)
4096 if(tng_data->input_endianness_swap_func_64(tng_data,
4097 &frame_set->long_stride_next_frame_set_file_pos)
4100 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4101 __FILE__, __LINE__);
4104 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4106 memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
4107 block->block_contents + offset,
4108 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4109 if(tng_data->input_endianness_swap_func_64)
4111 if(tng_data->input_endianness_swap_func_64(tng_data,
4112 &frame_set->long_stride_prev_frame_set_file_pos)
4115 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4116 __FILE__, __LINE__);
4119 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4121 if(block->block_version >= 3)
4123 memcpy(&frame_set->first_frame_time,
4124 block->block_contents + offset,
4125 sizeof(frame_set->first_frame_time));
4126 if(tng_data->input_endianness_swap_func_64)
4128 if(tng_data->input_endianness_swap_func_64(tng_data,
4129 (int64_t *)&frame_set->first_frame_time)
4132 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4133 __FILE__, __LINE__);
4136 offset += sizeof(frame_set->first_frame_time);
4138 memcpy(&tng_data->time_per_frame,
4139 block->block_contents + offset,
4140 sizeof(tng_data->time_per_frame));
4141 if(tng_data->input_endianness_swap_func_64)
4143 if(tng_data->input_endianness_swap_func_64(tng_data,
4144 (int64_t *)&tng_data->time_per_frame)
4147 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4148 __FILE__, __LINE__);
4154 frame_set->first_frame_time = -1;
4155 tng_data->time_per_frame = -1;
4158 /* If the output file and the input files are the same the number of
4159 * frames in the file are the same number as has just been read.
4160 * This is updated here to later on see if there have been new frames
4161 * added and thereby the frame set needs to be rewritten. */
4162 if(tng_data->output_file == tng_data->input_file)
4164 frame_set->n_written_frames = frame_set->n_frames;
4167 return(TNG_SUCCESS);
4170 /** Write tng_data->current_trajectory_frame_set to file
4171 * @param tng_data is a trajectory data container.
4172 * @param block is a general block container.
4173 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4174 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4175 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4176 * error has occured.
4178 static tng_function_status tng_frame_set_block_write
4179 (tng_trajectory_t tng_data,
4180 tng_gen_block_t block,
4181 const char hash_mode)
4186 unsigned int name_len;
4187 tng_trajectory_frame_set_t frame_set =
4188 &tng_data->current_trajectory_frame_set;
4190 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4192 return(TNG_CRITICAL);
4195 name_len = (int)strlen("TRAJECTORY FRAME SET");
4197 if(!block->name || strlen(block->name) < name_len)
4199 temp_name = realloc(block->name, name_len + 1);
4202 fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
4203 name_len+1, __FILE__, __LINE__);
4206 return(TNG_CRITICAL);
4208 block->name = temp_name;
4210 strcpy(block->name, "TRAJECTORY FRAME SET");
4211 block->id = TNG_TRAJECTORY_FRAME_SET;
4213 if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
4216 fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
4217 __FILE__, __LINE__);
4218 return(TNG_CRITICAL);
4221 if(block->block_contents)
4223 free(block->block_contents);
4225 block->block_contents = malloc(block->block_contents_size);
4226 if(!block->block_contents)
4228 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4229 block->block_contents_size, __FILE__, __LINE__);
4230 return(TNG_CRITICAL);
4233 memcpy(block->block_contents, &frame_set->first_frame,
4234 sizeof(frame_set->first_frame));
4235 if(tng_data->output_endianness_swap_func_64)
4237 if(tng_data->output_endianness_swap_func_64(tng_data,
4238 (int64_t *)block->header_contents+offset)
4241 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4242 __FILE__, __LINE__);
4245 offset += sizeof(frame_set->first_frame);
4247 memcpy(block->block_contents+offset, &frame_set->n_frames,
4248 sizeof(frame_set->n_frames));
4249 if(tng_data->output_endianness_swap_func_64)
4251 if(tng_data->output_endianness_swap_func_64(tng_data,
4252 (int64_t *)block->header_contents+offset)
4255 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4256 __FILE__, __LINE__);
4259 offset += sizeof(frame_set->n_frames);
4261 if(tng_data->var_num_atoms_flag)
4263 for(i = 0; i < tng_data->n_molecules; i++)
4265 memcpy(block->block_contents+offset,
4266 &frame_set->molecule_cnt_list[i],
4268 if(tng_data->output_endianness_swap_func_64)
4270 if(tng_data->output_endianness_swap_func_64(tng_data,
4271 (int64_t *)block->header_contents+offset)
4274 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4275 __FILE__, __LINE__);
4278 offset += sizeof(int64_t);
4283 memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
4284 sizeof(frame_set->next_frame_set_file_pos));
4285 if(tng_data->output_endianness_swap_func_64)
4287 if(tng_data->output_endianness_swap_func_64(tng_data,
4288 (int64_t *)block->header_contents+offset)
4291 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4292 __FILE__, __LINE__);
4295 offset += sizeof(frame_set->next_frame_set_file_pos);
4297 memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
4298 sizeof(frame_set->prev_frame_set_file_pos));
4299 if(tng_data->output_endianness_swap_func_64)
4301 if(tng_data->output_endianness_swap_func_64(tng_data,
4302 (int64_t *)block->header_contents+offset)
4305 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4306 __FILE__, __LINE__);
4309 offset += sizeof(frame_set->prev_frame_set_file_pos);
4311 memcpy(block->block_contents+offset,
4312 &frame_set->medium_stride_next_frame_set_file_pos,
4313 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4314 if(tng_data->output_endianness_swap_func_64)
4316 if(tng_data->output_endianness_swap_func_64(tng_data,
4317 (int64_t *)block->header_contents+offset)
4320 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4321 __FILE__, __LINE__);
4324 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4326 memcpy(block->block_contents+offset,
4327 &frame_set->medium_stride_prev_frame_set_file_pos,
4328 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4329 if(tng_data->output_endianness_swap_func_64)
4331 if(tng_data->output_endianness_swap_func_64(tng_data,
4332 (int64_t *)block->header_contents+offset)
4335 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4336 __FILE__, __LINE__);
4339 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4341 memcpy(block->block_contents+offset,
4342 &frame_set->long_stride_next_frame_set_file_pos,
4343 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4344 if(tng_data->output_endianness_swap_func_64)
4346 if(tng_data->output_endianness_swap_func_64(tng_data,
4347 (int64_t *)block->header_contents+offset)
4350 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4351 __FILE__, __LINE__);
4354 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4356 memcpy(block->block_contents+offset,
4357 &frame_set->long_stride_prev_frame_set_file_pos,
4358 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4359 if(tng_data->output_endianness_swap_func_64)
4361 if(tng_data->output_endianness_swap_func_64(tng_data,
4362 (int64_t *)block->header_contents+offset)
4365 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4366 __FILE__, __LINE__);
4369 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4371 memcpy(block->block_contents+offset,
4372 &frame_set->first_frame_time,
4373 sizeof(frame_set->first_frame_time));
4374 if(tng_data->output_endianness_swap_func_64)
4376 if(tng_data->output_endianness_swap_func_64(tng_data,
4377 (int64_t *)block->header_contents+offset)
4380 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4381 __FILE__, __LINE__);
4384 offset += sizeof(frame_set->first_frame_time);
4386 memcpy(block->block_contents+offset,
4387 &tng_data->time_per_frame,
4388 sizeof(tng_data->time_per_frame));
4389 if(tng_data->output_endianness_swap_func_64)
4391 if(tng_data->output_endianness_swap_func_64(tng_data,
4392 (int64_t *)block->header_contents+offset)
4395 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4396 __FILE__, __LINE__);
4400 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4402 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4403 tng_data->output_file_path, __FILE__, __LINE__);
4404 return(TNG_CRITICAL);
4407 if(fwrite(block->block_contents, block->block_contents_size, 1,
4408 tng_data->output_file) != 1)
4410 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4411 return(TNG_CRITICAL);
4414 return(TNG_SUCCESS);
4417 static tng_function_status tng_trajectory_mapping_block_len_calculate
4418 (const tng_trajectory_t tng_data,
4419 const int64_t n_particles,
4423 *len = sizeof(int64_t) * (2 + n_particles);
4425 return(TNG_SUCCESS);
4428 /** Read an atom mappings block (translating between real atom indexes and how
4429 * the atom info is written in this frame set).
4430 * @param tng_data is a trajectory data container.
4431 * @param block is a general block container.
4432 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4433 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
4434 * compared to the md5 hash of the read contents to ensure valid data.
4435 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4436 * error has occured.
4438 static tng_function_status tng_trajectory_mapping_block_read
4439 (tng_trajectory_t tng_data,
4440 tng_gen_block_t block,
4441 const char hash_mode)
4446 tng_trajectory_frame_set_t frame_set =
4447 &tng_data->current_trajectory_frame_set;
4449 tng_particle_mapping_t mapping, mappings;
4451 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
4453 return(TNG_CRITICAL);
4456 if(block->block_contents)
4458 free(block->block_contents);
4461 block->block_contents = malloc(block->block_contents_size);
4462 if(!block->block_contents)
4464 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4465 block->block_contents_size, __FILE__, __LINE__);
4466 return(TNG_CRITICAL);
4469 /* Read the whole block into block_contents to be able to write it to disk
4470 * even if it cannot be interpreted. */
4471 if(fread(block->block_contents, block->block_contents_size, 1,
4472 tng_data->input_file) == 0)
4474 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
4475 return(TNG_CRITICAL);
4478 /* FIXME: Does not check if the size of the contents matches the expected
4479 * size or if the contents can be read. */
4481 if(hash_mode == TNG_USE_HASH)
4483 tng_md5_hash_match_verify(block, &same_hash);
4484 if(same_hash != TNG_TRUE)
4486 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4488 __FILE__, __LINE__);
4489 /* return(TNG_FAILURE); */
4493 frame_set->n_mapping_blocks++;
4494 mappings = realloc(frame_set->mappings,
4495 sizeof(struct tng_particle_mapping) *
4496 frame_set->n_mapping_blocks);
4499 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4500 block->block_contents_size, __FILE__, __LINE__);
4501 free(frame_set->mappings);
4502 frame_set->mappings = 0;
4503 return(TNG_CRITICAL);
4505 frame_set->mappings = mappings;
4506 mapping = &mappings[frame_set->n_mapping_blocks - 1];
4509 memcpy(&mapping->num_first_particle, block->block_contents+offset,
4510 sizeof(mapping->num_first_particle));
4511 if(tng_data->input_endianness_swap_func_64)
4513 if(tng_data->input_endianness_swap_func_64(tng_data,
4514 &mapping->num_first_particle)
4517 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4518 __FILE__, __LINE__);
4521 offset += sizeof(mapping->num_first_particle);
4523 memcpy(&mapping->n_particles, block->block_contents+offset,
4524 sizeof(mapping->n_particles));
4525 if(tng_data->input_endianness_swap_func_64)
4527 if(tng_data->input_endianness_swap_func_64(tng_data,
4528 &mapping->n_particles)
4531 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4532 __FILE__, __LINE__);
4535 offset += sizeof(mapping->n_particles);
4537 mapping->real_particle_numbers = malloc(mapping->n_particles *
4539 if(!mapping->real_particle_numbers)
4541 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
4542 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
4543 return(TNG_CRITICAL);
4546 /* If the byte order needs to be swapped the data must be read one value at
4547 * a time and swapped */
4548 if(tng_data->input_endianness_swap_func_64)
4550 for(i = 0; i < mapping->n_particles; i++)
4552 memcpy(&mapping->real_particle_numbers[i],
4553 block->block_contents + offset,
4555 if(tng_data->input_endianness_swap_func_64(tng_data,
4556 &mapping->real_particle_numbers[i])
4559 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4560 __FILE__, __LINE__);
4562 offset += sizeof(int64_t);
4565 /* Otherwise the data can be read all at once */
4568 memcpy(mapping->real_particle_numbers, block->block_contents + offset,
4569 mapping->n_particles * sizeof(int64_t));
4573 return(TNG_SUCCESS);
4576 /** Write the atom mappings of the current trajectory frame set
4577 * @param tng_data is a trajectory data container.
4578 * @param block is a general block container.
4579 * @param mapping_block_nr is the index of the mapping block to write.
4580 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4581 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4582 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4583 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4585 static tng_function_status tng_trajectory_mapping_block_write
4586 (tng_trajectory_t tng_data,
4587 tng_gen_block_t block,
4588 int mapping_block_nr,
4589 const char hash_mode)
4593 unsigned int name_len;
4594 tng_particle_mapping_t mapping =
4595 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
4597 if(mapping_block_nr >=
4598 tng_data->current_trajectory_frame_set.n_mapping_blocks)
4600 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
4601 __FILE__, __LINE__);
4602 return(TNG_FAILURE);
4605 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4607 return(TNG_CRITICAL);
4610 name_len = (int)strlen("PARTICLE MAPPING");
4612 if(!block->name || strlen(block->name) < name_len)
4614 temp_name = realloc(block->name, name_len + 1);
4617 fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
4618 name_len+1, __FILE__, __LINE__);
4621 return(TNG_CRITICAL);
4623 block->name = temp_name;
4625 strcpy(block->name, "PARTICLE MAPPING");
4626 block->id = TNG_PARTICLE_MAPPING;
4628 if(tng_trajectory_mapping_block_len_calculate(tng_data,
4629 mapping->n_particles,
4630 &block->block_contents_size) !=
4633 fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4634 __FILE__, __LINE__);
4635 return(TNG_CRITICAL);
4638 if(block->block_contents)
4640 free(block->block_contents);
4642 block->block_contents = malloc(block->block_contents_size);
4643 if(!block->block_contents)
4645 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4646 block->block_contents_size, __FILE__, __LINE__);
4647 return(TNG_CRITICAL);
4650 memcpy(block->block_contents, &mapping->num_first_particle,
4651 sizeof(mapping->num_first_particle));
4652 if(tng_data->output_endianness_swap_func_64)
4654 if(tng_data->output_endianness_swap_func_64(tng_data,
4655 (int64_t *)block->header_contents+offset)
4658 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4659 __FILE__, __LINE__);
4662 offset += sizeof(mapping->num_first_particle);
4664 memcpy(block->block_contents+offset, &mapping->n_particles,
4665 sizeof(mapping->n_particles));
4666 if(tng_data->output_endianness_swap_func_64)
4668 if(tng_data->output_endianness_swap_func_64(tng_data,
4669 (int64_t *)block->header_contents+offset)
4672 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4673 __FILE__, __LINE__);
4676 offset += sizeof(mapping->n_particles);
4678 if(tng_data->output_endianness_swap_func_64)
4680 for(i = 0; i < mapping->n_particles; i++)
4682 memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
4684 if(tng_data->output_endianness_swap_func_64(tng_data,
4685 (int64_t *)block->header_contents+offset)
4688 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4689 __FILE__, __LINE__);
4691 offset += sizeof(int64_t);
4696 memcpy(block->block_contents+offset, mapping->real_particle_numbers,
4697 mapping->n_particles * sizeof(int64_t));
4701 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4703 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4704 tng_data->output_file_path, __FILE__, __LINE__);
4705 return(TNG_CRITICAL);
4708 if(fwrite(block->block_contents, block->block_contents_size, 1,
4709 tng_data->output_file) != 1)
4711 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4712 return(TNG_CRITICAL);
4715 return(TNG_SUCCESS);
4718 /** Prepare a block for storing particle data
4719 * @param tng_data is a trajectory data container.
4720 * @param block_type_flag specifies if this is a trajectory block or a
4721 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4722 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4723 * error has occured.
4725 static tng_function_status tng_particle_data_block_create
4726 (tng_trajectory_t tng_data,
4727 const char block_type_flag)
4729 tng_trajectory_frame_set_t frame_set =
4730 &tng_data->current_trajectory_frame_set;
4732 tng_particle_data_t data;
4734 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4736 frame_set->n_particle_data_blocks++;
4737 data = realloc(frame_set->tr_particle_data,
4738 sizeof(struct tng_particle_data) *
4739 frame_set->n_particle_data_blocks);
4742 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
4743 sizeof(struct tng_particle_data) *
4744 frame_set->n_particle_data_blocks,
4745 __FILE__, __LINE__);
4746 free(frame_set->tr_particle_data);
4747 frame_set->tr_particle_data = 0;
4748 return(TNG_CRITICAL);
4750 frame_set->tr_particle_data = data;
4754 tng_data->n_particle_data_blocks++;
4755 data = realloc(tng_data->non_tr_particle_data,
4756 sizeof(struct tng_particle_data) *
4757 tng_data->n_particle_data_blocks);
4760 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
4761 sizeof(struct tng_particle_data) *
4762 tng_data->n_particle_data_blocks,
4763 __FILE__, __LINE__);
4764 free(tng_data->non_tr_particle_data);
4765 tng_data->non_tr_particle_data = 0;
4766 return(TNG_CRITICAL);
4768 tng_data->non_tr_particle_data = data;
4771 return(TNG_SUCCESS);
4774 static tng_function_status tng_compress(tng_trajectory_t tng_data,
4775 tng_gen_block_t block,
4776 const int64_t n_frames,
4777 const int64_t n_particles,
4784 char *dest, *temp, *temp_data_contents;
4785 int64_t algo_find_n_frames, compressed_len, offset;
4789 if(block->id != TNG_TRAJ_POSITIONS &&
4790 block->id != TNG_TRAJ_VELOCITIES)
4792 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
4793 "TNG method. %s: %d\n", __FILE__, __LINE__);
4794 return(TNG_FAILURE);
4796 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4798 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
4799 return(TNG_FAILURE);
4802 if(n_frames <= 0 || n_particles <= 0)
4804 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
4805 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
4806 return(TNG_FAILURE);
4809 f_precision = 1/(float)tng_data->compression_precision;
4810 d_precision = 1/tng_data->compression_precision;
4812 compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
4813 temp_data_contents = malloc(compressed_len);
4814 if(!temp_data_contents)
4816 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4817 compressed_len, __FILE__, __LINE__);
4818 return(TNG_CRITICAL);
4821 memcpy(temp_data_contents, (char *)start_pos, compressed_len);
4823 if(block->id == TNG_TRAJ_POSITIONS)
4825 /* If there is only one frame in this frame set and there might be more
4826 * do not store the algorithm as the compression algorithm, but find
4827 * the best one without storing it */
4828 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4830 nalgo = tng_compress_nalgo();
4831 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4832 if(type == TNG_FLOAT_DATA)
4834 dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
4843 dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
4850 else if(!tng_data->compress_algo_pos)
4854 algo_find_n_frames = 5;
4858 algo_find_n_frames = n_frames;
4861 nalgo = tng_compress_nalgo();
4862 tng_data->compress_algo_pos=malloc(nalgo *
4863 sizeof *tng_data->compress_algo_pos);
4864 if(type == TNG_FLOAT_DATA)
4866 dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
4867 (int)algo_find_n_frames,
4873 if(algo_find_n_frames < n_frames)
4875 dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
4878 0, tng_data->compress_algo_pos,
4884 dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
4885 (int)algo_find_n_frames,
4891 if(algo_find_n_frames < n_frames)
4893 dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
4896 tng_data->compress_algo_pos,
4903 if(type == TNG_FLOAT_DATA)
4905 dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
4908 tng_data->compress_algo_pos, &new_len);
4912 dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
4915 tng_data->compress_algo_pos,
4920 else if(block->id == TNG_TRAJ_VELOCITIES)
4922 /* If there is only one frame in this frame set and there might be more
4923 * do not store the algorithm as the compression algorithm, but find
4924 * the best one without storing it */
4925 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4927 nalgo = tng_compress_nalgo();
4928 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_vel);
4929 if(type == TNG_FLOAT_DATA)
4931 dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
4940 dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
4947 else if(!tng_data->compress_algo_vel)
4951 algo_find_n_frames = 5;
4955 algo_find_n_frames = n_frames;
4958 nalgo = tng_compress_nalgo();
4959 tng_data->compress_algo_vel=malloc(nalgo *
4960 sizeof *tng_data->compress_algo_vel);
4962 if(type == TNG_FLOAT_DATA)
4964 dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
4965 (int)algo_find_n_frames,
4970 if(algo_find_n_frames < n_frames)
4972 dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
4975 0, tng_data->compress_algo_vel,
4981 dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
4982 (int)algo_find_n_frames,
4987 if(algo_find_n_frames < n_frames)
4989 dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
4992 0, tng_data->compress_algo_vel,
4999 if(type == TNG_FLOAT_DATA)
5001 dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
5010 dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
5021 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
5022 free(temp_data_contents);
5023 return(TNG_FAILURE);
5026 offset = (unsigned long)((char *)start_pos - block->block_contents);
5033 block->block_contents_size = new_len + offset;
5035 free(temp_data_contents);
5037 temp = realloc(block->block_contents, block->block_contents_size);
5040 free(block->block_contents);
5041 block->block_contents = 0;
5042 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5043 block->block_contents_size, __FILE__, __LINE__);
5044 return(TNG_CRITICAL);
5046 block->block_contents = temp;
5049 memcpy(temp + offset, dest, new_len);
5054 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
5055 return(TNG_FAILURE);
5058 return(TNG_SUCCESS);
5061 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
5062 tng_gen_block_t block,
5065 const int64_t uncompressed_len)
5067 char *temp, *temp_data_contents;
5068 int64_t compressed_len;
5075 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
5077 if(block->id != TNG_TRAJ_POSITIONS &&
5078 block->id != TNG_TRAJ_VELOCITIES)
5080 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
5082 return(TNG_FAILURE);
5084 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
5086 fprintf(stderr, "TNG library: Data type not supported.\n");
5087 return(TNG_FAILURE);
5090 compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
5091 temp_data_contents = malloc(compressed_len);
5092 if(!temp_data_contents)
5094 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5095 uncompressed_len, __FILE__, __LINE__);
5096 return(TNG_CRITICAL);
5099 memcpy(temp_data_contents, (char *)start_pos, compressed_len);
5101 if(type == TNG_FLOAT_DATA)
5103 f_dest = malloc(uncompressed_len);
5106 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5107 uncompressed_len, __FILE__, __LINE__);
5108 free(temp_data_contents);
5109 return(TNG_CRITICAL);
5111 result = tng_compress_uncompress_float(temp_data_contents, f_dest);
5115 d_dest = malloc(uncompressed_len);
5118 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5119 uncompressed_len, __FILE__, __LINE__);
5120 free(temp_data_contents);
5121 return(TNG_CRITICAL);
5123 result = tng_compress_uncompress(temp_data_contents, d_dest);
5128 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
5129 free(temp_data_contents);
5130 return(TNG_FAILURE);
5133 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
5135 block->block_contents_size = (int64_t)(uncompressed_len + offset);
5137 temp = realloc(block->block_contents, uncompressed_len + offset);
5140 free(block->block_contents);
5141 block->block_contents = 0;
5150 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5151 block->block_contents_size, __FILE__, __LINE__);
5152 free(temp_data_contents);
5153 return(TNG_CRITICAL);
5156 if(type == TNG_FLOAT_DATA)
5158 memcpy(temp + offset, f_dest, uncompressed_len);
5162 memcpy(temp + offset, d_dest, uncompressed_len);
5165 block->block_contents = temp;
5167 free(temp_data_contents);
5176 return(TNG_SUCCESS);
5180 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
5181 tng_gen_block_t block,
5182 void *start_pos, const int len)
5186 unsigned long max_len, stat, offset;
5189 max_len = compressBound(len);
5190 dest = malloc(max_len);
5193 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5194 max_len, __FILE__, __LINE__);
5195 return(TNG_CRITICAL);
5198 stat = compress(dest, &max_len, start_pos, len);
5199 if(stat != (unsigned long)Z_OK)
5202 if(stat == (unsigned long)Z_MEM_ERROR)
5204 fprintf(stderr, "TNG library: Not enough memory. ");
5206 else if(stat == (unsigned long)Z_BUF_ERROR)
5208 fprintf(stderr, "TNG library: Destination buffer too small. ");
5210 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
5211 return(TNG_FAILURE);
5214 offset = (char *)start_pos - block->block_contents;
5216 block->block_contents_size = max_len + offset;
5218 temp = realloc(block->block_contents, block->block_contents_size);
5221 free(block->block_contents);
5223 block->block_contents = 0;
5224 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5225 block->block_contents_size, __FILE__, __LINE__);
5226 return(TNG_CRITICAL);
5229 block->block_contents = temp;
5231 memcpy(temp + offset, dest, max_len);
5235 return(TNG_SUCCESS);
5238 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5239 tng_gen_block_t block,
5241 unsigned long uncompressed_len)
5249 offset = (char *)start_pos - (char *)block->block_contents;
5251 dest = malloc(uncompressed_len);
5254 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5255 uncompressed_len, __FILE__, __LINE__);
5256 return(TNG_CRITICAL);
5259 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
5260 block->block_contents_size - offset);
5265 if(stat == (unsigned long)Z_MEM_ERROR)
5267 fprintf(stderr, "TNG library: Not enough memory. ");
5269 else if(stat == (unsigned long)Z_BUF_ERROR)
5271 fprintf(stderr, "TNG library: Destination buffer too small. ");
5273 else if(stat == (unsigned long)Z_DATA_ERROR)
5275 fprintf(stderr, "TNG library: Data corrupt. ");
5277 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
5279 return(TNG_FAILURE);
5283 block->block_contents_size = uncompressed_len + offset;
5285 temp = realloc(block->block_contents, uncompressed_len + offset);
5288 free(block->block_contents);
5289 block->block_contents = 0;
5291 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5292 block->block_contents_size, __FILE__, __LINE__);
5293 return(TNG_CRITICAL);
5296 memcpy(temp + offset, dest, uncompressed_len);
5298 block->block_contents = temp;
5301 return(TNG_SUCCESS);
5305 /** Allocate memory for storing particle data.
5306 * The allocated block will be refered to by data->values.
5307 * @param tng_data is a trajectory data container.
5308 * @param data is the data struct, which will contain the allocated memory in
5310 * @param n_frames is the number of frames of data to store.
5311 * @param n_particles is the number of particles with data.
5312 * @param n_values_per_frame is the number of data values per particle and
5314 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5315 * error has occured.
5317 static tng_function_status tng_allocate_particle_data_mem
5318 (tng_trajectory_t tng_data,
5319 tng_particle_data_t data,
5321 int64_t stride_length,
5322 const int64_t n_particles,
5323 const int64_t n_values_per_frame)
5326 int64_t i, j, k, size, frame_alloc;
5329 if(n_particles == 0 || n_values_per_frame == 0)
5331 return(TNG_FAILURE);
5334 if(data->strings && data->datatype == TNG_CHAR_DATA)
5336 for(i = 0; i < data->n_frames; i++)
5338 for(j = 0; j < n_particles; j++)
5340 for(k = 0; k < data->n_values_per_frame; k++)
5342 if(data->strings[i][j][k])
5344 free(data->strings[i][j][k]);
5347 free(data->strings[i][j]);
5349 free(data->strings[i]);
5351 free(data->strings);
5353 data->n_frames = n_frames;
5354 n_frames = tng_max_i64(1, n_frames);
5355 data->stride_length = tng_max_i64(1, stride_length);
5356 data->n_values_per_frame = n_values_per_frame;
5357 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5359 if(data->datatype == TNG_CHAR_DATA)
5361 data->strings = malloc(sizeof(char ***) * frame_alloc);
5362 for(i = 0; i < frame_alloc; i++)
5364 data->strings[i] = malloc(sizeof(char **) *
5366 if(!data->strings[i])
5368 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
5369 sizeof(union data_values *) * n_particles,
5370 __FILE__, __LINE__);
5371 return(TNG_CRITICAL);
5373 for(j = 0; j < n_particles; j++)
5375 data->strings[i][j] = malloc(sizeof(char *) *
5376 n_values_per_frame);
5377 if(!data->strings[i][j])
5379 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
5380 sizeof(union data_values) * n_values_per_frame,
5381 __FILE__, __LINE__);
5382 return(TNG_CRITICAL);
5384 for(k = 0; k < n_values_per_frame; k++)
5386 data->strings[i][j][k] = 0;
5393 switch(data->datatype)
5396 size = sizeof(int64_t);
5398 case TNG_FLOAT_DATA:
5399 size = sizeof(float);
5401 case TNG_DOUBLE_DATA:
5403 size = sizeof(double);
5406 values = realloc(data->values,
5407 size * frame_alloc *
5408 n_particles * n_values_per_frame);
5411 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5412 size * frame_alloc *
5413 n_particles * n_values_per_frame,
5414 __FILE__, __LINE__);
5417 return(TNG_CRITICAL);
5419 data->values = values;
5421 return(TNG_SUCCESS);
5424 static tng_function_status tng_particle_data_find
5425 (tng_trajectory_t tng_data,
5427 tng_particle_data_t *data)
5429 int64_t block_index, i;
5430 tng_trajectory_frame_set_t frame_set = &tng_data->
5431 current_trajectory_frame_set;
5432 char block_type_flag;
5434 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5435 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5437 block_type_flag = TNG_TRAJECTORY_BLOCK;
5441 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5445 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5447 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
5449 *data = &frame_set->tr_particle_data[i];
5450 if((*data)->block_id == id)
5459 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
5461 *data = &tng_data->non_tr_particle_data[i];
5462 if((*data)->block_id == id)
5469 if(block_index == -1)
5471 return(TNG_FAILURE);
5473 return(TNG_SUCCESS);
5476 static tng_function_status tng_data_find
5477 (tng_trajectory_t tng_data,
5479 tng_non_particle_data_t *data)
5481 int64_t block_index, i;
5482 tng_trajectory_frame_set_t frame_set = &tng_data->
5483 current_trajectory_frame_set;
5484 char block_type_flag;
5486 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5487 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5489 block_type_flag = TNG_TRAJECTORY_BLOCK;
5493 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5497 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5499 for(i = 0; i < frame_set->n_data_blocks; i++)
5501 *data = &frame_set->tr_data[i];
5502 if((*data)->block_id == id)
5508 if(block_index == -1)
5510 for(i = 0; i < tng_data->n_data_blocks; i++)
5512 *data = &tng_data->non_tr_data[i];
5513 if((*data)->block_id == id)
5523 for(i = 0; i < tng_data->n_data_blocks; i++)
5525 *data = &tng_data->non_tr_data[i];
5526 if((*data)->block_id == id)
5533 if(block_index == -1)
5535 return(TNG_FAILURE);
5537 return(TNG_SUCCESS);
5540 static tng_function_status tng_data_block_len_calculate
5541 (const tng_trajectory_t tng_data,
5542 const tng_particle_data_t data,
5543 const tng_bool is_particle_data,
5544 const int64_t n_frames,
5545 const int64_t frame_step,
5546 const int64_t stride_length,
5547 const int64_t num_first_particle,
5548 const int64_t n_particles,
5549 const char dependency,
5550 int64_t *data_start_pos,
5555 char ***first_dim_values, **second_dim_values;
5560 return(TNG_SUCCESS);
5563 switch(data->datatype)
5569 size = sizeof(int64_t);
5571 case TNG_FLOAT_DATA:
5572 size = sizeof(float);
5574 case TNG_DOUBLE_DATA:
5576 size = sizeof(double);
5579 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5580 sizeof(data->codec_id);
5581 if(is_particle_data)
5583 *len += sizeof(num_first_particle) + sizeof(n_particles);
5586 if(stride_length > 1)
5588 *len += sizeof(data->first_frame_with_data) +
5589 sizeof(data->stride_length);
5592 if(data->codec_id != TNG_UNCOMPRESSED)
5594 *len += sizeof(data->compression_multiplier);
5597 if(dependency & TNG_FRAME_DEPENDENT)
5599 *len += sizeof(char);
5602 *data_start_pos = *len;
5604 if(data->datatype == TNG_CHAR_DATA)
5606 if(is_particle_data)
5608 for(i = 0; i < n_frames; i++)
5610 first_dim_values = data->strings[i];
5611 for(j = num_first_particle; j < num_first_particle + n_particles;
5614 second_dim_values = first_dim_values[j];
5615 for(k = 0; k < data->n_values_per_frame; k++)
5617 *len += strlen(second_dim_values[k]) + 1;
5624 for(i = 0; i < n_frames; i++)
5626 second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
5627 for(j = 0; j < data->n_values_per_frame; j++)
5629 *len += strlen(second_dim_values[j]) + 1;
5636 *len += size * frame_step * n_particles * data->n_values_per_frame;
5639 return(TNG_SUCCESS);
5642 /** Read the values of a particle data block
5643 * @param tng_data is a trajectory data container.
5644 * @param block is the block to store the data (should already contain
5645 * the block headers and the block contents).
5646 * @param offset is the reading offset to point at the place where the actual
5647 * values are stored, starting from the beginning of the block_contents. The
5648 * offset is changed during the reading.
5649 * @param datatype is the type of data of the data block (char, int, float or
5651 * @param num_first_particle is the number of the first particle in the data
5652 * block. This should be the same as in the corresponding particle mapping
5654 * @param n_particles is the number of particles in the data block. This should
5655 * be the same as in the corresponding particle mapping block.
5656 * @param first_frame_with_data is the frame number of the first frame with data
5657 * in this data block.
5658 * @param stride_length is the number of frames between each data entry.
5659 * @param n_frames is the number of frames in this data block.
5660 * @param n_values is the number of values per particle and frame stored in this
5662 * @param codec_id is the ID of the codec to compress the data.
5663 * @param multiplier is the multiplication factor applied to each data value
5664 * before compression. This factor is applied since some compression algorithms
5665 * work only on integers.
5666 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5667 * error has occured.
5669 static tng_function_status tng_particle_data_read
5670 (tng_trajectory_t tng_data,
5671 tng_gen_block_t block,
5673 const char datatype,
5674 const int64_t num_first_particle,
5675 const int64_t n_particles,
5676 const int64_t first_frame_with_data,
5677 const int64_t stride_length,
5679 const int64_t n_values,
5680 const int64_t codec_id,
5681 const double multiplier)
5683 int64_t i, j, k, tot_n_particles, n_frames_div;
5686 char ***first_dim_values, **second_dim_values;
5687 tng_particle_data_t data;
5688 tng_trajectory_frame_set_t frame_set =
5689 &tng_data->current_trajectory_frame_set;
5690 char block_type_flag;
5692 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5694 /* This must be caught early to avoid creating a data block if not necessary. */
5696 if(codec_id == TNG_GZIP_COMPRESSION)
5698 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
5700 return(TNG_FAILURE);
5710 size = sizeof(int64_t);
5712 case TNG_FLOAT_DATA:
5713 size = sizeof(float);
5715 case TNG_DOUBLE_DATA:
5717 size = sizeof(double);
5720 /* If the block does not exist, create it */
5721 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5723 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5725 block_type_flag = TNG_TRAJECTORY_BLOCK;
5729 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5732 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5735 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5736 __FILE__, __LINE__);
5737 return(TNG_CRITICAL);
5739 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5741 data = &frame_set->tr_particle_data[frame_set->
5742 n_particle_data_blocks - 1];
5746 data = &tng_data->non_tr_particle_data[tng_data->
5747 n_particle_data_blocks - 1];
5749 data->block_id = block->id;
5751 data->block_name = malloc(strlen(block->name) + 1);
5752 if(!data->block_name)
5754 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5755 (int)strlen(block->name)+1, __FILE__, __LINE__);
5756 return(TNG_CRITICAL);
5758 strcpy(data->block_name, block->name);
5760 data->datatype = datatype;
5763 /* FIXME: Memory leak from strings. */
5766 data->codec_id = codec_id;
5767 data->compression_multiplier = multiplier;
5768 data->last_retrieved_frame = -1;
5771 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5772 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5773 tng_data->var_num_atoms_flag)
5775 tot_n_particles = frame_set->n_particles;
5779 tot_n_particles = tng_data->n_particles;
5782 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5784 if(codec_id != TNG_UNCOMPRESSED)
5786 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5789 case TNG_XTC_COMPRESSION:
5790 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5792 case TNG_TNG_COMPRESSION:
5793 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5794 if(tng_uncompress(tng_data, block, datatype,
5795 block->block_contents + *offset,
5796 data_size) != TNG_SUCCESS)
5798 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5799 __FILE__, __LINE__);
5800 return(TNG_CRITICAL);
5802 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5805 case TNG_GZIP_COMPRESSION:
5806 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5807 if(tng_gzip_uncompress(tng_data, block,
5808 block->block_contents + *offset,
5809 data_size) != TNG_SUCCESS)
5811 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5813 return(TNG_CRITICAL);
5815 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5820 /* Allocate memory */
5821 if(!data->values || data->n_frames != n_frames ||
5822 data->n_values_per_frame != n_values)
5824 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5826 tot_n_particles, n_values) !=
5829 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5830 __FILE__, __LINE__);
5831 return(TNG_CRITICAL);
5835 data->first_frame_with_data = first_frame_with_data;
5837 if(datatype == TNG_CHAR_DATA)
5839 for(i = 0; i < n_frames_div; i++)
5841 first_dim_values = data->strings[i];
5842 for(j = num_first_particle; j < num_first_particle + n_particles;
5845 second_dim_values = first_dim_values[j];
5846 for(k = 0; k < n_values; k++)
5848 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5850 if(second_dim_values[k])
5852 free(second_dim_values[k]);
5854 second_dim_values[k] = malloc(len);
5855 if(!second_dim_values[k])
5857 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5858 len, __FILE__, __LINE__);
5859 return(TNG_CRITICAL);
5861 strncpy(second_dim_values[k],
5862 block->block_contents+*offset, len);
5870 memcpy((char *)data->values + n_frames_div * size * n_values *
5872 block->block_contents + *offset,
5873 block->block_contents_size - *offset);
5876 case TNG_FLOAT_DATA:
5877 if(tng_data->input_endianness_swap_func_32)
5879 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5881 if(tng_data->input_endianness_swap_func_32(tng_data,
5882 (int32_t *)((char *)data->values + i))
5885 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5886 __FILE__, __LINE__);
5892 case TNG_DOUBLE_DATA:
5893 if(tng_data->input_endianness_swap_func_64)
5895 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5897 if(tng_data->input_endianness_swap_func_64(tng_data,
5898 (int64_t *)((char *)data->values + i))
5901 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5902 __FILE__, __LINE__);
5911 return(TNG_SUCCESS);
5914 /** Write a particle data block
5915 * @param tng_data is a trajectory data container.
5916 * @param block is the block to store the data (should already contain
5917 * the block headers and the block contents).
5918 * @param block_index is the index number of the data block in the frame set.
5919 * @param mapping is the particle mapping that is relevant for the data block.
5920 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5921 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5922 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5923 * error has occured.
5925 static tng_function_status tng_particle_data_block_write
5926 (tng_trajectory_t tng_data,
5927 tng_gen_block_t block,
5928 const int64_t block_index,
5929 const tng_particle_mapping_t mapping,
5930 const char hash_mode)
5932 int64_t n_particles, num_first_particle, n_frames, stride_length;
5933 int64_t frame_step, data_start_pos;
5936 size_t len, offset = 0;
5937 char dependency, temp, *temp_name;
5939 char ***first_dim_values, **second_dim_values;
5940 tng_trajectory_frame_set_t frame_set;
5941 tng_function_status stat;
5943 tng_particle_data_t data;
5944 char block_type_flag;
5946 frame_set = &tng_data->current_trajectory_frame_set;
5948 /* If we have already started writing frame sets it is too late to write
5949 * non-trajectory data blocks */
5950 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5952 block_type_flag = TNG_TRAJECTORY_BLOCK;
5956 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5959 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5961 return(TNG_CRITICAL);
5964 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5966 data = &frame_set->tr_particle_data[block_index];
5968 /* If this data block has not had any data added in this frame set
5969 * do not write it. */
5970 if(data->first_frame_with_data < frame_set->first_frame)
5972 return(TNG_SUCCESS);
5975 stride_length = tng_max_i64(1, data->stride_length);
5979 data = &tng_data->non_tr_particle_data[block_index];
5983 switch(data->datatype)
5989 size = sizeof(int64_t);
5991 case TNG_FLOAT_DATA:
5992 size = sizeof(float);
5994 case TNG_DOUBLE_DATA:
5996 size = sizeof(double);
5999 len = strlen(data->block_name) + 1;
6001 if(!block->name || strlen(block->name) < len)
6003 temp_name = realloc(block->name, len);
6006 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n", len,
6007 __FILE__, __LINE__);
6010 return(TNG_CRITICAL);
6012 block->name = temp_name;
6014 strncpy(block->name, data->block_name, len);
6015 block->id = data->block_id;
6017 /* If writing frame independent data data->n_frames is 0, but n_frames
6018 is used for the loop writing the data (and reserving memory) and needs
6020 n_frames = tng_max_i64(1, data->n_frames);
6022 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6024 /* If the frame set is finished before writing the full number of frames
6025 make sure the data block is not longer than the frame set. */
6026 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6028 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6031 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6032 n_frames / stride_length;
6034 /* TNG compression will use compression precision to get integers from
6035 * floating point data. The compression multiplier stores that information
6036 * to be able to return the precision of the compressed data. */
6037 if(data->codec_id == TNG_TNG_COMPRESSION)
6039 data->compression_multiplier = tng_data->compression_precision;
6041 /* Uncompressed data blocks do not use compression multipliers at all.
6042 * GZip compression does not need it either. */
6043 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6045 data->compression_multiplier = 1.0;
6048 if(mapping && mapping->n_particles != 0)
6050 n_particles = mapping->n_particles;
6051 num_first_particle = mapping->num_first_particle;
6055 num_first_particle = 0;
6056 if(tng_data->var_num_atoms_flag)
6058 n_particles = frame_set->n_particles;
6062 n_particles = tng_data->n_particles;
6066 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6068 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6072 dependency = TNG_PARTICLE_DEPENDENT;
6075 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6076 frame_step, stride_length, num_first_particle,
6077 n_particles, dependency, &data_start_pos,
6078 &block->block_contents_size) != TNG_SUCCESS)
6080 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6081 __FILE__, __LINE__);
6082 return(TNG_CRITICAL);
6085 if(block->block_contents)
6087 free(block->block_contents);
6089 block->block_contents = malloc(block->block_contents_size);
6090 if(!block->block_contents)
6092 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6093 block->block_contents_size, __FILE__, __LINE__);
6094 return(TNG_CRITICAL);
6098 memcpy(block->block_contents, &data->datatype, sizeof(char));
6099 offset += sizeof(char);
6101 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6102 offset += sizeof(char);
6104 if(dependency & TNG_FRAME_DEPENDENT)
6106 if(stride_length > 1)
6114 memcpy(block->block_contents+offset, &temp, sizeof(char));
6115 offset += sizeof(char);
6118 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6119 sizeof(data->n_values_per_frame));
6120 if(tng_data->output_endianness_swap_func_64)
6122 if(tng_data->output_endianness_swap_func_64(tng_data,
6123 (int64_t *)block->header_contents+offset)
6126 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6127 __FILE__, __LINE__);
6130 offset += sizeof(data->n_values_per_frame);
6132 memcpy(block->block_contents+offset, &data->codec_id,
6133 sizeof(data->codec_id));
6134 if(tng_data->output_endianness_swap_func_64)
6136 if(tng_data->output_endianness_swap_func_64(tng_data,
6137 (int64_t *)block->header_contents+offset)
6140 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6141 __FILE__, __LINE__);
6144 offset += sizeof(data->codec_id);
6146 if(data->codec_id != TNG_UNCOMPRESSED)
6148 memcpy(block->block_contents+offset, &data->compression_multiplier,
6149 sizeof(data->compression_multiplier));
6150 if(tng_data->output_endianness_swap_func_64)
6152 if(tng_data->output_endianness_swap_func_64(tng_data,
6153 (int64_t *)block->header_contents+offset)
6156 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6157 __FILE__, __LINE__);
6160 offset += sizeof(data->compression_multiplier);
6163 if(data->n_frames > 0 && stride_length > 1)
6165 /* FIXME: first_frame_with_data is not reliably set */
6166 if(data->first_frame_with_data == 0)
6168 data->first_frame_with_data = frame_set->first_frame;
6170 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6171 sizeof(data->first_frame_with_data));
6172 if(tng_data->output_endianness_swap_func_64)
6174 if(tng_data->output_endianness_swap_func_64(tng_data,
6175 (int64_t *)block->header_contents+offset)
6178 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6179 __FILE__, __LINE__);
6182 offset += sizeof(data->first_frame_with_data);
6184 memcpy(block->block_contents+offset, &stride_length,
6185 sizeof(stride_length));
6186 if(tng_data->output_endianness_swap_func_64)
6188 if(tng_data->output_endianness_swap_func_64(tng_data,
6189 (int64_t *)block->header_contents+offset)
6192 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6193 __FILE__, __LINE__);
6196 offset += sizeof(stride_length);
6200 memcpy(block->block_contents+offset, &num_first_particle,
6201 sizeof(num_first_particle));
6202 if(tng_data->output_endianness_swap_func_64)
6204 if(tng_data->output_endianness_swap_func_64(tng_data,
6205 (int64_t *)block->header_contents+offset)
6208 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6209 __FILE__, __LINE__);
6212 offset += sizeof(num_first_particle);
6214 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
6215 if(tng_data->output_endianness_swap_func_64)
6217 if(tng_data->output_endianness_swap_func_64(tng_data,
6218 (int64_t *)block->header_contents+offset)
6221 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6222 __FILE__, __LINE__);
6225 offset += sizeof(n_particles);
6227 if(data->datatype == TNG_CHAR_DATA)
6231 for(i = 0; i < frame_step; i++)
6233 first_dim_values = data->strings[i];
6234 for(j = num_first_particle; j < num_first_particle + n_particles;
6237 second_dim_values = first_dim_values[j];
6238 for(k = 0; k < data->n_values_per_frame; k++)
6240 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6241 strncpy(block->block_contents+offset,
6242 second_dim_values[k], len);
6249 else if(data->values)
6251 memcpy(block->block_contents + offset, data->values,
6252 block->block_contents_size - offset);
6254 switch(data->datatype)
6256 case TNG_FLOAT_DATA:
6257 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6258 data->codec_id == TNG_TNG_COMPRESSION)
6260 if(tng_data->input_endianness_swap_func_32)
6262 for(i = offset; i < block->block_contents_size; i+=size)
6264 if(tng_data->input_endianness_swap_func_32(tng_data,
6265 (int32_t *)(block->block_contents + i))
6268 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6269 __FILE__, __LINE__);
6276 multiplier = data->compression_multiplier;
6277 if(fabs(multiplier - 1.0) > 0.00001 ||
6278 tng_data->input_endianness_swap_func_32)
6280 for(i = offset; i < block->block_contents_size; i+=size)
6282 *(float *)(block->block_contents + i) *= (float)multiplier;
6283 if(tng_data->input_endianness_swap_func_32 &&
6284 tng_data->input_endianness_swap_func_32(tng_data,
6285 (int32_t *)(block->block_contents + i))
6288 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6289 __FILE__, __LINE__);
6296 if(tng_data->input_endianness_swap_func_64)
6298 for(i = offset; i < block->block_contents_size; i+=size)
6300 if(tng_data->input_endianness_swap_func_64(tng_data,
6301 (int64_t *)(block->block_contents + i))
6304 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6305 __FILE__, __LINE__);
6310 case TNG_DOUBLE_DATA:
6311 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6312 data->codec_id == TNG_TNG_COMPRESSION)
6314 if(tng_data->input_endianness_swap_func_64)
6316 for(i = offset; i < block->block_contents_size; i+=size)
6318 if(tng_data->input_endianness_swap_func_64(tng_data,
6319 (int64_t *)(block->block_contents + i))
6322 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6323 __FILE__, __LINE__);
6330 multiplier = data->compression_multiplier;
6331 if(fabs(multiplier - 1.0) > 0.00001 ||
6332 tng_data->input_endianness_swap_func_64)
6334 for(i = offset; i < block->block_contents_size; i+=size)
6336 *(double *)(block->block_contents + i) *= multiplier;
6337 if(tng_data->input_endianness_swap_func_64 &&
6338 tng_data->input_endianness_swap_func_64(tng_data,
6339 (int64_t *)(block->block_contents + i))
6342 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6343 __FILE__, __LINE__);
6355 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6358 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6359 frame_set->n_unwritten_frames = 0;
6361 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6363 switch(data->codec_id)
6365 case TNG_XTC_COMPRESSION:
6366 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6367 data->codec_id = TNG_UNCOMPRESSED;
6369 case TNG_TNG_COMPRESSION:
6370 stat = tng_compress(tng_data, block, frame_step,
6371 n_particles, data->datatype,
6372 block->block_contents + data_start_pos);
6373 if(stat != TNG_SUCCESS)
6375 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6376 __FILE__, __LINE__);
6377 if(stat == TNG_CRITICAL)
6379 return(TNG_CRITICAL);
6381 /* Set the data again, but with no compression (to write only
6382 * the relevant data) */
6383 data->codec_id = TNG_UNCOMPRESSED;
6384 stat = tng_particle_data_block_write(tng_data, block,
6385 block_index, mapping,
6391 case TNG_GZIP_COMPRESSION:
6392 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6393 stat = tng_gzip_compress(tng_data, block,
6394 block->block_contents + data_start_pos,
6395 block->block_contents_size - data_start_pos);
6396 if(stat != TNG_SUCCESS)
6398 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6400 if(stat == TNG_CRITICAL)
6402 return(TNG_CRITICAL);
6404 /* Set the data again, but with no compression (to write only
6405 * the relevant data) */
6406 data->codec_id = TNG_UNCOMPRESSED;
6407 stat = tng_particle_data_block_write(tng_data, block,
6408 block_index, mapping,
6412 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6418 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6420 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6421 tng_data->output_file_path, __FILE__, __LINE__);
6422 return(TNG_CRITICAL);
6425 if(fwrite(block->block_contents, block->block_contents_size, 1,
6426 tng_data->output_file) != 1)
6428 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6430 return(TNG_CRITICAL);
6433 return(TNG_SUCCESS);
6437 /** Create a non-particle data block
6438 * @param tng_data is a trajectory data container.
6439 * @param block_type_flag specifies if this is a trajectory block or a
6440 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6441 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6442 * error has occured.
6444 static tng_function_status tng_data_block_create
6445 (tng_trajectory_t tng_data,
6446 const char block_type_flag)
6448 tng_trajectory_frame_set_t frame_set =
6449 &tng_data->current_trajectory_frame_set;
6451 tng_non_particle_data_t data;
6453 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6455 frame_set->n_data_blocks++;
6456 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6457 frame_set->n_data_blocks);
6460 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
6461 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6462 __FILE__, __LINE__);
6463 free(frame_set->tr_data);
6464 frame_set->tr_data = 0;
6465 return(TNG_CRITICAL);
6467 frame_set->tr_data = data;
6471 tng_data->n_data_blocks++;
6472 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6473 tng_data->n_data_blocks);
6476 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
6477 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6478 __FILE__, __LINE__);
6479 free(tng_data->non_tr_data);
6480 tng_data->non_tr_data = 0;
6481 return(TNG_CRITICAL);
6483 tng_data->non_tr_data = data;
6486 return(TNG_SUCCESS);
6490 /** Allocate memory for storing non-particle data.
6491 * The allocated block will be refered to by data->values.
6492 * @param tng_data is a trajectory data container.
6493 * @param data is the data struct, which will contain the allocated memory in
6495 * @param n_frames is the number of frames of data to store.
6496 * @param n_values_per_frame is the number of data values per frame.
6497 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6498 * error has occured.
6500 static tng_function_status tng_allocate_data_mem
6501 (tng_trajectory_t tng_data,
6502 tng_non_particle_data_t data,
6504 int64_t stride_length,
6505 const int64_t n_values_per_frame)
6508 int64_t i, j, size, frame_alloc;
6511 if(n_values_per_frame == 0)
6513 return(TNG_FAILURE);
6516 if(data->strings && data->datatype == TNG_CHAR_DATA)
6518 for(i = 0; i < data->n_frames; i++)
6520 for(j = 0; j < data->n_values_per_frame; j++)
6522 if(data->strings[i][j])
6524 free(data->strings[i][j]);
6525 data->strings[i][j] = 0;
6528 free(data->strings[i]);
6529 data->strings[i] = 0;
6531 free(data->strings);
6533 data->n_frames = n_frames;
6534 data->stride_length = tng_max_i64(1, stride_length);
6535 n_frames = tng_max_i64(1, n_frames);
6536 data->n_values_per_frame = n_values_per_frame;
6537 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6539 if(data->datatype == TNG_CHAR_DATA)
6541 data->strings = malloc(sizeof(char **) * frame_alloc);
6542 for(i = 0; i < frame_alloc; i++)
6544 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6545 if(!data->strings[i])
6547 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6549 __FILE__, __LINE__);
6550 return(TNG_CRITICAL);
6552 for(j = 0; j < n_values_per_frame; j++)
6554 data->strings[i][j] = 0;
6560 switch(data->datatype)
6563 size = sizeof(int64_t);
6565 case TNG_FLOAT_DATA:
6566 size = sizeof(float);
6568 case TNG_DOUBLE_DATA:
6570 size = sizeof(double);
6573 values = realloc(data->values,
6574 size * frame_alloc *
6575 n_values_per_frame);
6578 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6579 size * frame_alloc *
6581 __FILE__, __LINE__);
6584 return(TNG_CRITICAL);
6586 data->values = values;
6589 return(TNG_SUCCESS);
6592 /** Read the values of a non-particle data block
6593 * @param tng_data is a trajectory data container.
6594 * @param block is the block to store the data (should already contain
6595 * the block headers and the block contents).
6596 * @param offset is the reading offset to point at the place where the actual
6597 * values are stored, starting from the beginning of the block_contents. The
6598 * offset is changed during the reading.
6599 * @param datatype is the type of data of the data block (char, int, float or
6601 * @param first_frame_with_data is the frame number of the first frame with data
6602 * in this data block.
6603 * @param stride_length is the number of frames between each data entry.
6604 * @param n_frames is the number of frames in this data block.
6605 * @param n_values is the number of values per frame stored in this data block.
6606 * @param codec_id is the ID of the codec to compress the data.
6607 * @param multiplier is the multiplication factor applied to each data value
6608 * before compression. This factor is applied since some compression algorithms
6609 * work only on integers.
6610 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6611 * error has occured.
6613 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6614 tng_gen_block_t block,
6616 const char datatype,
6617 const int64_t first_frame_with_data,
6618 const int64_t stride_length,
6620 const int64_t n_values,
6621 const int64_t codec_id,
6622 const double multiplier)
6624 int64_t i, j, n_frames_div;
6629 tng_non_particle_data_t data;
6630 tng_trajectory_frame_set_t frame_set =
6631 &tng_data->current_trajectory_frame_set;
6632 char block_type_flag;
6634 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6636 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6638 /* This must be caught early to avoid creating a data block if not necessary. */
6640 if(codec_id == TNG_GZIP_COMPRESSION)
6642 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
6644 return(TNG_FAILURE);
6654 size = sizeof(int64_t);
6656 case TNG_FLOAT_DATA:
6657 size = sizeof(float);
6659 case TNG_DOUBLE_DATA:
6661 size = sizeof(double);
6664 /* If the block does not exist, create it */
6665 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6667 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6669 block_type_flag = TNG_TRAJECTORY_BLOCK;
6673 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6676 if(tng_data_block_create(tng_data, block_type_flag) !=
6679 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6680 __FILE__, __LINE__);
6681 return(TNG_CRITICAL);
6683 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6685 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6689 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6691 data->block_id = block->id;
6693 data->block_name = malloc(strlen(block->name) + 1);
6694 if(!data->block_name)
6696 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6697 (int)strlen(block->name)+1, __FILE__, __LINE__);
6698 return(TNG_CRITICAL);
6700 strcpy(data->block_name, block->name);
6702 data->datatype = datatype;
6705 /* FIXME: Memory leak from strings. */
6708 data->codec_id = codec_id;
6709 data->compression_multiplier = multiplier;
6710 data->last_retrieved_frame = -1;
6713 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6715 if(codec_id != TNG_UNCOMPRESSED)
6720 case TNG_GZIP_COMPRESSION:
6721 data_size = n_frames_div * size * n_values;
6722 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6723 if(tng_gzip_uncompress(tng_data, block,
6724 block->block_contents + *offset,
6725 data_size) != TNG_SUCCESS)
6727 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6729 return(TNG_CRITICAL);
6731 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6737 /* Allocate memory */
6738 if(!data->values || data->n_frames != n_frames ||
6739 data->n_values_per_frame != n_values)
6741 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6745 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6746 __FILE__, __LINE__);
6747 return(TNG_CRITICAL);
6751 data->first_frame_with_data = first_frame_with_data;
6753 if(datatype == TNG_CHAR_DATA)
6755 for(i = 0; i < n_frames_div; i++)
6757 for(j = 0; j < n_values; j++)
6759 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6761 if(data->strings[i][j])
6763 free(data->strings[i][j]);
6765 data->strings[i][j] = malloc(len);
6766 if(!data->strings[i][j])
6768 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6769 len, __FILE__, __LINE__);
6770 return(TNG_CRITICAL);
6772 strncpy(data->strings[i][j], block->block_contents+*offset,
6780 memcpy(data->values, block->block_contents + *offset,
6781 block->block_contents_size - *offset);
6784 case TNG_FLOAT_DATA:
6785 if(tng_data->input_endianness_swap_func_32)
6787 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6789 if(tng_data->input_endianness_swap_func_32(tng_data,
6790 (int32_t *)((char *)data->values + i))
6793 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6794 __FILE__, __LINE__);
6800 case TNG_DOUBLE_DATA:
6801 if(tng_data->input_endianness_swap_func_64)
6803 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6805 if(tng_data->input_endianness_swap_func_64(tng_data,
6806 (int64_t *)((char *)data->values + i))
6809 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6810 __FILE__, __LINE__);
6819 return(TNG_SUCCESS);
6822 /** Write a non-particle data block
6823 * @param tng_data is a trajectory data container.
6824 * @param block is the block to store the data (should already contain
6825 * the block headers and the block contents).
6826 * @param block_index is the index number of the data block in the frame set.
6827 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6828 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6829 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6830 * error has occured.
6832 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6833 tng_gen_block_t block,
6834 const int64_t block_index,
6835 const char hash_mode)
6837 int64_t n_frames, stride_length, frame_step, data_start_pos;
6839 int offset = 0, size;
6842 tng_function_status stat;
6844 char temp, dependency, *temp_name;
6846 tng_trajectory_frame_set_t frame_set =
6847 &tng_data->current_trajectory_frame_set;
6849 tng_non_particle_data_t data;
6850 char block_type_flag;
6852 /* If we have already started writing frame sets it is too late to write
6853 * non-trajectory data blocks */
6854 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6856 block_type_flag = TNG_TRAJECTORY_BLOCK;
6860 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6863 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6865 return(TNG_CRITICAL);
6868 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6870 data = &frame_set->tr_data[block_index];
6872 /* If this data block has not had any data added in this frame set
6873 * do not write it. */
6874 if(data->first_frame_with_data < frame_set->first_frame)
6876 return(TNG_SUCCESS);
6879 stride_length = tng_max_i64(1, data->stride_length);
6883 data = &tng_data->non_tr_data[block_index];
6887 switch(data->datatype)
6893 size = sizeof(int64_t);
6895 case TNG_FLOAT_DATA:
6896 size = sizeof(float);
6898 case TNG_DOUBLE_DATA:
6900 size = sizeof(double);
6903 len = (unsigned int)strlen(data->block_name) + 1;
6905 if(!block->name || strlen(block->name) < len)
6907 temp_name = realloc(block->name, len);
6910 fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n", len+1,
6911 __FILE__, __LINE__);
6914 return(TNG_CRITICAL);
6916 block->name = temp_name;
6918 strncpy(block->name, data->block_name, len);
6919 block->id = data->block_id;
6921 /* If writing frame independent data data->n_frames is 0, but n_frames
6922 is used for the loop writing the data (and reserving memory) and needs
6924 n_frames = tng_max_i64(1, data->n_frames);
6926 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6928 /* If the frame set is finished before writing the full number of frames
6929 make sure the data block is not longer than the frame set. */
6930 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6932 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6935 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6936 n_frames / stride_length;
6938 /* TNG compression will use compression precision to get integers from
6939 * floating point data. The compression multiplier stores that information
6940 * to be able to return the precision of the compressed data. */
6941 if(data->codec_id == TNG_TNG_COMPRESSION)
6943 data->compression_multiplier = tng_data->compression_precision;
6945 /* Uncompressed data blocks do not use compression multipliers at all.
6946 * GZip compression does not need it either. */
6947 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6949 data->compression_multiplier = 1.0;
6952 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6954 dependency = TNG_FRAME_DEPENDENT;
6961 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6962 frame_step, stride_length, 0,
6963 1, dependency, &data_start_pos,
6964 &block->block_contents_size) != TNG_SUCCESS)
6966 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6967 __FILE__, __LINE__);
6968 return(TNG_CRITICAL);
6971 if(block->block_contents)
6973 free(block->block_contents);
6975 block->block_contents = malloc(block->block_contents_size);
6976 if(!block->block_contents)
6978 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6979 block->block_contents_size, __FILE__, __LINE__);
6980 return(TNG_CRITICAL);
6984 memcpy(block->block_contents, &data->datatype, sizeof(char));
6985 offset += sizeof(char);
6987 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6988 offset += sizeof(char);
6990 if(dependency & TNG_FRAME_DEPENDENT)
6992 if(stride_length > 1)
7000 memcpy(block->block_contents+offset, &temp, sizeof(char));
7001 offset += sizeof(char);
7004 memcpy(block->block_contents+offset, &data->n_values_per_frame,
7005 sizeof(data->n_values_per_frame));
7006 if(tng_data->output_endianness_swap_func_64)
7008 if(tng_data->output_endianness_swap_func_64(tng_data,
7009 (int64_t *)block->header_contents+offset)
7012 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7013 __FILE__, __LINE__);
7016 offset += sizeof(data->n_values_per_frame);
7018 memcpy(block->block_contents+offset, &data->codec_id,
7019 sizeof(data->codec_id));
7020 if(tng_data->output_endianness_swap_func_64)
7022 if(tng_data->output_endianness_swap_func_64(tng_data,
7023 (int64_t *)block->header_contents+offset)
7026 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7027 __FILE__, __LINE__);
7030 offset += sizeof(data->codec_id);
7032 if(data->codec_id != TNG_UNCOMPRESSED)
7034 memcpy(block->block_contents+offset, &data->compression_multiplier,
7035 sizeof(data->compression_multiplier));
7036 if(tng_data->output_endianness_swap_func_64)
7038 if(tng_data->output_endianness_swap_func_64(tng_data,
7039 (int64_t *)block->header_contents+offset)
7042 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7043 __FILE__, __LINE__);
7046 offset += sizeof(data->compression_multiplier);
7049 if(data->n_frames > 0 && stride_length > 1)
7051 /* FIXME: first_frame_with_data is not reliably set */
7052 if(data->first_frame_with_data == 0)
7054 data->first_frame_with_data = frame_set->first_frame;
7056 memcpy(block->block_contents+offset, &data->first_frame_with_data,
7057 sizeof(data->first_frame_with_data));
7058 if(tng_data->output_endianness_swap_func_64)
7060 if(tng_data->output_endianness_swap_func_64(tng_data,
7061 (int64_t *)block->header_contents+offset)
7064 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7065 __FILE__, __LINE__);
7068 offset += sizeof(data->first_frame_with_data);
7070 memcpy(block->block_contents+offset, &stride_length,
7071 sizeof(data->stride_length));
7072 if(tng_data->output_endianness_swap_func_64)
7074 if(tng_data->output_endianness_swap_func_64(tng_data,
7075 (int64_t *)block->header_contents+offset)
7078 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7079 __FILE__, __LINE__);
7082 offset += sizeof(data->stride_length);
7085 if(data->datatype == TNG_CHAR_DATA)
7089 for(i = 0; i < frame_step; i++)
7091 for(j = 0; j < data->n_values_per_frame; j++)
7093 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7094 strncpy(block->block_contents+offset, data->strings[i][j],
7101 else if(data->values)
7103 memcpy(block->block_contents + offset, data->values,
7104 block->block_contents_size - offset);
7105 switch(data->datatype)
7107 case TNG_FLOAT_DATA:
7108 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7109 data->codec_id == TNG_TNG_COMPRESSION)
7111 if(tng_data->input_endianness_swap_func_32)
7113 for(i = offset; i < block->block_contents_size; i+=size)
7115 if(tng_data->input_endianness_swap_func_32(tng_data,
7116 (int32_t *)(block->block_contents + i))
7119 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7120 __FILE__, __LINE__);
7127 multiplier = data->compression_multiplier;
7128 if(fabs(multiplier - 1.0) > 0.00001 ||
7129 tng_data->input_endianness_swap_func_32)
7131 for(i = offset; block->block_contents_size; i+=size)
7133 *(float *)(block->block_contents + i) *= (float)multiplier;
7134 if(tng_data->input_endianness_swap_func_32 &&
7135 tng_data->input_endianness_swap_func_32(tng_data,
7136 (int32_t *)(block->block_contents + i))
7139 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7140 __FILE__, __LINE__);
7147 if(tng_data->input_endianness_swap_func_64)
7149 for(i = offset; i < block->block_contents_size; i+=size)
7151 if(tng_data->input_endianness_swap_func_64(tng_data,
7152 (int64_t *)(block->block_contents + i))
7155 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7156 __FILE__, __LINE__);
7161 case TNG_DOUBLE_DATA:
7162 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7163 data->codec_id == TNG_TNG_COMPRESSION)
7165 if(tng_data->input_endianness_swap_func_64)
7167 for(i = offset; i < block->block_contents_size; i+=size)
7169 if(tng_data->input_endianness_swap_func_64(tng_data,
7170 (int64_t *)(block->block_contents + i))
7173 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7174 __FILE__, __LINE__);
7181 multiplier = data->compression_multiplier;
7182 if(fabs(multiplier - 1.0) > 0.00001 ||
7183 tng_data->input_endianness_swap_func_64)
7185 for(i = offset; i < block->block_contents_size; i+=size)
7187 *(double *)(block->block_contents + i) *= multiplier;
7188 if(tng_data->input_endianness_swap_func_64 &&
7189 tng_data->input_endianness_swap_func_64(tng_data,
7190 (int64_t *)(block->block_contents + i))
7193 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7194 __FILE__, __LINE__);
7206 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7209 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7210 frame_set->n_unwritten_frames = 0;
7212 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7214 switch(data->codec_id)
7217 case TNG_GZIP_COMPRESSION:
7218 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7219 stat = tng_gzip_compress(tng_data, block,
7220 block->block_contents + data_start_pos,
7221 block->block_contents_size - data_start_pos);
7222 if(stat != TNG_SUCCESS)
7224 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7226 if(stat == TNG_CRITICAL)
7228 return(TNG_CRITICAL);
7230 data->codec_id = TNG_UNCOMPRESSED;
7232 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7238 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7240 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7241 tng_data->output_file_path, __FILE__, __LINE__);
7242 return(TNG_CRITICAL);
7245 if(fwrite(block->block_contents, block->block_contents_size, 1,
7246 tng_data->output_file) != 1)
7248 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7249 __FILE__, __LINE__);
7250 return(TNG_CRITICAL);
7253 return(TNG_SUCCESS);
7256 /** Read the meta information of a data block (particle or non-particle data).
7257 * @param tng_data is a trajectory data container.
7258 * @param block is the block to store the data (should already contain
7259 * the block headers).
7260 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7261 * error has occured.
7263 static tng_function_status tng_data_block_meta_information_read
7264 (tng_trajectory_t tng_data,
7265 tng_gen_block_t block,
7272 int64_t *first_frame_with_data,
7273 int64_t *stride_length,
7275 int64_t *num_first_particle,
7276 int64_t *block_n_particles,
7282 if(block->block_contents)
7284 contents = block->block_contents;
7288 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7289 contents = malloc(meta_size);
7292 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7293 meta_size, __FILE__, __LINE__);
7296 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7298 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7300 return(TNG_CRITICAL);
7304 memcpy(datatype, contents+*offset,
7306 *offset += sizeof(*datatype);
7308 memcpy(dependency, contents+*offset,
7309 sizeof(*dependency));
7310 *offset += sizeof(*dependency);
7312 if(*dependency & TNG_FRAME_DEPENDENT)
7314 memcpy(sparse_data, contents+*offset,
7315 sizeof(*sparse_data));
7316 *offset += sizeof(*sparse_data);
7319 memcpy(n_values, contents+*offset,
7321 if(tng_data->input_endianness_swap_func_64)
7323 if(tng_data->input_endianness_swap_func_64(tng_data,
7327 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7328 __FILE__, __LINE__);
7331 *offset += sizeof(*n_values);
7333 memcpy(codec_id, contents+*offset,
7335 if(tng_data->input_endianness_swap_func_64)
7337 if(tng_data->input_endianness_swap_func_64(tng_data,
7341 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7342 __FILE__, __LINE__);
7345 *offset += sizeof(*codec_id);
7347 if(*codec_id != TNG_UNCOMPRESSED)
7349 memcpy(multiplier, contents+*offset,
7350 sizeof(*multiplier));
7351 if(tng_data->input_endianness_swap_func_64)
7353 if(tng_data->input_endianness_swap_func_64(tng_data,
7354 (int64_t *) multiplier)
7357 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7358 __FILE__, __LINE__);
7361 *offset += sizeof(*multiplier);
7368 if(*dependency & TNG_FRAME_DEPENDENT)
7372 memcpy(first_frame_with_data, contents+*offset,
7373 sizeof(*first_frame_with_data));
7374 if(tng_data->input_endianness_swap_func_64)
7376 if(tng_data->input_endianness_swap_func_64(tng_data,
7377 first_frame_with_data)
7380 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7381 __FILE__, __LINE__);
7384 *offset += sizeof(*first_frame_with_data);
7386 memcpy(stride_length, contents+*offset,
7387 sizeof(*stride_length));
7388 if(tng_data->input_endianness_swap_func_64)
7390 if(tng_data->input_endianness_swap_func_64(tng_data,
7394 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7395 __FILE__, __LINE__);
7398 *offset += sizeof(*stride_length);
7399 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7400 (*first_frame_with_data -
7401 tng_data->current_trajectory_frame_set.first_frame);
7405 *first_frame_with_data = 0;
7407 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7412 *first_frame_with_data = 0;
7417 if (*dependency & TNG_PARTICLE_DEPENDENT)
7419 memcpy(num_first_particle, contents+*offset,
7420 sizeof(*num_first_particle));
7421 if(tng_data->input_endianness_swap_func_64)
7423 if(tng_data->input_endianness_swap_func_64(tng_data,
7427 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7428 __FILE__, __LINE__);
7431 *offset += sizeof(*num_first_particle);
7433 memcpy(block_n_particles, contents+*offset,
7434 sizeof(*block_n_particles));
7435 if(tng_data->input_endianness_swap_func_64)
7437 if(tng_data->input_endianness_swap_func_64(tng_data,
7441 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7442 __FILE__, __LINE__);
7445 *offset += sizeof(*block_n_particles);
7448 if(!block->block_contents)
7452 return(TNG_SUCCESS);
7455 /** Read the contents of a data block (particle or non-particle data).
7456 * @param tng_data is a trajectory data container.
7457 * @param block is the block to store the data (should already contain
7458 * the block headers).
7459 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7460 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7461 * compared to the md5 hash of the read contents to ensure valid data.
7462 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7463 * error has occured.
7465 static tng_function_status tng_data_block_contents_read
7466 (tng_trajectory_t tng_data,
7467 tng_gen_block_t block,
7468 const char hash_mode)
7470 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7471 int64_t stride_length, block_n_particles, num_first_particle;
7473 char datatype, dependency, sparse_data;
7477 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7479 return(TNG_CRITICAL);
7482 if(block->block_contents)
7484 free(block->block_contents);
7487 block->block_contents = malloc(block->block_contents_size);
7488 if(!block->block_contents)
7490 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7491 block->block_contents_size, __FILE__, __LINE__);
7492 return(TNG_CRITICAL);
7495 /* Read the whole block into block_contents to be able to write it to
7496 * disk even if it cannot be interpreted. */
7497 if(fread(block->block_contents, block->block_contents_size, 1,
7498 tng_data->input_file) == 0)
7500 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7501 return(TNG_CRITICAL);
7504 /* FIXME: Does not check if the size of the contents matches the expected
7505 * size or if the contents can be read. */
7507 if(hash_mode == TNG_USE_HASH)
7509 tng_md5_hash_match_verify(block, &same_hash);
7510 if(same_hash != TNG_TRUE)
7512 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7513 block->name, __FILE__, __LINE__);
7514 /* return(TNG_FAILURE); */
7518 if(tng_data_block_meta_information_read(tng_data, block,
7520 &dependency, &sparse_data,
7521 &n_values, &codec_id,
7522 &first_frame_with_data,
7523 &stride_length, &n_frames,
7524 &num_first_particle,
7526 &multiplier) == TNG_CRITICAL)
7528 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7529 block->name, __FILE__, __LINE__);
7530 return(TNG_CRITICAL);
7533 if (dependency & TNG_PARTICLE_DEPENDENT)
7535 return(tng_particle_data_read(tng_data, block,
7539 first_frame_with_data,
7542 codec_id, multiplier));
7546 return(tng_data_read(tng_data, block,
7548 first_frame_with_data,
7551 codec_id, multiplier));
7556 // ** Move the blocks in a frame set so that there is no unused space between
7557 // * them. This can only be done on the last frame set in the file and should
7558 // * be done e.g. if the last frame set in the file has fewer frames than
7559 // * default or after compressing data blocks in a frame set.
7560 // * @param tng_data is a trajectory data container.
7561 // * @details the current_trajectory_frame_set is the one that will be modified.
7562 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7563 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7564 // * FIXME: This function is not finished!!!
7566 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7568 // tng_gen_block_t block;
7569 // tng_trajectory_frame_set_t frame_set;
7570 // FILE *temp = tng_data->input_file;
7571 // int64_t pos, contents_start_pos, output_file_len;
7573 // frame_set = &tng_data->current_trajectory_frame_set;
7575 // if(frame_set->n_written_frames == frame_set->n_frames)
7577 // return(TNG_SUCCESS);
7580 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7581 // tng_data->last_trajectory_frame_set_output_file_pos)
7585 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7587 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7588 // __FILE__, __LINE__);
7589 // return(TNG_CRITICAL);
7592 // tng_block_init(&block);
7593 // // output_file_pos = ftello(tng_data->output_file);
7595 // tng_data->input_file = tng_data->output_file;
7597 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7599 // fseeko(tng_data->output_file, pos, SEEK_SET);
7600 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7602 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7603 // __FILE__, __LINE__);
7604 // tng_data->input_file = temp;
7605 // tng_block_destroy(&block);
7606 // return(TNG_CRITICAL);
7609 // contents_start_pos = ftello(tng_data->output_file);
7611 // fseeko(tng_data->output_file, 0, SEEK_END);
7612 // output_file_len = ftello(tng_data->output_file);
7613 // pos = contents_start_pos + block->block_contents_size;
7614 // fseeko(tng_data->output_file, pos,
7617 // while(pos < output_file_len)
7619 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7621 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7622 // __FILE__, __LINE__);
7623 // tng_data->input_file = temp;
7624 // tng_block_destroy(&block);
7625 // return(TNG_CRITICAL);
7627 // pos += block->header_contents_size + block->block_contents_size;
7628 // fseeko(tng_data->output_file, pos, SEEK_SET);
7631 // return(TNG_SUCCESS);
7634 /** Finish writing the current frame set. Update the number of frames
7635 * and the hashes of the frame set and all its data blocks (if hash_mode
7637 * @param tng_data is a trajectory data container.
7638 * @param hash_mode specifies whether to update the block md5 hash when
7639 * updating the pointers.
7640 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7641 * error has occured.
7643 static tng_function_status tng_frame_set_finalize
7644 (tng_trajectory_t tng_data, const char hash_mode)
7646 tng_gen_block_t block;
7647 tng_trajectory_frame_set_t frame_set;
7648 FILE *temp = tng_data->input_file;
7649 int64_t pos, contents_start_pos, output_file_len;
7651 frame_set = &tng_data->current_trajectory_frame_set;
7653 if(frame_set->n_written_frames == frame_set->n_frames)
7655 return(TNG_SUCCESS);
7658 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7660 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7661 __FILE__, __LINE__);
7662 return(TNG_CRITICAL);
7665 tng_block_init(&block);
7666 /* output_file_pos = ftello(tng_data->output_file); */
7668 tng_data->input_file = tng_data->output_file;
7670 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7672 fseeko(tng_data->output_file, pos, SEEK_SET);
7674 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7676 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7677 __FILE__, __LINE__);
7678 tng_data->input_file = temp;
7679 tng_block_destroy(&block);
7680 return(TNG_CRITICAL);
7683 contents_start_pos = ftello(tng_data->output_file);
7685 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7686 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7687 1, tng_data->output_file) != 1)
7689 tng_data->input_file = temp;
7690 tng_block_destroy(&block);
7691 return(TNG_CRITICAL);
7695 if(hash_mode == TNG_USE_HASH)
7697 tng_md5_hash_update(tng_data, block, pos,
7698 pos + block->header_contents_size);
7701 fseeko(tng_data->output_file, 0, SEEK_END);
7702 output_file_len = ftello(tng_data->output_file);
7703 pos = contents_start_pos + block->block_contents_size;
7704 fseeko(tng_data->output_file, pos, SEEK_SET);
7706 while(pos < output_file_len)
7708 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7710 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7711 __FILE__, __LINE__);
7712 tng_data->input_file = temp;
7713 tng_block_destroy(&block);
7714 return(TNG_CRITICAL);
7717 if(hash_mode == TNG_USE_HASH)
7719 tng_md5_hash_update(tng_data, block, pos,
7720 pos + block->header_contents_size);
7722 pos += block->header_contents_size + block->block_contents_size;
7723 fseeko(tng_data->output_file, pos, SEEK_SET);
7726 tng_data->input_file = temp;
7727 tng_block_destroy(&block);
7728 return(TNG_SUCCESS);
7732 // ** Sets the name of a file contents block
7733 // * @param tng_data is a trajectory data container.
7734 // * @param block is the block, of which to change names.
7735 // * @param new_name is the new name of the block.
7736 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7737 // * error has occured.
7739 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7740 // tng_gen_block_t block,
7741 // const char *new_name)
7745 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7747 // * If the currently stored string length is not enough to store the new
7748 // * string it is freed and reallocated. *
7749 // if(block->name && strlen(block->name) < len)
7751 // free(block->name);
7756 // block->name = malloc(len);
7759 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7760 // __FILE__, __LINE__);
7761 // return(TNG_CRITICAL);
7765 // strncpy(block->name, new_name, len);
7767 // return(TNG_SUCCESS);
7771 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7772 const tng_atom_t atom,
7773 tng_residue_t *residue)
7777 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7779 *residue = atom->residue;
7781 return(TNG_SUCCESS);
7784 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7785 const tng_atom_t atom,
7790 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7791 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7793 strncpy(name, atom->name, max_len - 1);
7794 name[max_len - 1] = 0;
7796 if(strlen(atom->name) > (unsigned int)max_len - 1)
7798 return(TNG_FAILURE);
7800 return(TNG_SUCCESS);
7803 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7805 const char *new_name)
7810 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7811 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7813 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7815 /* If the currently stored string length is not enough to store the new
7816 * string it is freed and reallocated. */
7817 if(atom->name && strlen(atom->name) < len)
7824 atom->name = malloc(len);
7827 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7828 __FILE__, __LINE__);
7829 return(TNG_CRITICAL);
7833 strncpy(atom->name, new_name, len);
7835 return(TNG_SUCCESS);
7838 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7839 const tng_atom_t atom,
7844 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7845 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7847 strncpy(type, atom->atom_type, max_len - 1);
7848 type[max_len - 1] = 0;
7850 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7852 return(TNG_FAILURE);
7854 return(TNG_SUCCESS);
7857 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7859 const char *new_type)
7864 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7865 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7867 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7869 /* If the currently stored string length is not enough to store the new
7870 * string it is freed and reallocated. */
7871 if(atom->atom_type && strlen(atom->atom_type) < len)
7873 free(atom->atom_type);
7874 atom->atom_type = 0;
7876 if(!atom->atom_type)
7878 atom->atom_type = malloc(len);
7879 if(!atom->atom_type)
7881 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7882 __FILE__, __LINE__);
7883 return(TNG_CRITICAL);
7887 strncpy(atom->atom_type, new_type, len);
7889 return(TNG_SUCCESS);
7892 /** Initialise an atom struct
7893 * @param atom is the atom to initialise.
7894 * @return TNG_SUCCESS (0) if successful.
7896 static tng_function_status tng_atom_init(tng_atom_t atom)
7899 atom->atom_type = 0;
7901 return(TNG_SUCCESS);
7904 /** Free the memory in an atom struct
7905 * @param atom is the atom to destroy.
7906 * @return TNG_SUCCESS (0) if successful.
7908 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7917 free(atom->atom_type);
7918 atom->atom_type = 0;
7921 return(TNG_SUCCESS);
7924 tng_function_status DECLSPECDLLEXPORT tng_version_major
7925 (const tng_trajectory_t tng_data,
7930 *version = TNG_VERSION_MAJOR;
7932 return(TNG_SUCCESS);
7935 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7936 (const tng_trajectory_t tng_data,
7941 *version = TNG_VERSION_MINOR;
7943 return(TNG_SUCCESS);
7946 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7947 (const tng_trajectory_t tng_data,
7952 *patch_level = TNG_VERSION_PATCHLEVEL;
7954 return(TNG_SUCCESS);
7957 tng_function_status DECLSPECDLLEXPORT tng_version
7958 (const tng_trajectory_t tng_data,
7963 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
7965 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
7967 return(TNG_SUCCESS);
7970 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7971 (tng_trajectory_t tng_data,
7973 tng_molecule_t *molecule)
7977 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7978 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7980 /* Set ID to the ID of the last molecule + 1 */
7981 if(tng_data->n_molecules)
7983 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7990 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7993 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7994 (tng_trajectory_t tng_data,
7997 tng_molecule_t *molecule)
7999 tng_molecule_t new_molecules;
8000 int64_t *new_molecule_cnt_list;
8001 tng_function_status stat = TNG_SUCCESS;
8003 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8004 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8006 new_molecules = realloc(tng_data->molecules,
8007 sizeof(struct tng_molecule) *
8008 (tng_data->n_molecules + 1));
8012 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8013 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8014 __FILE__, __LINE__);
8015 free(tng_data->molecules);
8016 tng_data->molecules = 0;
8017 return(TNG_CRITICAL);
8020 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8022 (tng_data->n_molecules + 1));
8024 if(!new_molecule_cnt_list)
8026 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8027 sizeof(int64_t) * (tng_data->n_molecules + 1),
8028 __FILE__, __LINE__);
8029 free(tng_data->molecule_cnt_list);
8030 tng_data->molecule_cnt_list = 0;
8031 free(new_molecules);
8032 return(TNG_CRITICAL);
8035 tng_data->molecules = new_molecules;
8036 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8038 *molecule = &new_molecules[tng_data->n_molecules];
8040 tng_molecule_init(tng_data, *molecule);
8041 tng_molecule_name_set(tng_data, *molecule, name);
8043 /* FIXME: Should this be a function argument instead? */
8044 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8046 (*molecule)->id = id;
8048 tng_data->n_molecules++;
8053 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
8054 (tng_trajectory_t tng_data,
8055 tng_molecule_t *molecule_p)
8057 int64_t *new_molecule_cnt_list, id;
8058 tng_molecule_t new_molecules, molecule;
8060 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8062 /* Set ID to the ID of the last molecule + 1 */
8063 if(tng_data->n_molecules)
8065 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
8072 new_molecules = realloc(tng_data->molecules,
8073 sizeof(struct tng_molecule) *
8074 (tng_data->n_molecules + 1));
8078 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8079 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8080 __FILE__, __LINE__);
8081 free(tng_data->molecules);
8082 tng_data->molecules = 0;
8083 return(TNG_CRITICAL);
8086 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8088 (tng_data->n_molecules + 1));
8090 if(!new_molecule_cnt_list)
8092 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8093 sizeof(int64_t) * (tng_data->n_molecules + 1),
8094 __FILE__, __LINE__);
8095 free(tng_data->molecule_cnt_list);
8096 tng_data->molecule_cnt_list = 0;
8097 free(new_molecules);
8098 return(TNG_CRITICAL);
8101 molecule = *molecule_p;
8103 tng_data->molecules = new_molecules;
8104 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8106 new_molecules[tng_data->n_molecules] = *molecule;
8108 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8112 molecule = &new_molecules[tng_data->n_molecules];
8114 *molecule_p = molecule;
8118 tng_data->n_molecules++;
8120 return(TNG_SUCCESS);
8123 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8124 const tng_molecule_t molecule,
8129 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8130 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8132 strncpy(name, molecule->name, max_len - 1);
8133 name[max_len - 1] = 0;
8135 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8137 return(TNG_FAILURE);
8139 return(TNG_SUCCESS);
8142 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8143 (tng_trajectory_t tng_data,
8144 tng_molecule_t molecule,
8145 const char *new_name)
8150 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8151 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8153 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8155 /* If the currently stored string length is not enough to store the new
8156 * string it is freed and reallocated. */
8157 if(molecule->name && strlen(molecule->name) < len)
8159 free(molecule->name);
8164 molecule->name = malloc(len);
8167 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8168 __FILE__, __LINE__);
8169 return(TNG_CRITICAL);
8173 strncpy(molecule->name, new_name, len);
8175 return(TNG_SUCCESS);
8178 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8179 (const tng_trajectory_t tng_data,
8180 const tng_molecule_t molecule,
8183 int64_t i, index = -1;
8185 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8186 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8188 for(i = 0; i < tng_data->n_molecules; i++)
8190 if(&tng_data->molecules[i] == molecule)
8198 return(TNG_FAILURE);
8200 *cnt = tng_data->molecule_cnt_list[index];
8202 return(TNG_SUCCESS);
8205 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8206 (tng_trajectory_t tng_data,
8207 tng_molecule_t molecule,
8210 int64_t i, old_cnt, index = -1;
8212 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8214 for(i = 0; i < tng_data->n_molecules; i++)
8216 if(&tng_data->molecules[i] == molecule)
8224 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8225 __FILE__, __LINE__);
8226 return(TNG_FAILURE);
8228 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8230 old_cnt = tng_data->molecule_cnt_list[index];
8231 tng_data->molecule_cnt_list[index] = cnt;
8233 tng_data->n_particles += (cnt-old_cnt) *
8234 tng_data->molecules[index].n_atoms;
8238 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8239 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8241 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8242 tng_data->molecules[index].n_atoms;
8245 return(TNG_SUCCESS);
8248 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8249 (tng_trajectory_t tng_data,
8252 tng_molecule_t *molecule)
8254 int64_t i, n_molecules;
8256 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8257 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8258 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8260 n_molecules = tng_data->n_molecules;
8262 for(i = n_molecules - 1; i >= 0; i--)
8264 *molecule = &tng_data->molecules[i];
8265 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8267 if(nr == -1 || nr == (*molecule)->id)
8269 return(TNG_SUCCESS);
8276 return(TNG_FAILURE);
8279 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8280 (tng_trajectory_t tng_data,
8282 tng_molecule_t *molecule)
8284 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8285 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8287 if(index >= tng_data->n_molecules)
8290 return(TNG_FAILURE);
8292 *molecule = &tng_data->molecules[index];
8293 return(TNG_SUCCESS);
8296 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8297 tng_trajectory_t tng_data_dest)
8299 tng_molecule_t molecule, molecule_temp;
8300 tng_chain_t chain, chain_temp;
8301 tng_residue_t residue, residue_temp;
8302 tng_atom_t atom, atom_temp;
8303 tng_bond_t bond_temp;
8304 tng_function_status stat;
8305 int64_t i, j, k, l, *list_temp;
8307 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8308 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8310 for(i = 0; i < tng_data_dest->n_molecules; i++)
8312 molecule = &tng_data_dest->molecules[i];
8313 tng_molecule_destroy(tng_data_dest, molecule);
8316 tng_data_dest->n_molecules = 0;
8317 tng_data_dest->n_particles = 0;
8319 molecule_temp = realloc(tng_data_dest->molecules,
8320 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8323 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8324 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8325 __FILE__, __LINE__);
8326 free(tng_data_dest->molecules);
8327 tng_data_dest->molecules = 0;
8328 return(TNG_CRITICAL);
8330 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8331 sizeof(int64_t) * tng_data_src->n_molecules);
8334 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8335 sizeof(int64_t) * tng_data_src->n_molecules,
8336 __FILE__, __LINE__);
8337 free(tng_data_dest->molecule_cnt_list);
8338 tng_data_dest->molecule_cnt_list = 0;
8339 free(molecule_temp);
8340 return(TNG_CRITICAL);
8343 tng_data_dest->molecules = molecule_temp;
8344 tng_data_dest->molecule_cnt_list = list_temp;
8346 for(i = 0; i < tng_data_src->n_molecules; i++)
8348 molecule = &tng_data_src->molecules[i];
8349 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8351 if(stat != TNG_SUCCESS)
8353 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8354 __FILE__, __LINE__);
8357 molecule_temp->quaternary_str = molecule->quaternary_str;
8358 for(j = 0; j < molecule->n_chains; j++)
8360 chain = &molecule->chains[j];
8361 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8362 chain->name, chain->id,
8364 if(stat != TNG_SUCCESS)
8366 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8367 __FILE__, __LINE__);
8370 for(k = 0; k < chain->n_residues; k++)
8372 residue = &chain->residues[k];
8373 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8374 residue->name, residue->id,
8376 if(stat != TNG_SUCCESS)
8378 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8379 __FILE__, __LINE__);
8382 for(l = 0; l < residue->n_atoms; l++)
8384 atom = &molecule->atoms[residue->atoms_offset + l];
8385 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8386 atom->name, atom->atom_type,
8387 atom->id, &atom_temp);
8388 if(stat != TNG_SUCCESS)
8390 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8391 __FILE__, __LINE__);
8397 molecule_temp->n_bonds = molecule->n_bonds;
8398 if(molecule->n_bonds > 0)
8400 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8404 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8405 sizeof(struct tng_bond) * molecule->n_bonds,
8406 __FILE__, __LINE__);
8407 free(molecule_temp->bonds);
8408 molecule_temp->n_bonds = 0;
8409 return(TNG_CRITICAL);
8411 molecule_temp->bonds = bond_temp;
8412 for(j = 0; j < molecule->n_bonds; j++)
8414 molecule_temp->bonds[j] = molecule->bonds[j];
8417 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8418 tng_data_src->molecule_cnt_list[i]);
8419 if(stat != TNG_SUCCESS)
8421 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8422 __FILE__, __LINE__);
8426 return(TNG_SUCCESS);
8429 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8430 (const tng_trajectory_t tng_data,
8431 const tng_molecule_t molecule,
8435 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8436 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8438 *n = molecule->n_chains;
8440 return(TNG_SUCCESS);
8443 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8444 (tng_trajectory_t tng_data,
8445 tng_molecule_t molecule,
8450 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8451 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8453 if(index >= molecule->n_chains)
8456 return(TNG_FAILURE);
8458 *chain = &molecule->chains[index];
8459 return(TNG_SUCCESS);
8462 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8463 (const tng_trajectory_t tng_data,
8464 const tng_molecule_t molecule,
8468 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8469 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8471 *n = molecule->n_residues;
8473 return(TNG_SUCCESS);
8476 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8477 (const tng_trajectory_t tng_data,
8478 const tng_molecule_t molecule,
8479 const int64_t index,
8480 tng_residue_t *residue)
8483 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8484 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8486 if(index >= molecule->n_residues)
8489 return(TNG_FAILURE);
8491 *residue = &molecule->residues[index];
8492 return(TNG_SUCCESS);
8495 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8496 (const tng_trajectory_t tng_data,
8497 const tng_molecule_t molecule,
8501 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8502 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8504 *n = molecule->n_atoms;
8506 return(TNG_SUCCESS);
8509 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8510 (const tng_trajectory_t tng_data,
8511 const tng_molecule_t molecule,
8512 const int64_t index,
8516 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8517 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8519 if(index >= molecule->n_atoms)
8522 return(TNG_FAILURE);
8524 *atom = &molecule->atoms[index];
8525 return(TNG_SUCCESS);
8528 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8529 (tng_trajectory_t tng_data,
8530 tng_molecule_t molecule,
8535 int64_t i, n_chains;
8538 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8539 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8541 n_chains = molecule->n_chains;
8543 for(i = n_chains - 1; i >= 0; i--)
8545 *chain = &molecule->chains[i];
8546 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8548 if(nr == -1 || nr == (*chain)->id)
8550 return(TNG_SUCCESS);
8557 return(TNG_FAILURE);
8560 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8561 (tng_trajectory_t tng_data,
8562 tng_molecule_t molecule,
8568 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8569 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8571 /* Set ID to the ID of the last chain + 1 */
8572 if(molecule->n_chains)
8574 id = molecule->chains[molecule->n_chains-1].id + 1;
8581 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8585 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8586 (tng_trajectory_t tng_data,
8587 tng_molecule_t molecule,
8592 tng_chain_t new_chains;
8593 tng_function_status stat = TNG_SUCCESS;
8595 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8596 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8598 new_chains = realloc(molecule->chains,
8599 sizeof(struct tng_chain) *
8600 (molecule->n_chains + 1));
8604 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8605 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8606 __FILE__, __LINE__);
8607 free(molecule->chains);
8608 molecule->chains = 0;
8609 return(TNG_CRITICAL);
8612 molecule->chains = new_chains;
8614 *chain = &new_chains[molecule->n_chains];
8617 tng_chain_name_set(tng_data, *chain, name);
8619 (*chain)->molecule = molecule;
8620 (*chain)->n_residues = 0;
8622 molecule->n_chains++;
8629 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8630 (const tng_trajectory_t tng_data,
8631 tng_molecule_t molecule,
8632 const int64_t from_atom_id,
8633 const int64_t to_atom_id,
8636 tng_bond_t new_bonds;
8639 new_bonds = realloc(molecule->bonds,
8640 sizeof(struct tng_bond) *
8641 (molecule->n_bonds + 1));
8645 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8646 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8647 __FILE__, __LINE__);
8649 free(molecule->bonds);
8650 molecule->bonds = 0;
8651 return(TNG_CRITICAL);
8654 molecule->bonds = new_bonds;
8656 *bond = &new_bonds[molecule->n_bonds];
8658 (*bond)->from_atom_id = from_atom_id;
8659 (*bond)->to_atom_id = to_atom_id;
8661 molecule->n_bonds++;
8663 return(TNG_SUCCESS);
8666 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8667 (tng_trajectory_t tng_data,
8668 tng_molecule_t molecule,
8676 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8678 n_atoms = molecule->n_atoms;
8680 for(i = n_atoms - 1; i >= 0; i--)
8682 *atom = &molecule->atoms[i];
8683 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8685 if(id == -1 || id == (*atom)->id)
8687 return(TNG_SUCCESS);
8694 return(TNG_FAILURE);
8697 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8698 const tng_chain_t chain,
8703 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8704 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8706 strncpy(name, chain->name, max_len - 1);
8707 name[max_len - 1] = 0;
8709 if(strlen(chain->name) > (unsigned int)max_len - 1)
8711 return(TNG_FAILURE);
8713 return(TNG_SUCCESS);
8716 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8717 (tng_trajectory_t tng_data,
8719 const char *new_name)
8724 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8726 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8728 /* If the currently stored string length is not enough to store the new
8729 * string it is freed and reallocated. */
8730 if(chain->name && strlen(chain->name) < len)
8737 chain->name = malloc(len);
8740 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8741 __FILE__, __LINE__);
8742 return(TNG_CRITICAL);
8746 strncpy(chain->name, new_name, len);
8748 return(TNG_SUCCESS);
8751 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8752 (const tng_trajectory_t tng_data,
8753 const tng_chain_t chain,
8757 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8758 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8760 *n = chain->n_residues;
8762 return(TNG_SUCCESS);
8765 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8766 (const tng_trajectory_t tng_data,
8767 const tng_chain_t chain,
8768 const int64_t index,
8769 tng_residue_t *residue)
8772 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8773 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8775 if(index >= chain->n_residues)
8778 return(TNG_FAILURE);
8780 *residue = &chain->residues[index];
8781 return(TNG_SUCCESS);
8784 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8785 (tng_trajectory_t tng_data,
8789 tng_residue_t *residue)
8791 int64_t i, n_residues;
8794 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8796 n_residues = chain->n_residues;
8798 for(i = n_residues - 1; i >= 0; i--)
8800 *residue = &chain->residues[i];
8801 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8803 if(id == -1 || id == (*residue)->id)
8805 return(TNG_SUCCESS);
8812 return(TNG_FAILURE);
8815 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8816 (tng_trajectory_t tng_data,
8819 tng_residue_t *residue)
8823 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8824 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8826 /* Set ID to the ID of the last residue + 1 */
8827 if(chain->n_residues)
8829 id = chain->residues[chain->n_residues-1].id + 1;
8836 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8840 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8841 (tng_trajectory_t tng_data,
8845 tng_residue_t *residue)
8848 tng_residue_t new_residues, temp_residue, last_residue;
8849 tng_molecule_t molecule = chain->molecule;
8850 tng_function_status stat = TNG_SUCCESS;
8852 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8853 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8855 if(chain->n_residues)
8857 curr_index = chain->residues - molecule->residues;
8864 new_residues = realloc(molecule->residues,
8865 sizeof(struct tng_residue) *
8866 (molecule->n_residues + 1));
8870 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8871 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8872 __FILE__, __LINE__);
8873 free(molecule->residues);
8874 molecule->residues = 0;
8875 return(TNG_CRITICAL);
8878 molecule->residues = new_residues;
8880 if(curr_index != -1)
8882 chain->residues = new_residues + curr_index;
8883 if(molecule->n_residues)
8885 last_residue = &new_residues[molecule->n_residues - 1];
8887 temp_residue = chain->residues + (chain->n_residues - 1);
8888 /* Make space in list of residues to add the new residues together with the other
8889 * residues of this chain */
8890 if(temp_residue != last_residue)
8893 memmove(temp_residue + 1, temp_residue,
8894 last_residue - temp_residue);
8900 curr_index = molecule->n_residues;
8903 *residue = &molecule->residues[curr_index + chain->n_residues];
8905 if(!chain->n_residues)
8907 chain->residues = *residue;
8911 chain->residues = &molecule->residues[curr_index];
8914 (*residue)->name = 0;
8915 tng_residue_name_set(tng_data, *residue, name);
8917 (*residue)->chain = chain;
8918 (*residue)->n_atoms = 0;
8919 (*residue)->atoms_offset = 0;
8921 chain->n_residues++;
8922 molecule->n_residues++;
8924 (*residue)->id = id;
8929 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8930 const tng_residue_t residue,
8935 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8936 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8938 strncpy(name, residue->name, max_len - 1);
8939 name[max_len - 1] = 0;
8941 if(strlen(residue->name) > (unsigned int)max_len - 1)
8943 return(TNG_FAILURE);
8945 return(TNG_SUCCESS);
8948 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8949 tng_residue_t residue,
8950 const char *new_name)
8955 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8956 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8958 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8960 /* If the currently stored string length is not enough to store the new
8961 * string it is freed and reallocated. */
8962 if(residue->name && strlen(residue->name) < len)
8964 free(residue->name);
8969 residue->name = malloc(len);
8972 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8973 __FILE__, __LINE__);
8974 return(TNG_CRITICAL);
8978 strncpy(residue->name, new_name, len);
8980 return(TNG_SUCCESS);
8983 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8984 (const tng_trajectory_t tng_data,
8985 const tng_residue_t residue,
8989 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8990 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8992 *n = residue->n_atoms;
8994 return(TNG_SUCCESS);
8997 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8998 (const tng_trajectory_t tng_data,
8999 const tng_residue_t residue,
9000 const int64_t index,
9004 tng_molecule_t molecule;
9007 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
9008 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
9010 if(index >= residue->n_atoms)
9013 return(TNG_FAILURE);
9015 chain = residue->chain;
9016 molecule = chain->molecule;
9018 if(index + residue->atoms_offset >= molecule->n_atoms)
9021 return(TNG_FAILURE);
9024 *atom = &molecule->atoms[residue->atoms_offset + index];
9025 return(TNG_SUCCESS);
9028 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
9029 (tng_trajectory_t tng_data,
9030 tng_residue_t residue,
9031 const char *atom_name,
9032 const char *atom_type,
9037 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9038 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9039 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9041 /* Set ID to the ID of the last atom + 1 */
9042 if(residue->chain->molecule->n_atoms)
9044 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
9051 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
9055 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
9056 (tng_trajectory_t tng_data,
9057 tng_residue_t residue,
9058 const char *atom_name,
9059 const char *atom_type,
9063 tng_atom_t new_atoms;
9064 tng_molecule_t molecule = residue->chain->molecule;
9065 tng_function_status stat = TNG_SUCCESS;
9067 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9068 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9069 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9071 if(!residue->n_atoms)
9073 residue->atoms_offset = molecule->n_atoms;
9076 new_atoms = realloc(molecule->atoms,
9077 sizeof(struct tng_atom) *
9078 (molecule->n_atoms + 1));
9082 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
9083 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
9084 __FILE__, __LINE__);
9085 free(molecule->atoms);
9086 molecule->atoms = 0;
9087 return(TNG_CRITICAL);
9090 molecule->atoms = new_atoms;
9092 *atom = &new_atoms[molecule->n_atoms];
9094 tng_atom_init(*atom);
9095 tng_atom_name_set(tng_data, *atom, atom_name);
9096 tng_atom_type_set(tng_data, *atom, atom_type);
9098 (*atom)->residue = residue;
9101 molecule->n_atoms++;
9108 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
9109 tng_molecule_t *molecule_p)
9111 *molecule_p = malloc(sizeof(struct tng_molecule));
9114 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
9115 sizeof(struct tng_molecule), __FILE__, __LINE__);
9116 return(TNG_CRITICAL);
9119 tng_molecule_init(tng_data, *molecule_p);
9121 return(TNG_SUCCESS);
9124 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9125 tng_molecule_t *molecule_p)
9129 return(TNG_SUCCESS);
9132 tng_molecule_destroy(tng_data, *molecule_p);
9137 return(TNG_SUCCESS);
9140 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9141 tng_molecule_t molecule)
9144 molecule->quaternary_str = 1;
9146 molecule->n_chains = 0;
9147 molecule->chains = 0;
9148 molecule->n_residues = 0;
9149 molecule->residues = 0;
9150 molecule->n_atoms = 0;
9151 molecule->atoms = 0;
9152 molecule->n_bonds = 0;
9153 molecule->bonds = 0;
9155 return(TNG_SUCCESS);
9158 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9159 tng_molecule_t molecule)
9166 free(molecule->name);
9170 if(molecule->chains)
9172 for(i = 0; i < molecule->n_chains; i++)
9174 if(molecule->chains[i].name)
9176 free(molecule->chains[i].name);
9177 molecule->chains[i].name = 0;
9180 free(molecule->chains);
9181 molecule->chains = 0;
9183 molecule->n_chains = 0;
9185 if(molecule->residues)
9187 for(i = 0; i < molecule->n_residues; i++)
9189 if(molecule->residues[i].name)
9191 free(molecule->residues[i].name);
9192 molecule->residues[i].name = 0;
9195 free(molecule->residues);
9196 molecule->residues = 0;
9198 molecule->n_residues = 0;
9202 for(i = 0; i < molecule->n_atoms; i++)
9204 tng_atom_destroy(&molecule->atoms[i]);
9206 free(molecule->atoms);
9207 molecule->atoms = 0;
9209 molecule->n_atoms = 0;
9213 free(molecule->bonds);
9214 molecule->bonds = 0;
9216 molecule->n_bonds = 0;
9218 return(TNG_SUCCESS);
9221 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9222 (const tng_trajectory_t tng_data,
9227 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9229 tng_bool found = TNG_FALSE;
9231 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9232 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9234 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9236 if(!molecule_cnt_list)
9238 return(TNG_FAILURE);
9241 for(i = 0; i < tng_data->n_molecules; i++)
9243 mol = &tng_data->molecules[i];
9244 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9246 cnt += mol->n_atoms * molecule_cnt_list[i];
9254 return(TNG_FAILURE);
9257 strncpy(name, mol->name, max_len - 1);
9258 name[max_len - 1] = 0;
9260 if(strlen(mol->name) > (unsigned int)max_len - 1)
9262 return(TNG_FAILURE);
9264 return(TNG_SUCCESS);
9267 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9268 (const tng_trajectory_t tng_data,
9272 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9274 tng_bool found = TNG_FALSE;
9276 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9277 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9279 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9281 if(!molecule_cnt_list)
9283 return(TNG_FAILURE);
9286 for(i = 0; i < tng_data->n_molecules; i++)
9288 mol = &tng_data->molecules[i];
9289 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9291 cnt += mol->n_atoms * molecule_cnt_list[i];
9299 return(TNG_FAILURE);
9304 return(TNG_SUCCESS);
9307 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9308 (const tng_trajectory_t tng_data,
9310 int64_t **from_atoms,
9313 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9314 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9318 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9319 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9320 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9321 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9323 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9325 if(!molecule_cnt_list)
9327 return(TNG_FAILURE);
9331 /* First count the total number of bonds to allocate memory */
9332 for(i = 0; i < tng_data->n_molecules; i++)
9334 mol = &tng_data->molecules[i];
9335 mol_cnt = molecule_cnt_list[i];
9336 *n_bonds += mol_cnt * mol->n_bonds;
9340 return(TNG_SUCCESS);
9343 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9346 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
9347 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9348 return(TNG_CRITICAL);
9350 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9353 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
9354 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9357 return(TNG_CRITICAL);
9361 for(i = 0; i < tng_data->n_molecules; i++)
9363 mol = &tng_data->molecules[i];
9364 mol_cnt = molecule_cnt_list[i];
9365 for(j = 0; j < mol_cnt; j++)
9367 for(k = 0; k < mol->n_bonds; k++)
9369 bond = &mol->bonds[k];
9370 from_atom = atom_cnt + bond->from_atom_id;
9371 to_atom = atom_cnt + bond->to_atom_id;
9372 (*from_atoms)[cnt] = from_atom;
9373 (*to_atoms)[cnt++] = to_atom;
9375 atom_cnt += mol->n_atoms;
9379 return(TNG_SUCCESS);
9382 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9383 (const tng_trajectory_t tng_data,
9388 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9391 tng_bool found = TNG_FALSE;
9393 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9394 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9396 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9398 if(!molecule_cnt_list)
9400 return(TNG_FAILURE);
9403 for(i = 0; i < tng_data->n_molecules; i++)
9405 mol = &tng_data->molecules[i];
9406 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9408 cnt += mol->n_atoms * molecule_cnt_list[i];
9411 atom = &mol->atoms[nr % mol->n_atoms];
9417 return(TNG_FAILURE);
9419 if(!atom->residue || !atom->residue->chain)
9421 return(TNG_FAILURE);
9424 strncpy(name, atom->residue->chain->name, max_len - 1);
9425 name[max_len - 1] = 0;
9427 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9429 return(TNG_FAILURE);
9431 return(TNG_SUCCESS);
9434 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9435 (const tng_trajectory_t tng_data,
9440 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9443 tng_bool found = TNG_FALSE;
9445 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9446 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9448 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9450 if(!molecule_cnt_list)
9452 return(TNG_FAILURE);
9455 for(i = 0; i < tng_data->n_molecules; i++)
9457 mol = &tng_data->molecules[i];
9458 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9460 cnt += mol->n_atoms * molecule_cnt_list[i];
9463 atom = &mol->atoms[nr % mol->n_atoms];
9469 return(TNG_FAILURE);
9473 return(TNG_FAILURE);
9476 strncpy(name, atom->residue->name, max_len - 1);
9477 name[max_len - 1] = 0;
9479 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9481 return(TNG_FAILURE);
9483 return(TNG_SUCCESS);
9486 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9487 (const tng_trajectory_t tng_data,
9491 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9494 tng_bool found = TNG_FALSE;
9496 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9497 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9499 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9501 if(!molecule_cnt_list)
9503 return(TNG_FAILURE);
9506 for(i = 0; i < tng_data->n_molecules; i++)
9508 mol = &tng_data->molecules[i];
9509 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9511 cnt += mol->n_atoms * molecule_cnt_list[i];
9514 atom = &mol->atoms[nr % mol->n_atoms];
9520 return(TNG_FAILURE);
9524 return(TNG_FAILURE);
9527 *id = atom->residue->id;
9529 return(TNG_SUCCESS);
9532 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9533 (const tng_trajectory_t tng_data,
9537 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9540 tng_bool found = TNG_FALSE;
9542 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9543 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9545 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9547 if(!molecule_cnt_list)
9549 return(TNG_FAILURE);
9552 for(i = 0; i < tng_data->n_molecules; i++)
9554 mol = &tng_data->molecules[i];
9555 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9557 cnt += mol->n_atoms * molecule_cnt_list[i];
9558 offset += mol->n_residues * molecule_cnt_list[i];
9561 atom = &mol->atoms[nr % mol->n_atoms];
9567 return(TNG_FAILURE);
9571 return(TNG_FAILURE);
9574 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9576 *id = atom->residue->id + offset;
9578 return(TNG_SUCCESS);
9581 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9582 (const tng_trajectory_t tng_data,
9587 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9590 tng_bool found = TNG_FALSE;
9592 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9593 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9595 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9597 if(!molecule_cnt_list)
9599 return(TNG_FAILURE);
9602 for(i = 0; i < tng_data->n_molecules; i++)
9604 mol = &tng_data->molecules[i];
9605 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9607 cnt += mol->n_atoms * molecule_cnt_list[i];
9610 atom = &mol->atoms[nr % mol->n_atoms];
9616 return(TNG_FAILURE);
9619 strncpy(name, atom->name, max_len - 1);
9620 name[max_len - 1] = 0;
9622 if(strlen(atom->name) > (unsigned int)max_len - 1)
9624 return(TNG_FAILURE);
9626 return(TNG_SUCCESS);
9629 tng_function_status tng_atom_type_of_particle_nr_get
9630 (const tng_trajectory_t tng_data,
9635 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9638 tng_bool found = TNG_FALSE;
9640 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9641 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9643 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9645 if(!molecule_cnt_list)
9647 return(TNG_FAILURE);
9650 for(i = 0; i < tng_data->n_molecules; i++)
9652 mol = &tng_data->molecules[i];
9653 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9655 cnt += mol->n_atoms * molecule_cnt_list[i];
9658 atom = &mol->atoms[nr % mol->n_atoms];
9664 return(TNG_FAILURE);
9667 strncpy(type, atom->atom_type, max_len - 1);
9668 type[max_len - 1] = 0;
9670 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9672 return(TNG_FAILURE);
9674 return(TNG_SUCCESS);
9677 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9678 (tng_trajectory_t tng_data,
9679 const int64_t num_first_particle,
9680 const int64_t n_particles,
9681 const int64_t *mapping_table)
9684 tng_particle_mapping_t mapping;
9685 tng_trajectory_frame_set_t frame_set;
9687 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9689 frame_set = &tng_data->current_trajectory_frame_set;
9691 /* Sanity check of the particle ranges. Split into multiple if
9692 * statements for improved readability */
9693 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9695 mapping = &frame_set->mappings[i];
9696 if(num_first_particle >= mapping->num_first_particle &&
9697 num_first_particle < mapping->num_first_particle +
9698 mapping->n_particles)
9700 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9701 return(TNG_FAILURE);
9703 if(num_first_particle + n_particles >=
9704 mapping->num_first_particle &&
9705 num_first_particle + n_particles <
9706 mapping->num_first_particle + mapping->n_particles)
9708 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9709 return(TNG_FAILURE);
9711 if(mapping->num_first_particle >= num_first_particle &&
9712 mapping->num_first_particle < num_first_particle +
9715 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9716 return(TNG_FAILURE);
9718 if(mapping->num_first_particle + mapping->n_particles >
9719 num_first_particle &&
9720 mapping->num_first_particle + mapping->n_particles <
9721 num_first_particle + n_particles)
9723 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9724 return(TNG_FAILURE);
9728 frame_set->n_mapping_blocks++;
9730 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9731 frame_set->n_mapping_blocks);
9735 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
9736 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9737 __FILE__, __LINE__);
9738 free(frame_set->mappings);
9739 frame_set->mappings = 0;
9740 return(TNG_CRITICAL);
9742 frame_set->mappings = mapping;
9744 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9745 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9747 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9748 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9750 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
9751 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9752 return(TNG_CRITICAL);
9755 for(i=0; i<n_particles; i++)
9757 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9760 return(TNG_SUCCESS);
9763 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9765 tng_trajectory_frame_set_t frame_set;
9766 tng_particle_mapping_t mapping;
9769 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9771 frame_set = &tng_data->current_trajectory_frame_set;
9773 if(frame_set->n_mapping_blocks && frame_set->mappings)
9775 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9777 mapping = &frame_set->mappings[i];
9778 if(mapping->real_particle_numbers)
9780 free(mapping->real_particle_numbers);
9781 mapping->real_particle_numbers = 0;
9784 free(frame_set->mappings);
9785 frame_set->mappings = 0;
9786 frame_set->n_mapping_blocks = 0;
9789 return(TNG_SUCCESS);
9792 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9795 tng_trajectory_frame_set_t frame_set;
9796 tng_trajectory_t tng_data;
9798 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9801 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
9802 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9803 return(TNG_CRITICAL);
9806 tng_data = *tng_data_p;
9808 frame_set = &tng_data->current_trajectory_frame_set;
9810 tng_data->input_file_path = 0;
9811 tng_data->input_file = 0;
9812 tng_data->input_file_len = 0;
9813 tng_data->output_file_path = 0;
9814 tng_data->output_file = 0;
9816 tng_data->first_program_name = 0;
9817 tng_data->first_user_name = 0;
9818 tng_data->first_computer_name = 0;
9819 tng_data->first_pgp_signature = 0;
9820 tng_data->last_program_name = 0;
9821 tng_data->last_user_name = 0;
9822 tng_data->last_computer_name = 0;
9823 tng_data->last_pgp_signature = 0;
9824 tng_data->forcefield_name = 0;
9829 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9833 tng_data->time = seconds;
9836 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9837 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9838 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9839 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9840 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9841 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9842 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9843 tng_data->frame_set_n_frames = 100;
9844 tng_data->n_trajectory_frame_sets = 0;
9845 tng_data->medium_stride_length = 100;
9846 tng_data->long_stride_length = 10000;
9848 tng_data->time_per_frame = -1;
9850 tng_data->n_particle_data_blocks = 0;
9851 tng_data->n_data_blocks = 0;
9853 tng_data->non_tr_particle_data = 0;
9854 tng_data->non_tr_data = 0;
9856 tng_data->compress_algo_pos = 0;
9857 tng_data->compress_algo_vel = 0;
9858 tng_data->compression_precision = 1000;
9859 tng_data->distance_unit_exponential = -9;
9861 frame_set->first_frame = -1;
9862 frame_set->n_mapping_blocks = 0;
9863 frame_set->mappings = 0;
9864 frame_set->molecule_cnt_list = 0;
9866 frame_set->n_particle_data_blocks = 0;
9867 frame_set->n_data_blocks = 0;
9869 frame_set->tr_particle_data = 0;
9870 frame_set->tr_data = 0;
9872 frame_set->n_written_frames = 0;
9873 frame_set->n_unwritten_frames = 0;
9875 frame_set->next_frame_set_file_pos = -1;
9876 frame_set->prev_frame_set_file_pos = -1;
9877 frame_set->medium_stride_next_frame_set_file_pos = -1;
9878 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9879 frame_set->long_stride_next_frame_set_file_pos = -1;
9880 frame_set->long_stride_prev_frame_set_file_pos = -1;
9882 frame_set->first_frame_time = -1;
9884 tng_data->n_molecules = 0;
9885 tng_data->molecules = 0;
9886 tng_data->molecule_cnt_list = 0;
9887 tng_data->n_particles = 0;
9890 /* Check the endianness of the computer */
9891 static int32_t endianness_32 = 0x01234567;
9893 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9895 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9899 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9901 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9906 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9908 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9912 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9913 /* 0x0123456789ABCDEF */
9914 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9916 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9919 /* 0xEFCDAB8967452301 */
9920 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9922 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9925 /* 0x89ABCDEF01234567 */
9926 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9928 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9931 /* 0x45670123CDEF89AB */
9932 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9934 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9937 /* 0x23016745AB89EFCD */
9938 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9940 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9944 /* By default do not swap the byte order, i.e. keep the byte order of the
9945 * architecture. The input file endianness will be set when reading the
9946 * header. The output endianness can be changed - before the file is
9948 tng_data->input_endianness_swap_func_32 = 0;
9949 tng_data->input_endianness_swap_func_64 = 0;
9950 tng_data->output_endianness_swap_func_32 = 0;
9951 tng_data->output_endianness_swap_func_64 = 0;
9953 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9954 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9955 tng_data->current_trajectory_frame_set.n_frames = 0;
9957 return(TNG_SUCCESS);
9960 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9963 int64_t n_particles, n_values_per_frame;
9964 tng_trajectory_t tng_data = *tng_data_p;
9965 tng_trajectory_frame_set_t frame_set;
9969 return(TNG_SUCCESS);
9972 frame_set = &tng_data->current_trajectory_frame_set;
9974 if(tng_data->input_file_path)
9976 free(tng_data->input_file_path);
9977 tng_data->input_file_path = 0;
9980 if(tng_data->input_file)
9982 if(tng_data->output_file == tng_data->input_file)
9984 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9985 tng_data->output_file = 0;
9987 fclose(tng_data->input_file);
9988 tng_data->input_file = 0;
9991 if(tng_data->output_file_path)
9993 free(tng_data->output_file_path);
9994 tng_data->output_file_path = 0;
9997 if(tng_data->output_file)
9999 /* FIXME: Do not always write the hash */
10000 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
10001 fclose(tng_data->output_file);
10002 tng_data->output_file = 0;
10005 if(tng_data->first_program_name)
10007 free(tng_data->first_program_name);
10008 tng_data->first_program_name = 0;
10011 if(tng_data->last_program_name)
10013 free(tng_data->last_program_name);
10014 tng_data->last_program_name = 0;
10017 if(tng_data->first_user_name)
10019 free(tng_data->first_user_name);
10020 tng_data->first_user_name = 0;
10023 if(tng_data->last_user_name)
10025 free(tng_data->last_user_name);
10026 tng_data->last_user_name = 0;
10029 if(tng_data->first_computer_name)
10031 free(tng_data->first_computer_name);
10032 tng_data->first_computer_name = 0;
10035 if(tng_data->last_computer_name)
10037 free(tng_data->last_computer_name);
10038 tng_data->last_computer_name = 0;
10041 if(tng_data->first_pgp_signature)
10043 free(tng_data->first_pgp_signature);
10044 tng_data->first_pgp_signature = 0;
10047 if(tng_data->last_pgp_signature)
10049 free(tng_data->last_pgp_signature);
10050 tng_data->last_pgp_signature = 0;
10053 if(tng_data->forcefield_name)
10055 free(tng_data->forcefield_name);
10056 tng_data->forcefield_name = 0;
10059 tng_frame_set_particle_mapping_free(tng_data);
10061 if(frame_set->molecule_cnt_list)
10063 free(frame_set->molecule_cnt_list);
10064 frame_set->molecule_cnt_list = 0;
10067 if(tng_data->var_num_atoms_flag)
10069 n_particles = frame_set->n_particles;
10073 n_particles = tng_data->n_particles;
10076 if(tng_data->non_tr_particle_data)
10078 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
10080 if(tng_data->non_tr_particle_data[i].values)
10082 free(tng_data->non_tr_particle_data[i].values);
10083 tng_data->non_tr_particle_data[i].values = 0;
10086 if(tng_data->non_tr_particle_data[i].strings)
10088 n_values_per_frame = tng_data->non_tr_particle_data[i].
10089 n_values_per_frame;
10090 if(tng_data->non_tr_particle_data[i].strings[0])
10092 for(j = 0; j < n_particles; j++)
10094 if(tng_data->non_tr_particle_data[i].strings[0][j])
10096 for(k = 0; k < n_values_per_frame; k++)
10098 if(tng_data->non_tr_particle_data[i].
10101 free(tng_data->non_tr_particle_data[i].
10103 tng_data->non_tr_particle_data[i].
10104 strings[0][j][k] = 0;
10107 free(tng_data->non_tr_particle_data[i].
10109 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
10112 free(tng_data->non_tr_particle_data[i].strings[0]);
10113 tng_data->non_tr_particle_data[i].strings[0] = 0;
10115 free(tng_data->non_tr_particle_data[i].strings);
10116 tng_data->non_tr_particle_data[i].strings = 0;
10119 if(tng_data->non_tr_particle_data[i].block_name)
10121 free(tng_data->non_tr_particle_data[i].block_name);
10122 tng_data->non_tr_particle_data[i].block_name = 0;
10125 free(tng_data->non_tr_particle_data);
10126 tng_data->non_tr_particle_data = 0;
10129 if(tng_data->non_tr_data)
10131 for(i = 0; i < tng_data->n_data_blocks; i++)
10133 if(tng_data->non_tr_data[i].values)
10135 free(tng_data->non_tr_data[i].values);
10136 tng_data->non_tr_data[i].values = 0;
10139 if(tng_data->non_tr_data[i].strings)
10141 n_values_per_frame = tng_data->non_tr_data[i].
10142 n_values_per_frame;
10143 if(tng_data->non_tr_data[i].strings[0])
10145 for(j = 0; j < n_values_per_frame; j++)
10147 if(tng_data->non_tr_data[i].strings[0][j])
10149 free(tng_data->non_tr_data[i].strings[0][j]);
10150 tng_data->non_tr_data[i].strings[0][j] = 0;
10153 free(tng_data->non_tr_data[i].strings[0]);
10154 tng_data->non_tr_data[i].strings[0] = 0;
10156 free(tng_data->non_tr_data[i].strings);
10157 tng_data->non_tr_data[i].strings = 0;
10160 if(tng_data->non_tr_data[i].block_name)
10162 free(tng_data->non_tr_data[i].block_name);
10163 tng_data->non_tr_data[i].block_name = 0;
10166 free(tng_data->non_tr_data);
10167 tng_data->non_tr_data = 0;
10170 tng_data->n_particle_data_blocks = 0;
10171 tng_data->n_data_blocks = 0;
10173 if(tng_data->compress_algo_pos)
10175 free(tng_data->compress_algo_pos);
10176 tng_data->compress_algo_pos = 0;
10178 if(tng_data->compress_algo_vel)
10180 free(tng_data->compress_algo_vel);
10181 tng_data->compress_algo_vel = 0;
10184 if(frame_set->tr_particle_data)
10186 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10188 if(frame_set->tr_particle_data[i].values)
10190 free(frame_set->tr_particle_data[i].values);
10191 frame_set->tr_particle_data[i].values = 0;
10194 if(frame_set->tr_particle_data[i].strings)
10196 n_values_per_frame = frame_set->tr_particle_data[i].
10197 n_values_per_frame;
10198 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10200 if(frame_set->tr_particle_data[i].strings[j])
10202 for(k = 0; k < n_particles; k++)
10204 if(frame_set->tr_particle_data[i].
10207 for(l = 0; l < n_values_per_frame; l++)
10209 if(frame_set->tr_particle_data[i].
10212 free(frame_set->tr_particle_data[i].
10214 frame_set->tr_particle_data[i].
10215 strings[j][k][l] = 0;
10218 free(frame_set->tr_particle_data[i].
10220 frame_set->tr_particle_data[i].
10224 free(frame_set->tr_particle_data[i].strings[j]);
10225 frame_set->tr_particle_data[i].strings[j] = 0;
10228 free(frame_set->tr_particle_data[i].strings);
10229 frame_set->tr_particle_data[i].strings = 0;
10232 if(frame_set->tr_particle_data[i].block_name)
10234 free(frame_set->tr_particle_data[i].block_name);
10235 frame_set->tr_particle_data[i].block_name = 0;
10238 free(frame_set->tr_particle_data);
10239 frame_set->tr_particle_data = 0;
10242 if(frame_set->tr_data)
10244 for(i = 0; i < frame_set->n_data_blocks; i++)
10246 if(frame_set->tr_data[i].values)
10248 free(frame_set->tr_data[i].values);
10249 frame_set->tr_data[i].values = 0;
10252 if(frame_set->tr_data[i].strings)
10254 n_values_per_frame = frame_set->tr_data[i].
10255 n_values_per_frame;
10256 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10258 if(frame_set->tr_data[i].strings[j])
10260 for(k = 0; k < n_values_per_frame; k++)
10262 if(frame_set->tr_data[i].strings[j][k])
10264 free(frame_set->tr_data[i].strings[j][k]);
10265 frame_set->tr_data[i].strings[j][k] = 0;
10268 free(frame_set->tr_data[i].strings[j]);
10269 frame_set->tr_data[i].strings[j] = 0;
10272 free(frame_set->tr_data[i].strings);
10273 frame_set->tr_data[i].strings = 0;
10276 if(frame_set->tr_data[i].block_name)
10278 free(frame_set->tr_data[i].block_name);
10279 frame_set->tr_data[i].block_name = 0;
10282 free(frame_set->tr_data);
10283 frame_set->tr_data = 0;
10286 frame_set->n_particle_data_blocks = 0;
10287 frame_set->n_data_blocks = 0;
10289 if(tng_data->molecules)
10291 for(i = 0; i < tng_data->n_molecules; i++)
10293 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10295 free(tng_data->molecules);
10296 tng_data->molecules = 0;
10297 tng_data->n_molecules = 0;
10299 if(tng_data->molecule_cnt_list)
10301 free(tng_data->molecule_cnt_list);
10302 tng_data->molecule_cnt_list = 0;
10308 return(TNG_SUCCESS);
10311 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10312 tng_trajectory_t *dest_p)
10314 tng_trajectory_frame_set_t frame_set;
10315 tng_trajectory_t dest;
10317 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10319 *dest_p = malloc(sizeof(struct tng_trajectory));
10322 fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
10323 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10324 return(TNG_CRITICAL);
10329 frame_set = &dest->current_trajectory_frame_set;
10331 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10332 if(!dest->input_file_path)
10334 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10335 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10336 return(TNG_CRITICAL);
10338 strcpy(dest->input_file_path, src->input_file_path);
10339 dest->input_file = 0;
10340 dest->input_file_len = src->input_file_len;
10341 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10342 if(!dest->output_file_path)
10344 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10345 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10346 return(TNG_CRITICAL);
10348 strcpy(dest->output_file_path, src->output_file_path);
10349 dest->output_file = 0;
10351 dest->first_program_name = 0;
10352 dest->first_user_name = 0;
10353 dest->first_computer_name = 0;
10354 dest->first_pgp_signature = 0;
10355 dest->last_program_name = 0;
10356 dest->last_user_name = 0;
10357 dest->last_computer_name = 0;
10358 dest->last_pgp_signature = 0;
10359 dest->forcefield_name = 0;
10361 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10362 dest->first_trajectory_frame_set_input_file_pos =
10363 src->first_trajectory_frame_set_input_file_pos;
10364 dest->last_trajectory_frame_set_input_file_pos =
10365 src->last_trajectory_frame_set_input_file_pos;
10366 dest->current_trajectory_frame_set_input_file_pos =
10367 src->current_trajectory_frame_set_input_file_pos;
10368 dest->first_trajectory_frame_set_output_file_pos =
10369 src->first_trajectory_frame_set_output_file_pos;
10370 dest->last_trajectory_frame_set_output_file_pos =
10371 src->last_trajectory_frame_set_output_file_pos;
10372 dest->current_trajectory_frame_set_output_file_pos =
10373 src->current_trajectory_frame_set_output_file_pos;
10374 dest->frame_set_n_frames = src->frame_set_n_frames;
10375 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10376 dest->medium_stride_length = src->medium_stride_length;
10377 dest->long_stride_length = src->long_stride_length;
10379 dest->time_per_frame = src->time_per_frame;
10381 /* Currently the non trajectory data blocks are not copied since it
10382 * can lead to problems when freeing memory in a parallel block. */
10383 dest->n_particle_data_blocks = 0;
10384 dest->n_data_blocks = 0;
10385 dest->non_tr_particle_data = 0;
10386 dest->non_tr_data = 0;
10388 dest->compress_algo_pos = 0;
10389 dest->compress_algo_vel = 0;
10390 dest->distance_unit_exponential = -9;
10391 dest->compression_precision = 1000;
10393 frame_set->n_mapping_blocks = 0;
10394 frame_set->mappings = 0;
10395 frame_set->molecule_cnt_list = 0;
10397 frame_set->n_particle_data_blocks = 0;
10398 frame_set->n_data_blocks = 0;
10400 frame_set->tr_particle_data = 0;
10401 frame_set->tr_data = 0;
10403 frame_set->next_frame_set_file_pos = -1;
10404 frame_set->prev_frame_set_file_pos = -1;
10405 frame_set->medium_stride_next_frame_set_file_pos = -1;
10406 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10407 frame_set->long_stride_next_frame_set_file_pos = -1;
10408 frame_set->long_stride_prev_frame_set_file_pos = -1;
10409 frame_set->first_frame = -1;
10411 dest->n_molecules = 0;
10412 dest->molecules = 0;
10413 dest->molecule_cnt_list = 0;
10414 dest->n_particles = src->n_particles;
10416 dest->endianness_32 = src->endianness_32;
10417 dest->endianness_64 = src->endianness_64;
10418 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10419 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10420 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10421 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10423 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10424 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10425 dest->current_trajectory_frame_set.n_frames = 0;
10427 return(TNG_SUCCESS);
10430 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10431 char *file_name, const int max_len)
10433 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10434 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10436 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10437 file_name[max_len - 1] = 0;
10439 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10441 return(TNG_FAILURE);
10443 return(TNG_SUCCESS);
10446 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10447 const char *file_name)
10452 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10453 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10456 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10459 return(TNG_SUCCESS);
10462 if(tng_data->input_file)
10464 fclose(tng_data->input_file);
10467 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10468 temp = realloc(tng_data->input_file_path, len);
10471 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10472 __FILE__, __LINE__);
10473 free(tng_data->input_file_path);
10474 tng_data->input_file_path = 0;
10475 return(TNG_CRITICAL);
10477 tng_data->input_file_path = temp;
10479 strncpy(tng_data->input_file_path, file_name, len);
10481 return(tng_input_file_init(tng_data));
10484 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10485 char *file_name, const int max_len)
10487 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10488 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10490 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10491 file_name[max_len - 1] = 0;
10493 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10495 return(TNG_FAILURE);
10497 return(TNG_SUCCESS);
10500 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10501 const char *file_name)
10506 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10507 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10509 if(tng_data->output_file_path &&
10510 strcmp(tng_data->output_file_path, file_name) == 0)
10512 return(TNG_SUCCESS);
10515 if(tng_data->output_file)
10517 fclose(tng_data->output_file);
10520 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10521 temp = realloc(tng_data->output_file_path, len);
10524 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10525 __FILE__, __LINE__);
10526 free(tng_data->output_file_path);
10527 tng_data->output_file_path = 0;
10528 return(TNG_CRITICAL);
10530 tng_data->output_file_path = temp;
10532 strncpy(tng_data->output_file_path, file_name, len);
10534 return(tng_output_file_init(tng_data));
10537 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10538 (tng_trajectory_t tng_data,
10539 const char *file_name)
10544 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10545 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10547 if(tng_data->output_file_path &&
10548 strcmp(tng_data->output_file_path, file_name) == 0)
10550 return(TNG_SUCCESS);
10553 if(tng_data->output_file)
10555 fclose(tng_data->output_file);
10558 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10559 temp = realloc(tng_data->output_file_path, len);
10562 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10563 __FILE__, __LINE__);
10564 free(tng_data->output_file_path);
10565 tng_data->output_file_path = 0;
10566 return(TNG_CRITICAL);
10568 tng_data->output_file_path = temp;
10570 strncpy(tng_data->output_file_path, file_name, len);
10572 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10573 if(!tng_data->output_file)
10575 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10576 tng_data->output_file_path, __FILE__, __LINE__);
10577 return(TNG_CRITICAL);
10579 tng_data->input_file = tng_data->output_file;
10581 return(TNG_SUCCESS);
10584 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10585 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10587 tng_endianness_32 end_32;
10588 tng_endianness_64 end_64;
10590 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10591 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10593 if(tng_data->output_endianness_swap_func_32)
10595 /* If other endianness variants are added they must be added here as well */
10596 if(tng_data->output_endianness_swap_func_32 ==
10597 &tng_swap_byte_order_big_endian_32)
10599 end_32 = TNG_BIG_ENDIAN_32;
10601 else if(tng_data->output_endianness_swap_func_32 ==
10602 &tng_swap_byte_order_little_endian_32)
10604 end_32 = TNG_LITTLE_ENDIAN_32;
10608 return(TNG_FAILURE);
10613 end_32 = (tng_endianness_32)tng_data->endianness_32;
10616 if(tng_data->output_endianness_swap_func_64)
10618 /* If other endianness variants are added they must be added here as well */
10619 if(tng_data->output_endianness_swap_func_64 ==
10620 &tng_swap_byte_order_big_endian_64)
10622 end_64 = TNG_BIG_ENDIAN_64;
10624 else if(tng_data->output_endianness_swap_func_64 ==
10625 &tng_swap_byte_order_little_endian_64)
10627 end_64 = TNG_LITTLE_ENDIAN_64;
10631 return(TNG_FAILURE);
10636 end_64 = (tng_endianness_64)tng_data->endianness_64;
10639 if((int)end_32 != (int)end_64)
10641 return(TNG_FAILURE);
10644 if(end_32 == TNG_LITTLE_ENDIAN_32)
10646 *endianness = TNG_LITTLE_ENDIAN;
10649 else if(end_32 == TNG_BIG_ENDIAN_32)
10651 *endianness = TNG_BIG_ENDIAN;
10655 return(TNG_FAILURE);
10658 return(TNG_SUCCESS);
10661 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10662 (tng_trajectory_t tng_data,
10663 const tng_file_endianness endianness)
10665 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10667 /* Tne endianness cannot be changed if the data has already been written
10668 * to the output file. */
10669 if(ftello(tng_data->output_file) > 0)
10671 return(TNG_FAILURE);
10674 if(endianness == TNG_BIG_ENDIAN)
10676 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10678 tng_data->output_endianness_swap_func_32 = 0;
10682 tng_data->output_endianness_swap_func_32 =
10683 &tng_swap_byte_order_big_endian_32;
10685 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10687 tng_data->output_endianness_swap_func_64 = 0;
10691 tng_data->output_endianness_swap_func_64 =
10692 &tng_swap_byte_order_big_endian_64;
10694 return(TNG_SUCCESS);
10696 else if(endianness == TNG_LITTLE_ENDIAN)
10698 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10700 tng_data->output_endianness_swap_func_32 = 0;
10704 tng_data->output_endianness_swap_func_32 =
10705 &tng_swap_byte_order_little_endian_32;
10707 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10709 tng_data->output_endianness_swap_func_64 = 0;
10713 tng_data->output_endianness_swap_func_64 =
10714 &tng_swap_byte_order_little_endian_64;
10716 return(TNG_SUCCESS);
10719 /* If the specified endianness is neither big nor little endian return a
10721 return(TNG_FAILURE);
10724 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10725 (const tng_trajectory_t tng_data,
10726 char *name, const int max_len)
10728 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10729 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10731 strncpy(name, tng_data->first_program_name, max_len - 1);
10732 name[max_len - 1] = 0;
10734 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10736 return(TNG_FAILURE);
10738 return(TNG_SUCCESS);
10741 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10742 const char *new_name)
10746 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10747 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10749 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10751 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10753 free(tng_data->first_program_name);
10754 tng_data->first_program_name = 0;
10756 if(!tng_data->first_program_name)
10758 tng_data->first_program_name = malloc(len);
10759 if(!tng_data->first_program_name)
10761 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10762 __FILE__, __LINE__);
10763 return(TNG_CRITICAL);
10767 strncpy(tng_data->first_program_name, new_name, len);
10769 return(TNG_SUCCESS);
10772 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10773 (const tng_trajectory_t tng_data,
10774 char *name, const int max_len)
10776 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10777 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10779 strncpy(name, tng_data->last_program_name, max_len - 1);
10780 name[max_len - 1] = 0;
10782 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10784 return(TNG_FAILURE);
10786 return(TNG_SUCCESS);
10789 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10790 (tng_trajectory_t tng_data,
10791 const char *new_name)
10795 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10796 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10798 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10800 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10802 free(tng_data->last_program_name);
10803 tng_data->last_program_name = 0;
10805 if(!tng_data->last_program_name)
10807 tng_data->last_program_name = malloc(len);
10808 if(!tng_data->last_program_name)
10810 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10811 __FILE__, __LINE__);
10812 return(TNG_CRITICAL);
10816 strncpy(tng_data->last_program_name, new_name, len);
10818 return(TNG_SUCCESS);
10821 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10822 (const tng_trajectory_t tng_data,
10823 char *name, const int max_len)
10825 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10826 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10828 strncpy(name, tng_data->first_user_name, max_len - 1);
10829 name[max_len - 1] = 0;
10831 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10833 return(TNG_FAILURE);
10835 return(TNG_SUCCESS);
10838 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10839 (tng_trajectory_t tng_data,
10840 const char *new_name)
10844 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10845 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10847 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10849 /* If the currently stored string length is not enough to store the new
10850 * string it is freed and reallocated. */
10851 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10853 free(tng_data->first_user_name);
10854 tng_data->first_user_name = 0;
10856 if(!tng_data->first_user_name)
10858 tng_data->first_user_name = malloc(len);
10859 if(!tng_data->first_user_name)
10861 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10862 __FILE__, __LINE__);
10863 return(TNG_CRITICAL);
10867 strncpy(tng_data->first_user_name, new_name, len);
10869 return(TNG_SUCCESS);
10872 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10873 (const tng_trajectory_t tng_data,
10874 char *name, const int max_len)
10876 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10877 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10879 strncpy(name, tng_data->last_user_name, max_len - 1);
10880 name[max_len - 1] = 0;
10882 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10884 return(TNG_FAILURE);
10886 return(TNG_SUCCESS);
10889 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10890 (tng_trajectory_t tng_data,
10891 const char *new_name)
10895 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10896 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10898 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10900 /* If the currently stored string length is not enough to store the new
10901 * string it is freed and reallocated. */
10902 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10904 free(tng_data->last_user_name);
10905 tng_data->last_user_name = 0;
10907 if(!tng_data->last_user_name)
10909 tng_data->last_user_name = malloc(len);
10910 if(!tng_data->last_user_name)
10912 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10913 __FILE__, __LINE__);
10914 return(TNG_CRITICAL);
10918 strncpy(tng_data->last_user_name, new_name, len);
10920 return(TNG_SUCCESS);
10923 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10924 (const tng_trajectory_t tng_data,
10925 char *name, const int max_len)
10927 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10928 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10930 strncpy(name, tng_data->first_computer_name, max_len - 1);
10931 name[max_len - 1] = 0;
10933 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10935 return(TNG_FAILURE);
10937 return(TNG_SUCCESS);
10940 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10941 (tng_trajectory_t tng_data,
10942 const char *new_name)
10946 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10947 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10949 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10951 /* If the currently stored string length is not enough to store the new
10952 * string it is freed and reallocated. */
10953 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10955 free(tng_data->first_computer_name);
10956 tng_data->first_computer_name = 0;
10958 if(!tng_data->first_computer_name)
10960 tng_data->first_computer_name = malloc(len);
10961 if(!tng_data->first_computer_name)
10963 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10964 __FILE__, __LINE__);
10965 return(TNG_CRITICAL);
10969 strncpy(tng_data->first_computer_name, new_name, len);
10971 return(TNG_SUCCESS);
10974 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10975 (const tng_trajectory_t tng_data,
10976 char *name, const int max_len)
10978 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10979 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10981 strncpy(name, tng_data->last_computer_name, max_len - 1);
10982 name[max_len - 1] = 0;
10984 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10986 return(TNG_FAILURE);
10988 return(TNG_SUCCESS);
10991 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10992 (tng_trajectory_t tng_data,
10993 const char *new_name)
10997 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10998 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11000 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11002 /* If the currently stored string length is not enough to store the new
11003 * string it is freed and reallocated. */
11004 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
11007 free(tng_data->last_computer_name);
11008 tng_data->last_computer_name = 0;
11010 if(!tng_data->last_computer_name)
11012 tng_data->last_computer_name = malloc(len);
11013 if(!tng_data->last_computer_name)
11015 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11016 __FILE__, __LINE__);
11017 return(TNG_CRITICAL);
11021 strncpy(tng_data->last_computer_name, new_name, len);
11023 return(TNG_SUCCESS);
11026 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
11027 (const tng_trajectory_t tng_data,
11028 char *signature, const int max_len)
11030 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11031 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11033 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
11034 signature[max_len - 1] = 0;
11036 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
11038 return(TNG_FAILURE);
11040 return(TNG_SUCCESS);
11043 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
11044 (tng_trajectory_t tng_data,
11045 const char *signature)
11049 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11050 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11052 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11054 /* If the currently stored string length is not enough to store the new
11055 * string it is freed and reallocated. */
11056 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
11059 free(tng_data->first_pgp_signature);
11060 tng_data->first_pgp_signature = 0;
11062 if(!tng_data->first_pgp_signature)
11064 tng_data->first_pgp_signature = malloc(len);
11065 if(!tng_data->first_pgp_signature)
11067 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11068 __FILE__, __LINE__);
11069 return(TNG_CRITICAL);
11073 strncpy(tng_data->first_pgp_signature, signature, len);
11075 return(TNG_SUCCESS);
11078 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11079 (const tng_trajectory_t tng_data,
11080 char *signature, const int max_len)
11082 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11083 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11085 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
11086 signature[max_len - 1] = 0;
11088 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
11090 return(TNG_FAILURE);
11092 return(TNG_SUCCESS);
11095 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11096 (tng_trajectory_t tng_data,
11097 const char *signature)
11101 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11102 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11104 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11106 /* If the currently stored string length is not enough to store the new
11107 * string it is freed and reallocated. */
11108 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
11111 free(tng_data->last_pgp_signature);
11112 tng_data->last_pgp_signature = 0;
11114 if(!tng_data->last_pgp_signature)
11116 tng_data->last_pgp_signature = malloc(len);
11117 if(!tng_data->last_pgp_signature)
11119 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11120 __FILE__, __LINE__);
11121 return(TNG_CRITICAL);
11125 strncpy(tng_data->last_pgp_signature, signature, len);
11127 return(TNG_SUCCESS);
11130 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11131 (const tng_trajectory_t tng_data,
11132 char *name, const int max_len)
11134 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11135 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11137 strncpy(name, tng_data->forcefield_name, max_len - 1);
11138 name[max_len - 1] = 0;
11140 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11142 return(TNG_FAILURE);
11144 return(TNG_SUCCESS);
11147 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11148 (tng_trajectory_t tng_data,
11149 const char *new_name)
11153 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11154 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11156 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11158 /* If the currently stored string length is not enough to store the new
11159 * string it is freed and reallocated. */
11160 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11162 free(tng_data->forcefield_name);
11163 tng_data->forcefield_name = 0;
11165 if(!tng_data->forcefield_name)
11167 tng_data->forcefield_name = malloc(len);
11168 if(!tng_data->forcefield_name)
11170 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11171 __FILE__, __LINE__);
11172 return(TNG_CRITICAL);
11176 strncpy(tng_data->forcefield_name, new_name, len);
11178 return(TNG_SUCCESS);
11181 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11182 (const tng_trajectory_t tng_data,
11185 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11186 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11188 *len = tng_data->medium_stride_length;
11190 return(TNG_SUCCESS);
11193 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11194 (tng_trajectory_t tng_data,
11197 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11199 if(len >= tng_data->long_stride_length)
11201 return(TNG_FAILURE);
11203 tng_data->medium_stride_length = len;
11205 return(TNG_SUCCESS);
11208 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11209 (const tng_trajectory_t tng_data,
11212 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11213 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11215 *len = tng_data->long_stride_length;
11217 return(TNG_SUCCESS);
11220 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11221 (tng_trajectory_t tng_data,
11224 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11226 if(len <= tng_data->medium_stride_length)
11228 return(TNG_FAILURE);
11230 tng_data->long_stride_length = len;
11232 return(TNG_SUCCESS);
11235 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11236 (const tng_trajectory_t tng_data,
11239 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11240 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11242 *time = tng_data->time_per_frame;
11244 return(TNG_SUCCESS);
11247 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11248 (tng_trajectory_t tng_data,
11251 tng_trajectory_frame_set_t frame_set;
11253 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11254 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11256 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11258 return(TNG_SUCCESS);
11261 frame_set = &tng_data->current_trajectory_frame_set;
11263 /* If the current frame set is not finished write it to disk before
11264 changing time per frame. */
11265 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11267 frame_set->n_frames = frame_set->n_unwritten_frames;
11268 tng_frame_set_write(tng_data, TNG_USE_HASH);
11270 tng_data->time_per_frame = time;
11272 return(TNG_SUCCESS);
11275 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11276 (const tng_trajectory_t tng_data,
11279 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11280 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11282 *len = tng_data->input_file_len;
11284 return(TNG_SUCCESS);
11287 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11288 (const tng_trajectory_t tng_data,
11291 tng_gen_block_t block;
11292 tng_function_status stat;
11293 int64_t file_pos, last_file_pos, first_frame, n_frames;
11295 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11296 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11297 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11299 file_pos = ftello(tng_data->input_file);
11300 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11302 if(last_file_pos <= 0)
11304 return(TNG_FAILURE);
11307 tng_block_init(&block);
11308 fseeko(tng_data->input_file,
11311 /* Read block headers first to see that a frame set block is found. */
11312 stat = tng_block_header_read(tng_data, block);
11313 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11315 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11316 __FILE__, __LINE__);
11317 tng_block_destroy(&block);
11318 return(TNG_FAILURE);
11320 tng_block_destroy(&block);
11322 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11324 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11325 __FILE__, __LINE__);
11326 return(TNG_CRITICAL);
11328 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11330 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11331 __FILE__, __LINE__);
11332 return(TNG_CRITICAL);
11334 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11336 *n = first_frame + n_frames;
11338 return(TNG_SUCCESS);
11341 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11342 (const tng_trajectory_t tng_data,
11345 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11347 *precision = tng_data->compression_precision;
11349 return(TNG_SUCCESS);
11352 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11353 (tng_trajectory_t tng_data,
11354 const double precision)
11356 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11358 tng_data->compression_precision = precision;
11360 return(TNG_SUCCESS);
11363 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11364 (tng_trajectory_t tng_data,
11367 tng_molecule_t mol;
11371 tng_function_status stat;
11372 int64_t diff, n_mod, n_impl;
11374 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11376 diff = n - tng_data->n_particles;
11378 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11379 if(stat == TNG_SUCCESS)
11381 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11383 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11384 __FILE__, __LINE__);
11385 return(TNG_FAILURE);
11387 diff -= n_impl * mol->n_atoms;
11392 if(stat == TNG_SUCCESS)
11394 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11397 return(TNG_SUCCESS);
11401 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11402 fprintf(stderr, "particle count.\n");
11403 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11404 __FILE__, __LINE__);
11405 /* FIXME: Should we set the count of all other molecules to 0 and add
11406 * implicit molecules? */
11407 return(TNG_FAILURE);
11409 if(stat != TNG_SUCCESS)
11411 stat = tng_molecule_add(tng_data,
11412 "TNG_IMPLICIT_MOL",
11414 if(stat != TNG_SUCCESS)
11418 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11419 if(stat != TNG_SUCCESS)
11423 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11424 if(stat != TNG_SUCCESS)
11428 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11429 if(stat != TNG_SUCCESS)
11436 if(mol->n_atoms > 1)
11438 n_mod = diff % mol->n_atoms;
11441 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11442 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11443 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11444 __FILE__, __LINE__);
11445 return(TNG_FAILURE);
11447 diff /= mol->n_atoms;
11450 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11455 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11456 (const tng_trajectory_t tng_data,
11459 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11460 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11462 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11464 *n = tng_data->n_particles;
11468 *n = tng_data->current_trajectory_frame_set.n_particles;
11471 return(TNG_SUCCESS);
11474 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11475 (const tng_trajectory_t tng_data,
11478 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11479 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11481 *variable = tng_data->var_num_atoms_flag;
11483 return(TNG_SUCCESS);
11486 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11487 (const tng_trajectory_t tng_data,
11490 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11491 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11493 *n = tng_data->n_molecules;
11495 return(TNG_SUCCESS);
11498 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11499 (const tng_trajectory_t tng_data,
11502 int64_t *cnt_list = 0, cnt = 0, i;
11504 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11505 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11507 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11511 return(TNG_FAILURE);
11514 for(i = 0; i < tng_data->n_molecules; i++)
11516 cnt += cnt_list[i];
11521 return(TNG_SUCCESS);
11524 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11525 (const tng_trajectory_t tng_data,
11526 int64_t **mol_cnt_list)
11528 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11530 if(tng_data->var_num_atoms_flag)
11532 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11537 *mol_cnt_list = tng_data->molecule_cnt_list;
11539 if(*mol_cnt_list == 0)
11541 return(TNG_FAILURE);
11543 return(TNG_SUCCESS);
11546 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11547 (const tng_trajectory_t tng_data,
11550 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11551 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11553 *exp = tng_data->distance_unit_exponential;
11555 return(TNG_SUCCESS);
11558 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11559 (const tng_trajectory_t tng_data,
11562 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11564 tng_data->distance_unit_exponential = exp;
11566 return(TNG_SUCCESS);
11569 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11570 (const tng_trajectory_t tng_data,
11573 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11574 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11576 *n = tng_data->frame_set_n_frames;
11578 return(TNG_SUCCESS);
11581 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11582 (const tng_trajectory_t tng_data,
11585 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11587 tng_data->frame_set_n_frames = n;
11589 return(TNG_SUCCESS);
11592 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11593 (const tng_trajectory_t tng_data,
11596 int64_t long_stride_length, medium_stride_length;
11597 int64_t file_pos, orig_frame_set_file_pos;
11598 tng_trajectory_frame_set_t frame_set;
11599 struct tng_trajectory_frame_set orig_frame_set;
11600 tng_gen_block_t block;
11601 tng_function_status stat;
11604 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11605 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11607 orig_frame_set = tng_data->current_trajectory_frame_set;
11609 frame_set = &tng_data->current_trajectory_frame_set;
11611 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11612 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11616 *n = tng_data->n_trajectory_frame_sets = cnt;
11617 return(TNG_SUCCESS);
11620 tng_block_init(&block);
11621 fseeko(tng_data->input_file,
11624 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11625 /* Read block headers first to see what block is found. */
11626 stat = tng_block_header_read(tng_data, block);
11627 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11629 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11630 __FILE__, __LINE__);
11631 tng_block_destroy(&block);
11632 return(TNG_CRITICAL);
11635 if(tng_block_read_next(tng_data, block,
11636 TNG_SKIP_HASH) != TNG_SUCCESS)
11638 tng_block_destroy(&block);
11639 return(TNG_CRITICAL);
11644 long_stride_length = tng_data->long_stride_length;
11645 medium_stride_length = tng_data->medium_stride_length;
11647 /* Take long steps forward until a long step forward would be too long or
11648 * the last frame set is found */
11649 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11650 while(file_pos > 0)
11654 cnt += long_stride_length;
11655 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11656 /* Read block headers first to see what block is found. */
11657 stat = tng_block_header_read(tng_data, block);
11658 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11660 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11661 file_pos, __FILE__, __LINE__);
11662 tng_block_destroy(&block);
11663 return(TNG_CRITICAL);
11666 if(tng_block_read_next(tng_data, block,
11667 TNG_SKIP_HASH) != TNG_SUCCESS)
11669 tng_block_destroy(&block);
11670 return(TNG_CRITICAL);
11673 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11676 /* Take medium steps forward until a medium step forward would be too long
11677 * or the last frame set is found */
11678 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11679 while(file_pos > 0)
11683 cnt += medium_stride_length;
11684 fseeko(tng_data->input_file,
11687 /* Read block headers first to see what block is found. */
11688 stat = tng_block_header_read(tng_data, block);
11689 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11691 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11692 file_pos, __FILE__, __LINE__);
11693 tng_block_destroy(&block);
11694 return(TNG_CRITICAL);
11697 if(tng_block_read_next(tng_data, block,
11698 TNG_SKIP_HASH) != TNG_SUCCESS)
11700 tng_block_destroy(&block);
11701 return(TNG_CRITICAL);
11704 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11707 /* Take one step forward until the last frame set is found */
11708 file_pos = frame_set->next_frame_set_file_pos;
11709 while(file_pos > 0)
11714 fseeko(tng_data->input_file,
11717 /* Read block headers first to see what block is found. */
11718 stat = tng_block_header_read(tng_data, block);
11719 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11721 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11722 file_pos, __FILE__, __LINE__);
11723 tng_block_destroy(&block);
11724 return(TNG_CRITICAL);
11727 if(tng_block_read_next(tng_data, block,
11728 TNG_SKIP_HASH) != TNG_SUCCESS)
11730 tng_block_destroy(&block);
11731 return(TNG_CRITICAL);
11734 file_pos = frame_set->next_frame_set_file_pos;
11737 tng_block_destroy(&block);
11739 *n = tng_data->n_trajectory_frame_sets = cnt;
11741 *frame_set = orig_frame_set;
11742 /* The mapping block in the original frame set has been freed when reading
11743 * other frame sets. */
11744 frame_set->mappings = 0;
11745 frame_set->n_mapping_blocks = 0;
11747 fseeko(tng_data->input_file,
11748 tng_data->first_trajectory_frame_set_input_file_pos,
11751 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11753 return(TNG_SUCCESS);
11756 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11757 (const tng_trajectory_t tng_data,
11758 tng_trajectory_frame_set_t *frame_set_p)
11760 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11762 *frame_set_p = &tng_data->current_trajectory_frame_set;
11764 return(TNG_SUCCESS);
11767 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11768 (tng_trajectory_t tng_data,
11771 int64_t long_stride_length, medium_stride_length;
11772 int64_t file_pos, curr_nr = 0, n_frame_sets;
11773 tng_trajectory_frame_set_t frame_set;
11774 tng_gen_block_t block;
11775 tng_function_status stat;
11777 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11778 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11780 frame_set = &tng_data->current_trajectory_frame_set;
11782 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11784 if(stat != TNG_SUCCESS)
11789 if(nr >= n_frame_sets)
11791 return(TNG_FAILURE);
11794 long_stride_length = tng_data->long_stride_length;
11795 medium_stride_length = tng_data->medium_stride_length;
11797 /* FIXME: The frame set number of the current frame set is not stored */
11799 if(nr < n_frame_sets - 1 - nr)
11801 /* Start from the beginning */
11802 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11806 /* Start from the end */
11807 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11808 curr_nr = n_frame_sets - 1;
11812 return(TNG_FAILURE);
11815 tng_block_init(&block);
11816 fseeko(tng_data->input_file,
11819 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11820 /* Read block headers first to see what block is found. */
11821 stat = tng_block_header_read(tng_data, block);
11822 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11824 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11825 __FILE__, __LINE__);
11826 tng_block_destroy(&block);
11827 return(TNG_CRITICAL);
11830 if(tng_block_read_next(tng_data, block,
11831 TNG_SKIP_HASH) != TNG_SUCCESS)
11833 tng_block_destroy(&block);
11834 return(TNG_CRITICAL);
11839 tng_block_destroy(&block);
11840 return(TNG_SUCCESS);
11843 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11845 /* Take long steps forward until a long step forward would be too long or
11846 * the right frame set is found */
11847 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11849 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11852 curr_nr += long_stride_length;
11853 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11854 /* Read block headers first to see what block is found. */
11855 stat = tng_block_header_read(tng_data, block);
11856 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11858 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11859 file_pos, __FILE__, __LINE__);
11860 tng_block_destroy(&block);
11861 return(TNG_CRITICAL);
11864 if(tng_block_read_next(tng_data, block,
11865 TNG_SKIP_HASH) != TNG_SUCCESS)
11867 tng_block_destroy(&block);
11868 return(TNG_CRITICAL);
11872 tng_block_destroy(&block);
11873 return(TNG_SUCCESS);
11878 /* Take medium steps forward until a medium step forward would be too long
11879 * or the right frame set is found */
11880 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11882 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11885 curr_nr += medium_stride_length;
11886 fseeko(tng_data->input_file,
11889 /* Read block headers first to see what block is found. */
11890 stat = tng_block_header_read(tng_data, block);
11891 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11893 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11894 file_pos, __FILE__, __LINE__);
11895 tng_block_destroy(&block);
11896 return(TNG_CRITICAL);
11899 if(tng_block_read_next(tng_data, block,
11900 TNG_SKIP_HASH) != TNG_SUCCESS)
11902 tng_block_destroy(&block);
11903 return(TNG_CRITICAL);
11907 tng_block_destroy(&block);
11908 return(TNG_SUCCESS);
11913 /* Take one step forward until the right frame set is found */
11914 while(file_pos > 0 && curr_nr < nr)
11916 file_pos = frame_set->next_frame_set_file_pos;
11921 fseeko(tng_data->input_file,
11924 /* Read block headers first to see what block is found. */
11925 stat = tng_block_header_read(tng_data, block);
11926 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11928 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11929 file_pos, __FILE__, __LINE__);
11930 tng_block_destroy(&block);
11931 return(TNG_CRITICAL);
11934 if(tng_block_read_next(tng_data, block,
11935 TNG_SKIP_HASH) != TNG_SUCCESS)
11937 tng_block_destroy(&block);
11938 return(TNG_CRITICAL);
11942 tng_block_destroy(&block);
11943 return(TNG_SUCCESS);
11948 /* Take long steps backward until a long step backward would be too long
11949 * or the right frame set is found */
11950 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11952 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11955 curr_nr -= long_stride_length;
11956 fseeko(tng_data->input_file,
11959 /* Read block headers first to see what block is found. */
11960 stat = tng_block_header_read(tng_data, block);
11961 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11963 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11964 file_pos, __FILE__, __LINE__);
11965 tng_block_destroy(&block);
11966 return(TNG_CRITICAL);
11969 if(tng_block_read_next(tng_data, block,
11970 TNG_SKIP_HASH) != TNG_SUCCESS)
11972 tng_block_destroy(&block);
11973 return(TNG_CRITICAL);
11977 tng_block_destroy(&block);
11978 return(TNG_SUCCESS);
11983 /* Take medium steps backward until a medium step backward would be too long
11984 * or the right frame set is found */
11985 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11987 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11990 curr_nr -= medium_stride_length;
11991 fseeko(tng_data->input_file,
11994 /* Read block headers first to see what block is found. */
11995 stat = tng_block_header_read(tng_data, block);
11996 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11998 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11999 file_pos, __FILE__, __LINE__);
12000 tng_block_destroy(&block);
12001 return(TNG_CRITICAL);
12004 if(tng_block_read_next(tng_data, block,
12005 TNG_SKIP_HASH) != TNG_SUCCESS)
12007 tng_block_destroy(&block);
12008 return(TNG_CRITICAL);
12012 tng_block_destroy(&block);
12013 return(TNG_SUCCESS);
12018 /* Take one step backward until the right frame set is found */
12019 while(file_pos > 0 && curr_nr > nr)
12021 file_pos = frame_set->prev_frame_set_file_pos;
12025 fseeko(tng_data->input_file,
12028 /* Read block headers first to see what block is found. */
12029 stat = tng_block_header_read(tng_data, block);
12030 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12032 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12033 file_pos, __FILE__, __LINE__);
12034 tng_block_destroy(&block);
12035 return(TNG_CRITICAL);
12038 if(tng_block_read_next(tng_data, block,
12039 TNG_SKIP_HASH) != TNG_SUCCESS)
12041 tng_block_destroy(&block);
12042 return(TNG_CRITICAL);
12046 tng_block_destroy(&block);
12047 return(TNG_SUCCESS);
12052 /* If for some reason the current frame set is not yet found,
12053 * take one step forward until the right frame set is found */
12054 while(file_pos > 0 && curr_nr < nr)
12056 file_pos = frame_set->next_frame_set_file_pos;
12060 fseeko(tng_data->input_file,
12063 /* Read block headers first to see what block is found. */
12064 stat = tng_block_header_read(tng_data, block);
12065 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12067 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12068 file_pos, __FILE__, __LINE__);
12069 tng_block_destroy(&block);
12070 return(TNG_CRITICAL);
12073 if(tng_block_read_next(tng_data, block,
12074 TNG_SKIP_HASH) != TNG_SUCCESS)
12076 tng_block_destroy(&block);
12077 return(TNG_CRITICAL);
12081 tng_block_destroy(&block);
12082 return(TNG_SUCCESS);
12087 tng_block_destroy(&block);
12088 return(TNG_FAILURE);
12091 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12092 (tng_trajectory_t tng_data,
12093 const int64_t frame)
12095 int64_t first_frame, last_frame, n_frames_per_frame_set;
12096 int64_t long_stride_length, medium_stride_length;
12097 int64_t file_pos, temp_frame, n_frames;
12098 tng_trajectory_frame_set_t frame_set;
12099 tng_gen_block_t block;
12100 tng_function_status stat;
12102 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12103 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
12105 frame_set = &tng_data->current_trajectory_frame_set;
12107 tng_block_init(&block);
12109 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
12111 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12112 fseeko(tng_data->input_file,
12115 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12116 /* Read block headers first to see what block is found. */
12117 stat = tng_block_header_read(tng_data, block);
12118 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12120 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12121 file_pos, __FILE__, __LINE__);
12122 tng_block_destroy(&block);
12123 return(TNG_CRITICAL);
12126 if(tng_block_read_next(tng_data, block,
12127 TNG_SKIP_HASH) != TNG_SUCCESS)
12129 tng_block_destroy(&block);
12130 return(TNG_CRITICAL);
12134 first_frame = tng_max_i64(frame_set->first_frame, 0);
12135 last_frame = first_frame + frame_set->n_frames - 1;
12136 /* Is this the right frame set? */
12137 if(first_frame <= frame && frame <= last_frame)
12139 tng_block_destroy(&block);
12140 return(TNG_SUCCESS);
12143 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12144 long_stride_length = tng_data->long_stride_length;
12145 medium_stride_length = tng_data->medium_stride_length;
12147 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12150 if(temp_frame - first_frame > n_frames_per_frame_set)
12152 n_frames_per_frame_set = temp_frame - first_frame;
12156 tng_num_frames_get(tng_data, &n_frames);
12158 if(frame >= n_frames)
12160 tng_block_destroy(&block);
12161 return(TNG_FAILURE);
12164 if(first_frame - frame >= frame ||
12165 frame - last_frame >
12166 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12168 /* Start from the beginning */
12169 if(first_frame - frame >= frame)
12171 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12175 tng_block_destroy(&block);
12176 return(TNG_FAILURE);
12179 /* Start from the end */
12180 else if(frame - first_frame > (n_frames - 1) - frame)
12182 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12184 /* If the last frame set position is not set start from the current
12185 * frame set, since it will be closer than the first frame set. */
12187 /* Start from current */
12190 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12195 fseeko(tng_data->input_file,
12198 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12199 /* Read block headers first to see what block is found. */
12200 stat = tng_block_header_read(tng_data, block);
12201 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12203 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12204 file_pos, __FILE__, __LINE__);
12205 tng_block_destroy(&block);
12206 return(TNG_CRITICAL);
12209 if(tng_block_read_next(tng_data, block,
12210 TNG_SKIP_HASH) != TNG_SUCCESS)
12212 tng_block_destroy(&block);
12213 return(TNG_CRITICAL);
12218 first_frame = tng_max_i64(frame_set->first_frame, 0);
12219 last_frame = first_frame + frame_set->n_frames - 1;
12221 if(frame >= first_frame && frame <= last_frame)
12223 tng_block_destroy(&block);
12224 return(TNG_SUCCESS);
12227 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12229 /* Take long steps forward until a long step forward would be too long or
12230 * the right frame set is found */
12231 while(file_pos > 0 && first_frame + long_stride_length *
12232 n_frames_per_frame_set <= frame)
12234 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12237 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12238 /* Read block headers first to see what block is found. */
12239 stat = tng_block_header_read(tng_data, block);
12240 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12242 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12243 file_pos, __FILE__, __LINE__);
12244 tng_block_destroy(&block);
12245 return(TNG_CRITICAL);
12248 if(tng_block_read_next(tng_data, block,
12249 TNG_SKIP_HASH) != TNG_SUCCESS)
12251 tng_block_destroy(&block);
12252 return(TNG_CRITICAL);
12255 first_frame = tng_max_i64(frame_set->first_frame, 0);
12256 last_frame = first_frame + frame_set->n_frames - 1;
12257 if(frame >= first_frame && frame <= last_frame)
12259 tng_block_destroy(&block);
12260 return(TNG_SUCCESS);
12264 /* Take medium steps forward until a medium step forward would be too long
12265 * or the right frame set is found */
12266 while(file_pos > 0 && first_frame + medium_stride_length *
12267 n_frames_per_frame_set <= frame)
12269 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12272 fseeko(tng_data->input_file,
12275 /* Read block headers first to see what block is found. */
12276 stat = tng_block_header_read(tng_data, block);
12277 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12279 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12280 file_pos, __FILE__, __LINE__);
12281 tng_block_destroy(&block);
12282 return(TNG_CRITICAL);
12285 if(tng_block_read_next(tng_data, block,
12286 TNG_SKIP_HASH) != TNG_SUCCESS)
12288 tng_block_destroy(&block);
12289 return(TNG_CRITICAL);
12292 first_frame = tng_max_i64(frame_set->first_frame, 0);
12293 last_frame = first_frame + frame_set->n_frames - 1;
12294 if(frame >= first_frame && frame <= last_frame)
12296 tng_block_destroy(&block);
12297 return(TNG_SUCCESS);
12301 /* Take one step forward until the right frame set is found */
12302 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12304 file_pos = frame_set->next_frame_set_file_pos;
12307 fseeko(tng_data->input_file,
12310 /* Read block headers first to see what block is found. */
12311 stat = tng_block_header_read(tng_data, block);
12312 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12314 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12315 file_pos, __FILE__, __LINE__);
12316 tng_block_destroy(&block);
12317 return(TNG_CRITICAL);
12320 if(tng_block_read_next(tng_data, block,
12321 TNG_SKIP_HASH) != TNG_SUCCESS)
12323 tng_block_destroy(&block);
12324 return(TNG_CRITICAL);
12327 first_frame = tng_max_i64(frame_set->first_frame, 0);
12328 last_frame = first_frame + frame_set->n_frames - 1;
12329 if(frame >= first_frame && frame <= last_frame)
12331 tng_block_destroy(&block);
12332 return(TNG_SUCCESS);
12336 /* Take long steps backward until a long step backward would be too long
12337 * or the right frame set is found */
12338 while(file_pos > 0 && first_frame - long_stride_length *
12339 n_frames_per_frame_set >= frame)
12341 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12344 fseeko(tng_data->input_file,
12347 /* Read block headers first to see what block is found. */
12348 stat = tng_block_header_read(tng_data, block);
12349 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12351 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12352 file_pos, __FILE__, __LINE__);
12353 tng_block_destroy(&block);
12354 return(TNG_CRITICAL);
12357 if(tng_block_read_next(tng_data, block,
12358 TNG_SKIP_HASH) != TNG_SUCCESS)
12360 tng_block_destroy(&block);
12361 return(TNG_CRITICAL);
12364 first_frame = tng_max_i64(frame_set->first_frame, 0);
12365 last_frame = first_frame + frame_set->n_frames - 1;
12366 if(frame >= first_frame && frame <= last_frame)
12368 tng_block_destroy(&block);
12369 return(TNG_SUCCESS);
12373 /* Take medium steps backward until a medium step backward would be too long
12374 * or the right frame set is found */
12375 while(file_pos > 0 && first_frame - medium_stride_length *
12376 n_frames_per_frame_set >= frame)
12378 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12381 fseeko(tng_data->input_file,
12384 /* Read block headers first to see what block is found. */
12385 stat = tng_block_header_read(tng_data, block);
12386 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12388 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12389 file_pos, __FILE__, __LINE__);
12390 tng_block_destroy(&block);
12391 return(TNG_CRITICAL);
12394 if(tng_block_read_next(tng_data, block,
12395 TNG_SKIP_HASH) != TNG_SUCCESS)
12397 tng_block_destroy(&block);
12398 return(TNG_CRITICAL);
12401 first_frame = tng_max_i64(frame_set->first_frame, 0);
12402 last_frame = first_frame + frame_set->n_frames - 1;
12403 if(frame >= first_frame && frame <= last_frame)
12405 tng_block_destroy(&block);
12406 return(TNG_SUCCESS);
12410 /* Take one step backward until the right frame set is found */
12411 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12413 file_pos = frame_set->prev_frame_set_file_pos;
12416 fseeko(tng_data->input_file,
12419 /* Read block headers first to see what block is found. */
12420 stat = tng_block_header_read(tng_data, block);
12421 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12423 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12424 file_pos, __FILE__, __LINE__);
12425 tng_block_destroy(&block);
12426 return(TNG_CRITICAL);
12429 if(tng_block_read_next(tng_data, block,
12430 TNG_SKIP_HASH) != TNG_SUCCESS)
12432 tng_block_destroy(&block);
12433 return(TNG_CRITICAL);
12436 first_frame = tng_max_i64(frame_set->first_frame, 0);
12437 last_frame = first_frame + frame_set->n_frames - 1;
12438 if(frame >= first_frame && frame <= last_frame)
12440 tng_block_destroy(&block);
12441 return(TNG_SUCCESS);
12445 /* If for some reason the current frame set is not yet found,
12446 * take one step forward until the right frame set is found */
12447 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12449 file_pos = frame_set->next_frame_set_file_pos;
12452 fseeko(tng_data->input_file,
12455 /* Read block headers first to see what block is found. */
12456 stat = tng_block_header_read(tng_data, block);
12457 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12459 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12460 file_pos, __FILE__, __LINE__);
12461 tng_block_destroy(&block);
12462 return(TNG_CRITICAL);
12465 if(tng_block_read_next(tng_data, block,
12466 TNG_SKIP_HASH) != TNG_SUCCESS)
12468 tng_block_destroy(&block);
12469 return(TNG_CRITICAL);
12472 first_frame = tng_max_i64(frame_set->first_frame, 0);
12473 last_frame = first_frame + frame_set->n_frames - 1;
12474 if(frame >= first_frame && frame <= last_frame)
12476 tng_block_destroy(&block);
12477 return(TNG_SUCCESS);
12481 tng_block_destroy(&block);
12482 return(TNG_FAILURE);
12485 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12486 (const tng_trajectory_t tng_data,
12487 const tng_trajectory_frame_set_t frame_set,
12492 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12493 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12495 *pos = frame_set->next_frame_set_file_pos;
12497 return(TNG_SUCCESS);
12500 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12501 (const tng_trajectory_t tng_data,
12502 const tng_trajectory_frame_set_t frame_set,
12507 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12508 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12510 *pos = frame_set->prev_frame_set_file_pos;
12512 return(TNG_SUCCESS);
12515 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12516 (const tng_trajectory_t tng_data,
12517 const tng_trajectory_frame_set_t frame_set,
12518 int64_t *first_frame,
12519 int64_t *last_frame)
12523 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12524 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12525 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12527 *first_frame = frame_set->first_frame;
12528 *last_frame = *first_frame + frame_set->n_frames - 1;
12530 return(TNG_SUCCESS);
12533 /** Translate from the particle numbering used in a frame set to the real
12534 * particle numbering - used in the molecule description.
12535 * @param frame_set is the frame_set containing the mappings to use.
12536 * @param local is the index number of the atom in this frame set
12537 * @param real is set to the index of the atom in the molecular system.
12538 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12541 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12542 (const tng_trajectory_frame_set_t frame_set,
12543 const int64_t local,
12546 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12547 tng_particle_mapping_t mapping;
12551 return(TNG_SUCCESS);
12553 for(i = 0; i < n_blocks; i++)
12555 mapping = &frame_set->mappings[i];
12556 first = mapping->num_first_particle;
12557 if(local < first ||
12558 local >= first + mapping->n_particles)
12562 *real = mapping->real_particle_numbers[local-first];
12563 return(TNG_SUCCESS);
12566 return(TNG_FAILURE);
12569 /** Translate from the real particle numbering to the particle numbering
12570 * used in a frame set.
12571 * @param frame_set is the frame_set containing the mappings to use.
12572 * @param real is the index number of the atom in the molecular system.
12573 * @param local is set to the index of the atom in this frame set.
12574 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12577 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12578 (const tng_trajectory_frame_set_t frame_set,
12579 const int64_t real,
12582 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12583 tng_particle_mapping_t mapping;
12587 return(TNG_SUCCESS);
12589 for(i = 0; i < n_blocks; i++)
12591 mapping = &frame_set->mappings[i];
12592 for(j = mapping->n_particles; j--;)
12594 if(mapping->real_particle_numbers[j] == real)
12597 return(TNG_SUCCESS);
12601 return(TNG_FAILURE);
12605 static tng_function_status tng_file_headers_len_get
12606 (tng_trajectory_t tng_data,
12610 tng_gen_block_t block;
12612 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12614 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12616 return(TNG_CRITICAL);
12621 orig_pos = ftello(tng_data->input_file);
12623 if(!tng_data->input_file_len)
12625 fseeko(tng_data->input_file, 0, SEEK_END);
12626 tng_data->input_file_len = ftello(tng_data->input_file);
12628 fseeko(tng_data->input_file, 0, SEEK_SET);
12630 tng_block_init(&block);
12631 /* Read through the headers of non-trajectory blocks (they come before the
12632 * trajectory blocks in the file) */
12633 while (*len < tng_data->input_file_len &&
12634 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12636 block->id != TNG_TRAJECTORY_FRAME_SET)
12638 *len += block->header_contents_size + block->block_contents_size;
12639 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12642 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
12644 tng_block_destroy(&block);
12646 return(TNG_SUCCESS);
12649 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12650 (tng_trajectory_t tng_data,
12651 const char hash_mode)
12653 int64_t prev_pos = 0;
12654 tng_gen_block_t block;
12656 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12658 tng_data->n_trajectory_frame_sets = 0;
12660 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12662 return(TNG_CRITICAL);
12665 if(!tng_data->input_file_len)
12667 fseeko(tng_data->input_file, 0, SEEK_END);
12668 tng_data->input_file_len = ftello(tng_data->input_file);
12670 fseeko(tng_data->input_file, 0, SEEK_SET);
12672 tng_block_init(&block);
12673 /* Non trajectory blocks (they come before the trajectory
12674 * blocks in the file) */
12675 while (prev_pos < tng_data->input_file_len &&
12676 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12678 block->id != TNG_TRAJECTORY_FRAME_SET)
12680 tng_block_read_next(tng_data, block, hash_mode);
12681 prev_pos = ftello(tng_data->input_file);
12684 /* Go back if a trajectory block was encountered */
12685 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12687 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
12690 tng_block_destroy(&block);
12692 return(TNG_SUCCESS);
12695 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12696 (tng_trajectory_t tng_data,
12697 const char hash_mode)
12700 int64_t len, orig_len, tot_len = 0, data_start_pos;
12701 tng_function_status stat;
12702 tng_gen_block_t block;
12704 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12706 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12708 return(TNG_CRITICAL);
12711 if(tng_data->n_trajectory_frame_sets > 0)
12713 stat = tng_file_headers_len_get(tng_data, &orig_len);
12714 if(stat != TNG_SUCCESS)
12719 tng_block_init(&block);
12720 block->name = malloc(TNG_MAX_STR_LEN);
12723 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12724 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12725 tng_block_destroy(&block);
12726 return(TNG_CRITICAL);
12728 strcpy(block->name, "GENERAL INFO");
12729 tng_block_header_len_calculate(tng_data, block, &len);
12731 tng_general_info_block_len_calculate(tng_data, &len);
12733 strcpy(block->name, "MOLECULES");
12734 tng_block_header_len_calculate(tng_data, block, &len);
12736 tng_molecules_block_len_calculate(tng_data, &len);
12739 for(i = 0; i < tng_data->n_data_blocks; i++)
12741 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12742 tng_block_header_len_calculate(tng_data, block, &len);
12744 tng_data_block_len_calculate(tng_data,
12745 (tng_particle_data_t)&tng_data->non_tr_data[i],
12746 TNG_FALSE, 1, 1, 1, 0,
12747 1, 0, &data_start_pos,
12751 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12753 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12754 tng_block_header_len_calculate(tng_data, block, &len);
12756 tng_data_block_len_calculate(tng_data,
12757 &tng_data->non_tr_particle_data[i],
12758 TNG_TRUE, 1, 1, 1, 0,
12759 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12764 tng_block_destroy(&block);
12766 if(tot_len > orig_len)
12768 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12771 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12774 /* TODO: If there is already frame set data written to this file (e.g. when
12775 * appending to an already existing file we might need to move frame sets to
12776 * the end of the file. */
12778 if(tng_general_info_block_write(tng_data, hash_mode)
12781 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12782 tng_data->input_file_path, __FILE__, __LINE__);
12783 return(TNG_CRITICAL);
12786 if(tng_molecules_block_write(tng_data, hash_mode)
12789 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12790 tng_data->input_file_path, __FILE__, __LINE__);
12791 return(TNG_CRITICAL);
12794 /* FIXME: Currently writing non-trajectory data blocks here.
12795 * Should perhaps be moved. */
12796 tng_block_init(&block);
12797 for(i = 0; i < tng_data->n_data_blocks; i++)
12799 block->id = tng_data->non_tr_data[i].block_id;
12800 tng_data_block_write(tng_data, block,
12804 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12806 block->id = tng_data->non_tr_particle_data[i].block_id;
12807 tng_particle_data_block_write(tng_data, block,
12811 tng_block_destroy(&block);
12813 return(TNG_SUCCESS);
12816 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12817 tng_gen_block_t block,
12818 const char hash_mode)
12820 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12821 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12825 case TNG_TRAJECTORY_FRAME_SET:
12826 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12827 case TNG_PARTICLE_MAPPING:
12828 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12829 case TNG_GENERAL_INFO:
12830 return(tng_general_info_block_read(tng_data, block, hash_mode));
12831 case TNG_MOLECULES:
12832 return(tng_molecules_block_read(tng_data, block, hash_mode));
12834 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12836 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12840 /* Skip to the next block */
12841 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12842 return(TNG_FAILURE);
12847 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12848 (tng_trajectory_t tng_data,
12849 const char hash_mode)
12852 tng_gen_block_t block;
12853 tng_function_status stat;
12855 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12857 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12859 return(TNG_CRITICAL);
12862 file_pos = ftello(tng_data->input_file);
12864 tng_block_init(&block);
12866 if(!tng_data->input_file_len)
12868 fseeko(tng_data->input_file, 0, SEEK_END);
12869 tng_data->input_file_len = ftello(tng_data->input_file);
12870 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12873 /* Read block headers first to see what block is found. */
12874 stat = tng_block_header_read(tng_data, block);
12875 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12878 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12879 file_pos, __FILE__, __LINE__);
12880 tng_block_destroy(&block);
12881 return(TNG_CRITICAL);
12884 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12886 if(tng_block_read_next(tng_data, block,
12887 hash_mode) == TNG_SUCCESS)
12889 tng_data->n_trajectory_frame_sets++;
12890 file_pos = ftello(tng_data->input_file);
12891 /* Read all blocks until next frame set block */
12892 stat = tng_block_header_read(tng_data, block);
12893 while(file_pos < tng_data->input_file_len &&
12894 stat != TNG_CRITICAL &&
12895 block->id != TNG_TRAJECTORY_FRAME_SET &&
12898 stat = tng_block_read_next(tng_data, block,
12900 if(stat != TNG_CRITICAL)
12902 file_pos = ftello(tng_data->input_file);
12903 if(file_pos < tng_data->input_file_len)
12905 stat = tng_block_header_read(tng_data, block);
12909 if(stat == TNG_CRITICAL)
12911 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12912 file_pos, __FILE__, __LINE__);
12913 tng_block_destroy(&block);
12917 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12919 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12923 tng_block_destroy(&block);
12925 return(TNG_SUCCESS);
12929 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12930 (tng_trajectory_t tng_data,
12931 const char hash_mode,
12932 const int64_t block_id)
12935 tng_gen_block_t block;
12936 tng_function_status stat;
12937 int found_flag = 1;
12939 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12941 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12943 return(TNG_CRITICAL);
12946 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12950 /* No current frame set. This means that the first frame set must be
12953 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12958 fseeko(tng_data->input_file,
12964 return(TNG_FAILURE);
12967 tng_block_init(&block);
12969 if(!tng_data->input_file_len)
12971 fseeko(tng_data->input_file, 0, SEEK_END);
12972 tng_data->input_file_len = ftello(tng_data->input_file);
12973 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12976 /* Read block headers first to see what block is found. */
12977 stat = tng_block_header_read(tng_data, block);
12978 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12980 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12981 file_pos, __FILE__, __LINE__);
12982 tng_block_destroy(&block);
12983 return(TNG_CRITICAL);
12985 /* If the current frame set had already been read skip its block contents */
12988 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12990 /* Otherwiese read the frame set block */
12993 stat = tng_block_read_next(tng_data, block,
12995 if(stat != TNG_SUCCESS)
12997 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12998 tng_block_destroy(&block);
13002 file_pos = ftello(tng_data->input_file);
13006 /* Read only blocks of the requested ID
13007 * until next frame set block */
13008 stat = tng_block_header_read(tng_data, block);
13009 while(file_pos < tng_data->input_file_len &&
13010 stat != TNG_CRITICAL &&
13011 block->id != TNG_TRAJECTORY_FRAME_SET &&
13014 if(block->id == block_id)
13016 stat = tng_block_read_next(tng_data, block,
13018 if(stat != TNG_CRITICAL)
13020 file_pos = ftello(tng_data->input_file);
13022 if(file_pos < tng_data->input_file_len)
13024 stat = tng_block_header_read(tng_data, block);
13030 file_pos += (block->block_contents_size + block->header_contents_size);
13031 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13032 if(file_pos < tng_data->input_file_len)
13034 stat = tng_block_header_read(tng_data, block);
13038 if(stat == TNG_CRITICAL)
13040 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13041 file_pos, __FILE__, __LINE__);
13042 tng_block_destroy(&block);
13046 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13048 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13051 tng_block_destroy(&block);
13055 return(TNG_SUCCESS);
13059 return(TNG_FAILURE);
13063 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
13064 (tng_trajectory_t tng_data,
13065 const char hash_mode)
13069 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13071 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13073 return(TNG_CRITICAL);
13076 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13078 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13080 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13085 fseeko(tng_data->input_file,
13091 return(TNG_FAILURE);
13094 return(tng_frame_set_read(tng_data, hash_mode));
13097 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13098 (tng_trajectory_t tng_data,
13099 const char hash_mode,
13100 const int64_t block_id)
13103 tng_gen_block_t block;
13104 tng_function_status stat;
13106 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13108 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13110 return(TNG_CRITICAL);
13113 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13115 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13117 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13122 fseeko(tng_data->input_file,
13128 return(TNG_FAILURE);
13131 tng_block_init(&block);
13133 if(!tng_data->input_file_len)
13135 fseeko(tng_data->input_file, 0, SEEK_END);
13136 tng_data->input_file_len = ftello(tng_data->input_file);
13137 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13140 /* Read block headers first to see what block is found. */
13141 stat = tng_block_header_read(tng_data, block);
13142 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13144 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13145 file_pos, __FILE__, __LINE__);
13146 tng_block_destroy(&block);
13147 return(TNG_CRITICAL);
13150 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13152 if(tng_block_read_next(tng_data, block,
13153 hash_mode) == TNG_SUCCESS)
13155 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13158 tng_block_destroy(&block);
13163 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13164 const char hash_mode)
13167 tng_gen_block_t block;
13168 tng_trajectory_frame_set_t frame_set;
13169 tng_function_status stat;
13171 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13173 frame_set = &tng_data->current_trajectory_frame_set;
13175 if(frame_set->n_written_frames == frame_set->n_frames)
13177 return(TNG_SUCCESS);
13180 tng_data->current_trajectory_frame_set_output_file_pos =
13181 ftello(tng_data->output_file);
13182 tng_data->last_trajectory_frame_set_output_file_pos =
13183 tng_data->current_trajectory_frame_set_output_file_pos;
13185 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13187 return(TNG_FAILURE);
13190 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13192 tng_data->first_trajectory_frame_set_output_file_pos =
13193 tng_data->current_trajectory_frame_set_output_file_pos;
13196 tng_block_init(&block);
13198 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13200 tng_block_destroy(&block);
13201 return(TNG_FAILURE);
13204 /* Write non-particle data blocks */
13205 for(i = 0; i<frame_set->n_data_blocks; i++)
13207 block->id = frame_set->tr_data[i].block_id;
13208 tng_data_block_write(tng_data, block, i, hash_mode);
13210 /* Write the mapping blocks and particle data blocks*/
13211 if(frame_set->n_mapping_blocks)
13213 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13215 block->id = TNG_PARTICLE_MAPPING;
13216 if(frame_set->mappings[i].n_particles > 0)
13218 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13219 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13221 block->id = frame_set->tr_particle_data[j].block_id;
13222 tng_particle_data_block_write(tng_data, block,
13223 j, &frame_set->mappings[i],
13231 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13233 block->id = frame_set->tr_particle_data[i].block_id;
13234 tng_particle_data_block_write(tng_data, block,
13240 /* Update pointers in the general info block */
13241 stat = tng_header_pointers_update(tng_data, hash_mode);
13243 if(stat == TNG_SUCCESS)
13245 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13248 tng_block_destroy(&block);
13250 frame_set->n_unwritten_frames = 0;
13252 fflush(tng_data->output_file);
13257 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13258 (tng_trajectory_t tng_data,
13259 const char hash_mode)
13261 tng_trajectory_frame_set_t frame_set;
13263 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13265 frame_set = &tng_data->current_trajectory_frame_set;
13267 if(frame_set->n_unwritten_frames == 0)
13269 return(TNG_SUCCESS);
13271 frame_set->n_frames = frame_set->n_unwritten_frames;
13273 return(tng_frame_set_write(tng_data, hash_mode));
13276 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13277 (tng_trajectory_t tng_data,
13278 const int64_t first_frame,
13279 const int64_t n_frames)
13281 tng_gen_block_t block;
13282 tng_trajectory_frame_set_t frame_set;
13283 FILE *temp = tng_data->input_file;
13286 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13287 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13288 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13290 frame_set = &tng_data->current_trajectory_frame_set;
13292 curr_pos = ftello(tng_data->output_file);
13296 tng_file_headers_write(tng_data, TNG_USE_HASH);
13299 /* Set pointer to previous frame set to the one that was loaded
13301 * FIXME: This is a bit risky. If they are not added in order
13302 * it will be wrong. */
13303 if(tng_data->n_trajectory_frame_sets)
13305 frame_set->prev_frame_set_file_pos =
13306 tng_data->current_trajectory_frame_set_output_file_pos;
13309 tng_data->current_trajectory_frame_set_output_file_pos =
13310 ftello(tng_data->output_file);
13312 tng_data->n_trajectory_frame_sets++;
13314 /* Set the medium range pointers */
13315 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13317 frame_set->medium_stride_prev_frame_set_file_pos =
13318 tng_data->first_trajectory_frame_set_output_file_pos;
13320 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13322 /* FIXME: Currently only working if the previous frame set has its
13323 * medium stride pointer already set. This might need some fixing. */
13324 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13325 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13327 tng_block_init(&block);
13328 tng_data->input_file = tng_data->output_file;
13330 curr_pos = ftello(tng_data->output_file);
13331 fseeko(tng_data->output_file,
13332 frame_set->medium_stride_prev_frame_set_file_pos,
13335 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13337 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13338 __FILE__, __LINE__);
13339 tng_data->input_file = temp;
13340 tng_block_destroy(&block);
13341 return(TNG_CRITICAL);
13344 /* Read the next frame set from the previous frame set and one
13345 * medium stride step back */
13346 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13347 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13348 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13349 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13350 1, tng_data->output_file) == 0)
13352 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13353 tng_data->input_file = temp;
13354 tng_block_destroy(&block);
13355 return(TNG_CRITICAL);
13358 if(tng_data->input_endianness_swap_func_64)
13360 if(tng_data->input_endianness_swap_func_64(tng_data,
13361 &frame_set->medium_stride_prev_frame_set_file_pos)
13364 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13365 __FILE__, __LINE__);
13369 tng_block_destroy(&block);
13371 /* Set the long range pointers */
13372 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13374 frame_set->long_stride_prev_frame_set_file_pos =
13375 tng_data->first_trajectory_frame_set_output_file_pos;
13377 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13379 /* FIXME: Currently only working if the previous frame set has its
13380 * long stride pointer already set. This might need some fixing. */
13381 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13382 frame_set->long_stride_prev_frame_set_file_pos != 0)
13384 tng_block_init(&block);
13385 tng_data->input_file = tng_data->output_file;
13387 fseeko(tng_data->output_file,
13388 frame_set->long_stride_prev_frame_set_file_pos,
13391 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13393 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13394 __FILE__, __LINE__);
13395 tng_data->input_file = temp;
13396 tng_block_destroy(&block);
13397 return(TNG_CRITICAL);
13400 /* Read the next frame set from the previous frame set and one
13401 * long stride step back */
13402 fseeko(tng_data->output_file, block->block_contents_size - (6 *
13403 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13405 tng_block_destroy(&block);
13407 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13408 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13409 1, tng_data->output_file) == 0)
13411 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13412 tng_data->input_file = temp;
13413 return(TNG_CRITICAL);
13416 if(tng_data->input_endianness_swap_func_64)
13418 if(tng_data->input_endianness_swap_func_64(tng_data,
13419 &frame_set->long_stride_prev_frame_set_file_pos)
13422 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13423 __FILE__, __LINE__);
13430 tng_data->input_file = temp;
13431 fseeko(tng_data->output_file, curr_pos, SEEK_SET);
13435 frame_set->first_frame = first_frame;
13436 frame_set->n_frames = n_frames;
13437 frame_set->n_written_frames = 0;
13438 frame_set->n_unwritten_frames = 0;
13439 frame_set->first_frame_time = -1;
13441 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13442 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13444 tng_data->first_trajectory_frame_set_output_file_pos =
13445 tng_data->current_trajectory_frame_set_output_file_pos;
13447 /* FIXME: Should check the frame number instead of the file_pos,
13448 * in case frame sets are not in order */
13449 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13450 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13451 tng_data->last_trajectory_frame_set_output_file_pos <
13452 tng_data->current_trajectory_frame_set_output_file_pos)
13454 tng_data->last_trajectory_frame_set_output_file_pos =
13455 tng_data->current_trajectory_frame_set_output_file_pos;
13458 return(TNG_SUCCESS);
13461 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13462 (tng_trajectory_t tng_data,
13463 const int64_t first_frame,
13464 const int64_t n_frames,
13465 const double first_frame_time)
13467 tng_function_status stat;
13469 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13470 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13471 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13472 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13475 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13476 if(stat != TNG_SUCCESS)
13480 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13485 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13486 (tng_trajectory_t tng_data,
13487 const double first_frame_time)
13489 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13490 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13492 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13494 return(TNG_SUCCESS);
13497 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13498 (const tng_trajectory_t tng_data,
13501 int64_t file_pos, next_frame_set_file_pos;
13502 tng_gen_block_t block;
13503 tng_function_status stat;
13505 tng_trajectory_frame_set_t frame_set;
13507 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13508 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13509 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13511 file_pos = ftello(tng_data->input_file);
13513 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13515 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
13519 frame_set = &tng_data->current_trajectory_frame_set;
13520 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
13523 if(next_frame_set_file_pos <= 0)
13525 return(TNG_FAILURE);
13528 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
13529 /* Read block headers first to see that a frame set block is found. */
13530 tng_block_init(&block);
13531 stat = tng_block_header_read(tng_data, block);
13532 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13534 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13535 file_pos, __FILE__, __LINE__);
13536 return(TNG_CRITICAL);
13538 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13540 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13542 tng_block_destroy(&block);
13544 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13546 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13547 __FILE__, __LINE__);
13548 return(TNG_CRITICAL);
13550 fseeko(tng_data->input_file, file_pos, SEEK_SET);
13552 return(TNG_SUCCESS);
13555 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13556 (tng_trajectory_t tng_data,
13558 const char *block_name,
13559 const char datatype,
13560 const char block_type_flag,
13562 const int64_t n_values_per_frame,
13563 int64_t stride_length,
13564 const int64_t codec_id,
13567 int i, j, size, len;
13568 tng_trajectory_frame_set_t frame_set;
13569 tng_non_particle_data_t data;
13570 char **first_dim_values;
13571 char *new_data_c=new_data;
13572 int64_t n_frames_div;
13574 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13575 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13576 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13578 frame_set = &tng_data->current_trajectory_frame_set;
13580 if(stride_length <= 0)
13585 /* If the block does not exist, create it */
13586 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13588 if(tng_data_block_create(tng_data, block_type_flag) !=
13591 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13592 __FILE__, __LINE__);
13593 return(TNG_CRITICAL);
13595 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13597 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13601 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13603 data->block_id = id;
13605 data->block_name = malloc(strlen(block_name) + 1);
13606 if(!data->block_name)
13608 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13609 (int)strlen(block_name)+1, __FILE__, __LINE__);
13610 return(TNG_CRITICAL);
13612 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13615 /* FIXME: Memory leak from strings. */
13617 data->last_retrieved_frame = -1;
13620 data->datatype = datatype;
13621 data->stride_length = tng_max_i64(stride_length, 1);
13622 data->n_values_per_frame = n_values_per_frame;
13623 data->n_frames = n_frames;
13624 data->codec_id = codec_id;
13625 data->compression_multiplier = 1.0;
13626 /* FIXME: This can cause problems. */
13627 data->first_frame_with_data = frame_set->first_frame;
13631 case TNG_FLOAT_DATA:
13632 size = sizeof(float);
13635 size = sizeof(int64_t);
13637 case TNG_DOUBLE_DATA:
13639 size = sizeof(double);
13645 /* Allocate memory */
13646 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13647 n_values_per_frame) !=
13650 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13651 __FILE__, __LINE__);
13652 return(TNG_CRITICAL);
13655 if(n_frames > frame_set->n_unwritten_frames)
13657 frame_set->n_unwritten_frames = n_frames;
13660 n_frames_div = (n_frames % stride_length) ?
13661 n_frames / stride_length + 1:
13662 n_frames / stride_length;
13664 if(datatype == TNG_CHAR_DATA)
13666 for(i = 0; i < n_frames_div; i++)
13668 first_dim_values = data->strings[i];
13669 for(j = 0; j < n_values_per_frame; j++)
13671 len = tng_min_i((int)strlen(new_data_c) + 1,
13673 if(first_dim_values[j])
13675 free(first_dim_values[j]);
13677 first_dim_values[j] = malloc(len);
13678 if(!first_dim_values[j])
13680 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13681 len, __FILE__, __LINE__);
13682 return(TNG_CRITICAL);
13684 strncpy(first_dim_values[j],
13692 memcpy(data->values, new_data, size * n_frames_div *
13693 n_values_per_frame);
13697 return(TNG_SUCCESS);
13700 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13701 (tng_trajectory_t tng_data,
13703 const char *block_name,
13704 const char datatype,
13705 const char block_type_flag,
13707 const int64_t n_values_per_frame,
13708 int64_t stride_length,
13709 const int64_t num_first_particle,
13710 const int64_t n_particles,
13711 const int64_t codec_id,
13716 int64_t tot_n_particles, n_frames_div;
13717 char ***first_dim_values, **second_dim_values;
13718 tng_trajectory_frame_set_t frame_set;
13719 tng_particle_data_t data;
13720 char *new_data_c=new_data;
13722 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13723 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13724 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13725 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13726 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13729 frame_set = &tng_data->current_trajectory_frame_set;
13731 if(stride_length <= 0)
13736 /* If the block does not exist, create it */
13737 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13739 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13742 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13743 __FILE__, __LINE__);
13744 return(TNG_CRITICAL);
13746 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13748 data = &frame_set->tr_particle_data[frame_set->
13749 n_particle_data_blocks - 1];
13753 data = &tng_data->non_tr_particle_data[tng_data->
13754 n_particle_data_blocks - 1];
13756 data->block_id = id;
13758 data->block_name = malloc(strlen(block_name) + 1);
13759 if(!data->block_name)
13761 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13762 (int)strlen(block_name)+1, __FILE__, __LINE__);
13763 return(TNG_CRITICAL);
13765 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13767 data->datatype = datatype;
13770 /* FIXME: Memory leak from strings. */
13772 data->last_retrieved_frame = -1;
13775 data->stride_length = tng_max_i64(stride_length, 1);
13776 data->n_values_per_frame = n_values_per_frame;
13777 data->n_frames = n_frames;
13778 data->codec_id = codec_id;
13779 data->compression_multiplier = 1.0;
13780 /* FIXME: This can cause problems. */
13781 data->first_frame_with_data = frame_set->first_frame;
13783 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13785 tot_n_particles = frame_set->n_particles;
13789 tot_n_particles = tng_data->n_particles;
13792 /* If data values are supplied add that data to the data block. */
13795 /* Allocate memory */
13796 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13797 stride_length, tot_n_particles,
13798 n_values_per_frame) !=
13801 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13802 __FILE__, __LINE__);
13803 return(TNG_CRITICAL);
13806 if(n_frames > frame_set->n_unwritten_frames)
13808 frame_set->n_unwritten_frames = n_frames;
13811 n_frames_div = (n_frames % stride_length) ?
13812 n_frames / stride_length + 1:
13813 n_frames / stride_length;
13815 if(datatype == TNG_CHAR_DATA)
13817 for(i = 0; i < n_frames_div; i++)
13819 first_dim_values = data->strings[i];
13820 for(j = num_first_particle; j < num_first_particle + n_particles;
13823 second_dim_values = first_dim_values[j];
13824 for(k = 0; k < n_values_per_frame; k++)
13826 len = tng_min_i((int)strlen(new_data_c) + 1,
13828 if(second_dim_values[k])
13830 free(second_dim_values[k]);
13832 second_dim_values[k] = malloc(len);
13833 if(!second_dim_values[k])
13835 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13836 len, __FILE__, __LINE__);
13837 return(TNG_CRITICAL);
13839 strncpy(second_dim_values[k],
13851 size = sizeof(int64_t);
13853 case TNG_FLOAT_DATA:
13854 size = sizeof(float);
13856 case TNG_DOUBLE_DATA:
13858 size = sizeof(double);
13861 memcpy(data->values, new_data, size * n_frames_div *
13862 n_particles * n_values_per_frame);
13866 return(TNG_SUCCESS);
13869 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13870 (tng_trajectory_t tng_data,
13876 tng_trajectory_frame_set_t frame_set;
13877 tng_function_status stat;
13878 tng_particle_data_t p_data;
13879 tng_non_particle_data_t np_data;
13880 int block_type = -1;
13882 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13883 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13885 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13887 p_data = &tng_data->non_tr_particle_data[i];
13888 if(p_data->block_id == block_id)
13890 strncpy(name, p_data->block_name, max_len);
13891 name[max_len - 1] = '\0';
13892 return(TNG_SUCCESS);
13895 for(i = 0; i < tng_data->n_data_blocks; i++)
13897 np_data = &tng_data->non_tr_data[i];
13898 if(np_data->block_id == block_id)
13900 strncpy(name, np_data->block_name, max_len);
13901 name[max_len - 1] = '\0';
13902 return(TNG_SUCCESS);
13906 frame_set = &tng_data->current_trajectory_frame_set;
13908 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13909 if(stat == TNG_SUCCESS)
13911 block_type = TNG_PARTICLE_BLOCK_DATA;
13915 stat = tng_data_find(tng_data, block_id, &np_data);
13916 if(stat == TNG_SUCCESS)
13918 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13922 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13923 if(stat != TNG_SUCCESS)
13927 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13928 if(stat == TNG_SUCCESS)
13930 block_type = TNG_PARTICLE_BLOCK_DATA;
13934 stat = tng_data_find(tng_data, block_id, &np_data);
13935 if(stat == TNG_SUCCESS)
13937 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13942 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13944 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13946 p_data = &frame_set->tr_particle_data[i];
13947 if(p_data->block_id == block_id)
13949 strncpy(name, p_data->block_name, max_len);
13950 name[max_len - 1] = '\0';
13951 return(TNG_SUCCESS);
13955 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13957 for(i = 0; i < frame_set->n_data_blocks; i++)
13959 np_data = &frame_set->tr_data[i];
13960 if(np_data->block_id == block_id)
13962 strncpy(name, np_data->block_name, max_len);
13963 name[max_len - 1] = '\0';
13964 return(TNG_SUCCESS);
13969 return(TNG_FAILURE);
13972 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13973 (const tng_trajectory_t tng_data,
13975 int *block_dependency)
13978 tng_function_status stat;
13979 tng_particle_data_t p_data;
13980 tng_non_particle_data_t np_data;
13982 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13983 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13985 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13987 p_data = &tng_data->non_tr_particle_data[i];
13988 if(p_data->block_id == block_id)
13990 *block_dependency = TNG_PARTICLE_DEPENDENT;
13991 return(TNG_SUCCESS);
13994 for(i = 0; i < tng_data->n_data_blocks; i++)
13996 np_data = &tng_data->non_tr_data[i];
13997 if(np_data->block_id == block_id)
13999 *block_dependency = 0;
14000 return(TNG_SUCCESS);
14004 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14005 if(stat == TNG_SUCCESS)
14007 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
14008 return(TNG_SUCCESS);
14012 stat = tng_data_find(tng_data, block_id, &np_data);
14013 if(stat == TNG_SUCCESS)
14015 *block_dependency = TNG_FRAME_DEPENDENT;
14016 return(TNG_SUCCESS);
14020 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14021 if(stat != TNG_SUCCESS)
14025 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14026 if(stat == TNG_SUCCESS)
14028 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
14029 return(TNG_SUCCESS);
14033 stat = tng_data_find(tng_data, block_id, &np_data);
14034 if(stat == TNG_SUCCESS)
14036 *block_dependency = TNG_FRAME_DEPENDENT;
14037 return(TNG_SUCCESS);
14043 return(TNG_FAILURE);
14046 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
14047 (const tng_trajectory_t tng_data,
14049 int64_t *n_values_per_frame)
14052 tng_function_status stat;
14053 tng_particle_data_t p_data;
14054 tng_non_particle_data_t np_data;
14056 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14057 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14059 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
14061 p_data = &tng_data->non_tr_particle_data[i];
14062 if(p_data->block_id == block_id)
14064 *n_values_per_frame = p_data->n_values_per_frame;
14065 return(TNG_SUCCESS);
14068 for(i = 0; i < tng_data->n_data_blocks; i++)
14070 np_data = &tng_data->non_tr_data[i];
14071 if(np_data->block_id == block_id)
14073 *n_values_per_frame = np_data->n_values_per_frame;
14074 return(TNG_SUCCESS);
14078 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14079 if(stat == TNG_SUCCESS)
14081 *n_values_per_frame = p_data->n_values_per_frame;
14082 return(TNG_SUCCESS);
14086 stat = tng_data_find(tng_data, block_id, &np_data);
14087 if(stat == TNG_SUCCESS)
14089 *n_values_per_frame = np_data->n_values_per_frame;
14090 return(TNG_SUCCESS);
14094 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14095 if(stat != TNG_SUCCESS)
14099 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14100 if(stat == TNG_SUCCESS)
14102 *n_values_per_frame = p_data->n_values_per_frame;
14103 return(TNG_SUCCESS);
14107 stat = tng_data_find(tng_data, block_id, &np_data);
14108 if(stat == TNG_SUCCESS)
14110 *n_values_per_frame = np_data->n_values_per_frame;
14111 return(TNG_SUCCESS);
14117 return(TNG_FAILURE);
14120 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14121 (tng_trajectory_t tng_data,
14122 const int64_t frame_nr,
14123 const int64_t block_id,
14124 const void *values,
14125 const char hash_mode)
14127 int64_t header_pos, file_pos;
14128 int64_t output_file_len, n_values_per_frame, size, contents_size;
14129 int64_t header_size, temp_first, temp_last;
14130 int64_t i, last_frame, temp_current;
14131 tng_gen_block_t block;
14132 tng_trajectory_frame_set_t frame_set;
14133 FILE *temp = tng_data->input_file;
14134 struct tng_non_particle_data data;
14135 tng_function_status stat;
14136 char dependency, sparse_data, datatype;
14139 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14140 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14141 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14143 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14145 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14146 __FILE__, __LINE__);
14147 return(TNG_CRITICAL);
14150 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14151 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14152 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14153 tng_data->first_trajectory_frame_set_input_file_pos =
14154 tng_data->first_trajectory_frame_set_output_file_pos;
14155 tng_data->last_trajectory_frame_set_input_file_pos =
14156 tng_data->last_trajectory_frame_set_output_file_pos;
14157 tng_data->current_trajectory_frame_set_input_file_pos =
14158 tng_data->current_trajectory_frame_set_output_file_pos;
14160 tng_data->input_file = tng_data->output_file;
14162 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14164 frame_set = &tng_data->current_trajectory_frame_set;
14166 if(stat != TNG_SUCCESS)
14168 last_frame = frame_set->first_frame +
14169 frame_set->n_frames - 1;
14170 /* If the wanted frame would be in the frame set after the last
14171 * frame set create a new frame set. */
14172 if(stat == TNG_FAILURE &&
14173 last_frame < frame_nr)
14174 /* (last_frame < frame_nr &&
14175 tng_data->current_trajectory_frame_set.first_frame +
14176 tng_data->frame_set_n_frames >= frame_nr))*/
14178 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14180 last_frame = frame_nr - 1;
14182 tng_frame_set_new(tng_data,
14184 tng_data->frame_set_n_frames);
14185 file_pos = ftello(tng_data->output_file);
14186 fseeko(tng_data->output_file, 0, SEEK_END);
14187 output_file_len = ftello(tng_data->output_file);
14188 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14190 /* Read mapping blocks from the last frame set */
14191 tng_block_init(&block);
14193 stat = tng_block_header_read(tng_data, block);
14194 while(file_pos < output_file_len &&
14195 stat != TNG_CRITICAL &&
14196 block->id != TNG_TRAJECTORY_FRAME_SET &&
14199 if(block->id == TNG_PARTICLE_MAPPING)
14201 tng_trajectory_mapping_block_read(tng_data, block,
14206 fseeko(tng_data->output_file, block->block_contents_size,
14209 file_pos = ftello(tng_data->output_file);
14210 if(file_pos < output_file_len)
14212 stat = tng_block_header_read(tng_data, block);
14216 tng_block_destroy(&block);
14217 /* Write the frame set to disk */
14218 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14220 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14221 return(TNG_CRITICAL);
14226 tng_data->input_file = temp;
14227 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14228 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14229 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14234 tng_block_init(&block);
14236 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14238 fseeko(tng_data->output_file, 0, SEEK_END);
14239 output_file_len = ftello(tng_data->output_file);
14240 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14242 /* Read past the frame set block first */
14243 stat = tng_block_header_read(tng_data, block);
14244 if(stat == TNG_CRITICAL)
14246 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14247 file_pos, __FILE__, __LINE__);
14248 tng_block_destroy(&block);
14249 tng_data->input_file = temp;
14251 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14252 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14253 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14256 fseeko(tng_data->output_file, block->block_contents_size,
14259 /* Read all block headers until next frame set block or
14260 * until the wanted block id is found */
14261 stat = tng_block_header_read(tng_data, block);
14262 while(file_pos < output_file_len &&
14263 stat != TNG_CRITICAL &&
14264 block->id != block_id &&
14265 block->id != TNG_TRAJECTORY_FRAME_SET &&
14268 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14269 file_pos = ftello(tng_data->output_file);
14270 if(file_pos < output_file_len)
14272 stat = tng_block_header_read(tng_data, block);
14275 if(stat == TNG_CRITICAL)
14277 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14278 file_pos, __FILE__, __LINE__);
14279 tng_block_destroy(&block);
14280 tng_data->input_file = temp;
14281 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14282 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14283 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14287 contents_size = block->block_contents_size;
14288 header_size = block->header_contents_size;
14290 header_pos = ftello(tng_data->output_file) - header_size;
14291 frame_set = &tng_data->current_trajectory_frame_set;
14293 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14295 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14296 tng_block_destroy(&block);
14297 return(TNG_CRITICAL);
14299 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14301 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14302 tng_block_destroy(&block);
14303 return(TNG_CRITICAL);
14305 data.datatype = datatype;
14307 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14308 (dependency & TNG_PARTICLE_DEPENDENT))
14310 tng_block_destroy(&block);
14311 tng_data->input_file = temp;
14313 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14314 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14315 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14316 return(TNG_FAILURE);
14319 if(fread(&sparse_data, sizeof(sparse_data), 1, 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);
14326 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14327 tng_data->input_file) == 0)
14329 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14330 tng_block_destroy(&block);
14331 return(TNG_CRITICAL);
14333 if(tng_data->output_endianness_swap_func_64)
14335 if(tng_data->output_endianness_swap_func_64(tng_data,
14336 &data.n_values_per_frame)
14339 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14340 __FILE__, __LINE__);
14344 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14345 tng_data->input_file) == 0)
14347 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14348 tng_block_destroy(&block);
14349 return(TNG_CRITICAL);
14351 if(tng_data->output_endianness_swap_func_64)
14353 if(tng_data->output_endianness_swap_func_64(tng_data,
14357 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14358 __FILE__, __LINE__);
14362 if(data.codec_id != TNG_UNCOMPRESSED)
14364 if(fread(&data.compression_multiplier,
14365 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14368 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14369 tng_block_destroy(&block);
14370 return(TNG_CRITICAL);
14372 if(tng_data->output_endianness_swap_func_64)
14374 if(tng_data->output_endianness_swap_func_64(tng_data,
14375 (int64_t *)&data.compression_multiplier)
14378 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14379 __FILE__, __LINE__);
14385 data.compression_multiplier = 1;
14390 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14391 1, tng_data->input_file) == 0)
14393 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14394 tng_block_destroy(&block);
14395 return(TNG_CRITICAL);
14397 if(tng_data->output_endianness_swap_func_64)
14399 if(tng_data->output_endianness_swap_func_64(tng_data,
14400 &data.first_frame_with_data)
14403 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14404 __FILE__, __LINE__);
14408 if(fread(&data.stride_length, sizeof(data.stride_length),
14409 1, tng_data->input_file) == 0)
14411 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14412 tng_block_destroy(&block);
14413 return(TNG_CRITICAL);
14415 if(tng_data->output_endianness_swap_func_64)
14417 if(tng_data->output_endianness_swap_func_64(tng_data,
14418 &data.stride_length)
14421 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14422 __FILE__, __LINE__);
14428 data.first_frame_with_data = 0;
14429 data.stride_length = 1;
14431 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14433 tng_data->input_file = temp;
14435 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14436 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14437 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14439 switch(data.datatype)
14441 case(TNG_INT_DATA):
14442 size = sizeof(int64_t);
14444 case(TNG_FLOAT_DATA):
14445 size = sizeof(float);
14447 case(TNG_DOUBLE_DATA):
14448 size = sizeof(double);
14451 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14453 tng_block_destroy(&block);
14454 return(TNG_FAILURE);
14457 n_values_per_frame = data.n_values_per_frame;
14459 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14460 data.first_frame_with_data)) /
14461 data.stride_length;
14462 file_pos *= size * n_values_per_frame;
14464 if(file_pos > contents_size)
14466 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14468 tng_block_destroy(&block);
14469 return(TNG_FAILURE);
14472 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
14474 /* If the endianness is not big endian the data needs to be swapped */
14475 if((data.datatype == TNG_INT_DATA ||
14476 data.datatype == TNG_DOUBLE_DATA) &&
14477 tng_data->output_endianness_swap_func_64)
14479 copy = malloc(n_values_per_frame * size);
14480 memcpy(copy, values, n_values_per_frame * size);
14481 for(i = 0; i < n_values_per_frame; i++)
14483 if(tng_data->output_endianness_swap_func_64(tng_data,
14487 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14488 __FILE__, __LINE__);
14491 fwrite(copy, n_values_per_frame, size,
14492 tng_data->output_file);
14495 else if(data.datatype == TNG_FLOAT_DATA &&
14496 tng_data->output_endianness_swap_func_32)
14498 copy = malloc(n_values_per_frame * size);
14499 memcpy(copy, values, n_values_per_frame * size);
14500 for(i = 0; i < n_values_per_frame; i++)
14502 if(tng_data->output_endianness_swap_func_32(tng_data,
14506 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14507 __FILE__, __LINE__);
14510 fwrite(copy, n_values_per_frame, size,
14511 tng_data->output_file);
14517 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14520 fflush(tng_data->output_file);
14522 /* Update the number of written frames in the frame set. */
14523 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14525 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14528 /* If the last frame has been written update the hash */
14529 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14530 data.first_frame_with_data) >=
14531 frame_set->n_frames)
14533 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14537 tng_block_destroy(&block);
14539 return(TNG_SUCCESS);
14542 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14543 (tng_trajectory_t tng_data,
14544 const int64_t frame_nr,
14545 const int64_t block_id,
14546 const int64_t val_first_particle,
14547 const int64_t val_n_particles,
14548 const void *values,
14549 const char hash_mode)
14551 int64_t header_pos, file_pos, tot_n_particles;
14552 int64_t output_file_len, n_values_per_frame, size, contents_size;
14553 int64_t header_size, temp_first, temp_last;
14554 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14555 int64_t i, last_frame, temp_current;
14556 tng_gen_block_t block;
14557 tng_trajectory_frame_set_t frame_set;
14558 FILE *temp = tng_data->input_file;
14559 struct tng_particle_data data;
14560 tng_function_status stat;
14561 tng_particle_mapping_t mapping;
14562 char dependency, sparse_data, datatype;
14565 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14566 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14567 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14568 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14569 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14571 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14573 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14574 __FILE__, __LINE__);
14575 return(TNG_CRITICAL);
14578 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14579 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14580 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14581 tng_data->first_trajectory_frame_set_input_file_pos =
14582 tng_data->first_trajectory_frame_set_output_file_pos;
14583 tng_data->last_trajectory_frame_set_input_file_pos =
14584 tng_data->last_trajectory_frame_set_output_file_pos;
14585 tng_data->current_trajectory_frame_set_input_file_pos =
14586 tng_data->current_trajectory_frame_set_output_file_pos;
14588 tng_data->input_file = tng_data->output_file;
14590 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14592 frame_set = &tng_data->current_trajectory_frame_set;
14594 if(stat != TNG_SUCCESS)
14596 last_frame = frame_set->first_frame +
14597 frame_set->n_frames - 1;
14598 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14600 /* If the wanted frame would be in the frame set after the last
14601 * frame set create a new frame set. */
14602 if(stat == TNG_FAILURE &&
14603 (last_frame < frame_nr &&
14604 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14606 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14608 last_frame = frame_nr - 1;
14610 tng_frame_set_new(tng_data,
14612 tng_data->frame_set_n_frames);
14614 file_pos = ftello(tng_data->output_file);
14615 fseeko(tng_data->output_file, 0, SEEK_END);
14616 output_file_len = ftello(tng_data->output_file);
14617 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14619 /* Read mapping blocks from the last frame set */
14620 tng_block_init(&block);
14622 stat = tng_block_header_read(tng_data, block);
14623 while(file_pos < output_file_len &&
14624 stat != TNG_CRITICAL &&
14625 block->id != TNG_TRAJECTORY_FRAME_SET &&
14628 if(block->id == TNG_PARTICLE_MAPPING)
14630 tng_trajectory_mapping_block_read(tng_data, block,
14635 fseeko(tng_data->output_file, block->block_contents_size,
14638 file_pos = ftello(tng_data->output_file);
14639 if(file_pos < output_file_len)
14641 stat = tng_block_header_read(tng_data, block);
14645 tng_block_destroy(&block);
14646 /* Write the frame set to disk */
14647 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14649 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14655 tng_data->input_file = temp;
14656 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14657 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14658 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14664 tng_block_init(&block);
14666 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14668 fseeko(tng_data->output_file, 0, SEEK_END);
14669 output_file_len = ftello(tng_data->output_file);
14670 fseeko(tng_data->output_file, file_pos, SEEK_SET);
14672 /* Read past the frame set block first */
14673 stat = tng_block_header_read(tng_data, block);
14674 if(stat == TNG_CRITICAL)
14676 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14677 file_pos, __FILE__, __LINE__);
14678 tng_block_destroy(&block);
14679 tng_data->input_file = temp;
14681 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14682 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14683 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14686 fseeko(tng_data->output_file, block->block_contents_size,
14689 if(tng_data->var_num_atoms_flag)
14691 tot_n_particles = frame_set->n_particles;
14695 tot_n_particles = tng_data->n_particles;
14698 if(val_n_particles < tot_n_particles)
14700 mapping_block_end_pos = -1;
14701 /* Read all mapping blocks to find the right place to put the data */
14702 stat = tng_block_header_read(tng_data, block);
14703 while(file_pos < output_file_len &&
14704 stat != TNG_CRITICAL &&
14705 block->id != TNG_TRAJECTORY_FRAME_SET &&
14708 if(block->id == TNG_PARTICLE_MAPPING)
14710 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14714 fseeko(tng_data->output_file, block->block_contents_size,
14717 file_pos = ftello(tng_data->output_file);
14718 if(block->id == TNG_PARTICLE_MAPPING)
14720 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14721 if(val_first_particle >= mapping->num_first_particle &&
14722 val_first_particle < mapping->num_first_particle +
14723 mapping->n_particles &&
14724 val_first_particle + val_n_particles <=
14725 mapping->num_first_particle + mapping->n_particles)
14727 mapping_block_end_pos = file_pos;
14730 if(file_pos < output_file_len)
14732 stat = tng_block_header_read(tng_data, block);
14735 if(stat == TNG_CRITICAL)
14737 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14738 file_pos, __FILE__, __LINE__);
14739 tng_block_destroy(&block);
14740 tng_data->input_file = temp;
14742 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14743 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14744 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14747 if(mapping_block_end_pos < 0)
14749 tng_block_destroy(&block);
14750 tng_data->input_file = temp;
14752 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14753 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14754 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14755 return(TNG_FAILURE);
14757 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
14760 /* Read all block headers until next frame set block or
14761 * until the wanted block id is found */
14762 stat = tng_block_header_read(tng_data, block);
14763 while(file_pos < output_file_len &&
14764 stat != TNG_CRITICAL &&
14765 block->id != block_id &&
14766 block->id != TNG_PARTICLE_MAPPING &&
14767 block->id != TNG_TRAJECTORY_FRAME_SET &&
14770 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
14771 file_pos = ftello(tng_data->output_file);
14772 if(file_pos < output_file_len)
14774 stat = tng_block_header_read(tng_data, block);
14777 if(stat == TNG_CRITICAL)
14779 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14780 file_pos, __FILE__, __LINE__);
14781 tng_block_destroy(&block);
14782 tng_data->input_file = temp;
14784 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14785 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14786 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14790 contents_size = block->block_contents_size;
14791 header_size = block->header_contents_size;
14793 header_pos = ftello(tng_data->output_file) - header_size;
14794 frame_set = &tng_data->current_trajectory_frame_set;
14796 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14798 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14799 tng_block_destroy(&block);
14800 return(TNG_CRITICAL);
14803 data.datatype = datatype;
14805 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14807 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14808 tng_block_destroy(&block);
14809 return(TNG_CRITICAL);
14812 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14813 !(dependency & TNG_PARTICLE_DEPENDENT))
14815 tng_block_destroy(&block);
14816 tng_data->input_file = temp;
14818 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14819 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14820 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14821 return(TNG_FAILURE);
14824 if(fread(&sparse_data, sizeof(sparse_data), 1, 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);
14831 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14832 tng_data->input_file) == 0)
14834 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14835 tng_block_destroy(&block);
14836 return(TNG_CRITICAL);
14838 if(tng_data->output_endianness_swap_func_64)
14840 if(tng_data->output_endianness_swap_func_64(tng_data,
14841 &data.n_values_per_frame)
14844 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14845 __FILE__, __LINE__);
14849 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14850 tng_data->input_file) == 0)
14852 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14853 tng_block_destroy(&block);
14854 return(TNG_CRITICAL);
14856 if(tng_data->output_endianness_swap_func_64)
14858 if(tng_data->output_endianness_swap_func_64(tng_data,
14862 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14863 __FILE__, __LINE__);
14867 if(data.codec_id != TNG_UNCOMPRESSED)
14869 if(fread(&data.compression_multiplier,
14870 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14873 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14874 tng_block_destroy(&block);
14875 return(TNG_CRITICAL);
14878 if(tng_data->output_endianness_swap_func_64)
14880 if(tng_data->output_endianness_swap_func_64(tng_data,
14881 (int64_t *)&data.compression_multiplier)
14884 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14885 __FILE__, __LINE__);
14891 data.compression_multiplier = 1;
14896 if(fread(&data.first_frame_with_data,
14897 sizeof(data.first_frame_with_data),
14898 1, tng_data->input_file) == 0)
14900 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14901 tng_block_destroy(&block);
14902 return(TNG_CRITICAL);
14904 if(tng_data->output_endianness_swap_func_64)
14906 if(tng_data->output_endianness_swap_func_64(tng_data,
14907 &data.first_frame_with_data)
14910 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14911 __FILE__, __LINE__);
14915 if(fread(&data.stride_length, sizeof(data.stride_length),
14916 1, tng_data->input_file) == 0)
14918 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14919 tng_block_destroy(&block);
14920 return(TNG_CRITICAL);
14922 if(tng_data->output_endianness_swap_func_64)
14924 if(tng_data->output_endianness_swap_func_64(tng_data,
14925 &data.stride_length)
14928 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14929 __FILE__, __LINE__);
14935 data.first_frame_with_data = 0;
14936 data.stride_length = 1;
14938 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14940 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14941 tng_data->input_file) == 0)
14943 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14944 tng_block_destroy(&block);
14945 return(TNG_CRITICAL);
14947 if(tng_data->output_endianness_swap_func_64)
14949 if(tng_data->output_endianness_swap_func_64(tng_data,
14950 &num_first_particle)
14953 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14954 __FILE__, __LINE__);
14958 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14959 tng_data->input_file) == 0)
14961 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14962 tng_block_destroy(&block);
14963 return(TNG_CRITICAL);
14965 if(tng_data->output_endianness_swap_func_64)
14967 if(tng_data->output_endianness_swap_func_64(tng_data,
14968 &block_n_particles)
14971 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14972 __FILE__, __LINE__);
14977 tng_data->input_file = temp;
14979 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14980 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14981 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14984 switch(data.datatype)
14986 case(TNG_INT_DATA):
14987 size = sizeof(int64_t);
14989 case(TNG_FLOAT_DATA):
14990 size = sizeof(float);
14992 case(TNG_DOUBLE_DATA):
14993 size = sizeof(double);
14996 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14998 tng_block_destroy(&block);
14999 return(TNG_FAILURE);
15002 n_values_per_frame = data.n_values_per_frame;
15004 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
15005 data.first_frame_with_data)) /
15006 data.stride_length;
15007 file_pos *= block_n_particles * size * n_values_per_frame;
15009 if(file_pos > contents_size)
15011 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
15013 tng_block_destroy(&block);
15014 return(TNG_FAILURE);
15017 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
15019 /* If the endianness is not big endian the data needs to be swapped */
15020 if((data.datatype == TNG_INT_DATA ||
15021 data.datatype == TNG_DOUBLE_DATA) &&
15022 tng_data->output_endianness_swap_func_64)
15024 copy = malloc(val_n_particles * n_values_per_frame * size);
15025 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15026 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15028 if(tng_data->output_endianness_swap_func_64(tng_data,
15029 (int64_t *) copy+i)
15032 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15033 __FILE__, __LINE__);
15036 fwrite(copy, val_n_particles * n_values_per_frame, size,
15037 tng_data->output_file);
15040 else if(data.datatype == TNG_FLOAT_DATA &&
15041 tng_data->output_endianness_swap_func_32)
15043 copy = malloc(val_n_particles * n_values_per_frame * size);
15044 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15045 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15047 if(tng_data->output_endianness_swap_func_32(tng_data,
15048 (int32_t *) copy+i)
15051 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15052 __FILE__, __LINE__);
15055 fwrite(copy, val_n_particles * n_values_per_frame, size,
15056 tng_data->output_file);
15062 fwrite(values, val_n_particles * n_values_per_frame, size,
15063 tng_data->output_file);
15065 fflush(tng_data->output_file);
15067 /* Update the number of written frames in the frame set. */
15068 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
15070 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
15073 /* If the last frame has been written update the hash */
15074 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
15075 data.first_frame_with_data) >=
15076 frame_set->n_frames)
15078 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
15082 tng_block_destroy(&block);
15083 return(TNG_SUCCESS);
15086 static tng_function_status tng_data_values_alloc
15087 (const tng_trajectory_t tng_data,
15088 union data_values ***values,
15089 const int64_t n_frames,
15090 const int64_t n_values_per_frame,
15094 tng_function_status stat;
15096 if(n_frames <= 0 || n_values_per_frame <= 0)
15098 return(TNG_FAILURE);
15103 stat = tng_data_values_free(tng_data, *values, n_frames,
15104 n_values_per_frame,
15106 if(stat != TNG_SUCCESS)
15108 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15109 __FILE__, __LINE__);
15113 *values = malloc(sizeof(union data_values *) * n_frames);
15116 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
15117 sizeof(union data_values **) * n_frames,
15118 __FILE__, __LINE__);
15119 return(TNG_CRITICAL);
15123 for(i = 0; i < n_frames; i++)
15125 (*values)[i] = malloc(sizeof(union data_values) *
15126 n_values_per_frame);
15129 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
15130 sizeof(union data_values) * n_values_per_frame,
15131 __FILE__, __LINE__);
15134 return(TNG_CRITICAL);
15137 return(TNG_SUCCESS);
15140 /* FIXME: This needs ***values */
15141 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15142 (const tng_trajectory_t tng_data,
15143 union data_values **values,
15144 const int64_t n_frames,
15145 const int64_t n_values_per_frame,
15153 for(i = 0; i < n_frames; i++)
15157 if(type == TNG_CHAR_DATA)
15159 for(j = 0; j < n_values_per_frame; j++)
15163 free(values[i][j].c);
15164 values[i][j].c = 0;
15176 return(TNG_SUCCESS);
15179 static tng_function_status tng_particle_data_values_alloc
15180 (const tng_trajectory_t tng_data,
15181 union data_values ****values,
15182 const int64_t n_frames,
15183 const int64_t n_particles,
15184 const int64_t n_values_per_frame,
15188 tng_function_status stat;
15190 if(n_particles == 0 || n_values_per_frame == 0)
15192 return(TNG_FAILURE);
15197 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15198 n_particles, n_values_per_frame,
15200 if(stat != TNG_SUCCESS)
15202 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15203 __FILE__, __LINE__);
15207 *values = malloc(sizeof(union data_values **) * n_frames);
15210 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
15211 sizeof(union data_values **) * n_frames,
15212 __FILE__, __LINE__);
15213 return(TNG_CRITICAL);
15217 for(i = 0; i < n_frames; i++)
15219 (*values)[i] = malloc(sizeof(union data_values *) *
15223 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
15224 sizeof(union data_values *) * n_particles,
15225 __FILE__, __LINE__);
15228 return(TNG_CRITICAL);
15230 for(j = 0; j < n_particles; j++)
15232 (*values)[i][j] = malloc(sizeof(union data_values) *
15233 n_values_per_frame);
15234 if(!(*values)[i][j])
15236 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
15237 sizeof(union data_values *) * n_particles,
15238 __FILE__, __LINE__);
15239 tng_particle_data_values_free(tng_data, *values, n_frames,
15240 n_particles, n_values_per_frame,
15243 return(TNG_CRITICAL);
15247 return(TNG_SUCCESS);
15250 /* FIXME: This needs ****values */
15251 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15252 (const tng_trajectory_t tng_data,
15253 union data_values ***values,
15254 const int64_t n_frames,
15255 const int64_t n_particles,
15256 const int64_t n_values_per_frame,
15264 for(i = 0; i < n_frames; i++)
15268 for(j = 0; j < n_particles; j++)
15270 if(type == TNG_CHAR_DATA)
15272 for(k = 0; k < n_values_per_frame; k++)
15274 if(values[i][j][k].c)
15276 free(values[i][j][k].c);
15277 values[i][j][k].c = 0;
15281 free(values[i][j]);
15292 return(TNG_SUCCESS);
15296 tng_function_status DECLSPECDLLEXPORT tng_data_get
15297 (tng_trajectory_t tng_data,
15298 const int64_t block_id,
15299 union data_values ***values,
15301 int64_t *n_values_per_frame,
15304 int64_t i, j, file_pos, block_index;
15307 tng_non_particle_data_t data;
15308 tng_trajectory_frame_set_t frame_set;
15309 tng_gen_block_t block;
15310 tng_function_status stat;
15312 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15313 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15314 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15315 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15317 frame_set = &tng_data->current_trajectory_frame_set;
15322 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15324 tng_block_init(&block);
15325 file_pos = ftello(tng_data->input_file);
15326 /* Read all blocks until next frame set block */
15327 stat = tng_block_header_read(tng_data, block);
15328 while(file_pos < tng_data->input_file_len &&
15329 stat != TNG_CRITICAL &&
15330 block->id != TNG_TRAJECTORY_FRAME_SET &&
15333 /* Use hash by default */
15334 stat = tng_block_read_next(tng_data, block,
15336 if(stat != TNG_CRITICAL)
15338 file_pos = ftello(tng_data->input_file);
15339 if(file_pos < tng_data->input_file_len)
15341 stat = tng_block_header_read(tng_data, block);
15345 tng_block_destroy(&block);
15346 if(stat == TNG_CRITICAL)
15348 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15349 file_pos, __FILE__, __LINE__);
15353 for(i = 0; i < frame_set->n_data_blocks; i++)
15355 data = &frame_set->tr_data[i];
15356 if(data->block_id == block_id)
15362 if(block_index < 0)
15364 return(TNG_FAILURE);
15368 *n_frames = tng_max_i64(1, data->n_frames);
15369 *n_values_per_frame = data->n_values_per_frame;
15370 *type = data->datatype;
15374 if(tng_data_values_alloc(tng_data, values, *n_frames,
15375 *n_values_per_frame,
15379 return(TNG_CRITICAL);
15385 case TNG_CHAR_DATA:
15386 for(i = 0; i < *n_frames; i++)
15388 for(j = 0; j < *n_values_per_frame; j++)
15390 len = strlen(data->strings[i][j]) + 1;
15391 (*values)[i][j].c = malloc(len);
15392 strncpy((*values)[i][j].c, data->strings[i][j], len);
15397 size = sizeof(int);
15398 for(i = 0; i < *n_frames; i++)
15400 for(j = 0; j < *n_values_per_frame; j++)
15402 (*values)[i][j].i = *(int *)((char *)data->values + size *
15403 (i*(*n_values_per_frame) + j));
15407 case TNG_FLOAT_DATA:
15408 size = sizeof(float);
15409 for(i = 0; i < *n_frames; i++)
15411 for(j = 0; j < *n_values_per_frame; j++)
15413 (*values)[i][j].f = *(float *)((char *)data->values + size *
15414 (i*(*n_values_per_frame) + j));
15418 case TNG_DOUBLE_DATA:
15420 size = sizeof(double);
15421 for(i = 0; i < *n_frames; i++)
15423 for(j = 0; j < *n_values_per_frame; j++)
15425 (*values)[i][j].d = *(double *)((char *)data->values + size *
15426 (i*(*n_values_per_frame) + j));
15431 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15433 return(TNG_SUCCESS);
15436 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15437 const int64_t block_id,
15440 int64_t *stride_length,
15441 int64_t *n_values_per_frame,
15444 int64_t file_pos, data_size, n_frames_div, block_index;
15446 tng_non_particle_data_t data;
15447 tng_trajectory_frame_set_t frame_set;
15448 tng_gen_block_t block;
15450 tng_function_status stat;
15452 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15453 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15454 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15455 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15456 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15458 frame_set = &tng_data->current_trajectory_frame_set;
15463 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15465 tng_block_init(&block);
15466 file_pos = ftello(tng_data->input_file);
15467 /* Read all blocks until next frame set block */
15468 stat = tng_block_header_read(tng_data, block);
15469 while(file_pos < tng_data->input_file_len &&
15470 stat != TNG_CRITICAL &&
15471 block->id != TNG_TRAJECTORY_FRAME_SET &&
15474 /* Use hash by default */
15475 stat = tng_block_read_next(tng_data, block,
15477 if(stat != TNG_CRITICAL)
15479 file_pos = ftello(tng_data->input_file);
15480 if(file_pos < tng_data->input_file_len)
15482 stat = tng_block_header_read(tng_data, block);
15486 tng_block_destroy(&block);
15487 if(stat == TNG_CRITICAL)
15489 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15490 file_pos, __FILE__, __LINE__);
15494 for(i = 0; i < frame_set->n_data_blocks; i++)
15496 data = &frame_set->tr_data[i];
15497 if(data->block_id == block_id)
15503 if(block_index < 0)
15505 return(TNG_FAILURE);
15509 *type = data->datatype;
15513 case TNG_CHAR_DATA:
15514 return(TNG_FAILURE);
15516 size = sizeof(int64_t);
15518 case TNG_FLOAT_DATA:
15519 size = sizeof(float);
15521 case TNG_DOUBLE_DATA:
15523 size = sizeof(double);
15526 *n_frames = data->n_frames;
15527 *n_values_per_frame = data->n_values_per_frame;
15528 *stride_length = data->stride_length;
15529 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15530 *n_frames / *stride_length;
15532 data_size = n_frames_div * size *
15533 *n_values_per_frame;
15535 temp = realloc(*values, data_size);
15538 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15539 data_size, __FILE__, __LINE__);
15542 return(TNG_CRITICAL);
15547 memcpy(*values, data->values, data_size);
15549 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15551 return(TNG_SUCCESS);
15554 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15555 (tng_trajectory_t tng_data,
15556 const int64_t block_id,
15557 const int64_t start_frame_nr,
15558 const int64_t end_frame_nr,
15559 const char hash_mode,
15560 union data_values ***values,
15561 int64_t *n_values_per_frame,
15564 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15565 int64_t block_index;
15568 tng_non_particle_data_t data;
15569 tng_trajectory_frame_set_t frame_set;
15570 tng_gen_block_t block;
15571 tng_function_status stat;
15573 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15574 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15575 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15576 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15580 frame_set = &tng_data->current_trajectory_frame_set;
15581 first_frame = frame_set->first_frame;
15583 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15584 if(stat != TNG_SUCCESS)
15590 /* Do not re-read the frame set. */
15591 if(first_frame != frame_set->first_frame ||
15592 frame_set->n_data_blocks <= 0)
15594 tng_block_init(&block);
15595 file_pos = ftello(tng_data->input_file);
15596 /* Read all blocks until next frame set block */
15597 stat = tng_block_header_read(tng_data, block);
15598 while(file_pos < tng_data->input_file_len &&
15599 stat != TNG_CRITICAL &&
15600 block->id != TNG_TRAJECTORY_FRAME_SET &&
15603 stat = tng_block_read_next(tng_data, block,
15605 if(stat != TNG_CRITICAL)
15607 file_pos = ftello(tng_data->input_file);
15608 if(file_pos < tng_data->input_file_len)
15610 stat = tng_block_header_read(tng_data, block);
15614 tng_block_destroy(&block);
15615 if(stat == TNG_CRITICAL)
15617 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15618 file_pos, __FILE__, __LINE__);
15624 /* See if there is a data block of this ID.
15625 * Start checking the last read frame set */
15626 for(i = 0; i < frame_set->n_data_blocks; i++)
15628 data = &frame_set->tr_data[i];
15629 if(data->block_id == block_id)
15636 if(block_index < 0)
15638 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15639 block_id, __FILE__, __LINE__);
15640 return(TNG_FAILURE);
15643 n_frames = end_frame_nr - start_frame_nr + 1;
15644 *n_values_per_frame = data->n_values_per_frame;
15645 *type = data->datatype;
15649 if(tng_data_values_alloc(tng_data, values, n_frames,
15650 *n_values_per_frame,
15651 *type) != TNG_SUCCESS)
15653 return(TNG_CRITICAL);
15657 current_frame_pos = start_frame_nr - frame_set->first_frame;
15658 /* It's not very elegant to reuse so much of the code in the different case
15659 * statements, but it's unnecessarily slow to have the switch-case block
15660 * inside the for loops. */
15663 case TNG_CHAR_DATA:
15664 for(i=0; i<n_frames; i++)
15666 if(current_frame_pos == frame_set->n_frames)
15668 stat = tng_frame_set_read_next(tng_data, hash_mode);
15669 if(stat != TNG_SUCCESS)
15673 current_frame_pos = 0;
15675 for(j = 0; j < *n_values_per_frame; j++)
15677 len = strlen(data->strings[current_frame_pos][j]) + 1;
15678 (*values)[i][j].c = malloc(len);
15679 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15681 current_frame_pos++;
15685 size = sizeof(int);
15686 for(i=0; i<n_frames; i++)
15688 if(current_frame_pos == frame_set->n_frames)
15690 stat = tng_frame_set_read_next(tng_data, hash_mode);
15691 if(stat != TNG_SUCCESS)
15695 current_frame_pos = 0;
15697 for(j = 0; j < *n_values_per_frame; j++)
15699 (*values)[i][j].i = *(int *)((char *)data->values + size *
15700 (current_frame_pos *
15701 (*n_values_per_frame) + j));
15703 current_frame_pos++;
15706 case TNG_FLOAT_DATA:
15707 size = sizeof(float);
15708 for(i=0; i<n_frames; i++)
15710 if(current_frame_pos == frame_set->n_frames)
15712 stat = tng_frame_set_read_next(tng_data, hash_mode);
15713 if(stat != TNG_SUCCESS)
15717 current_frame_pos = 0;
15719 for(j = 0; j < *n_values_per_frame; j++)
15721 (*values)[i][j].f = *(float *)((char *)data->values + size *
15722 (current_frame_pos *
15723 (*n_values_per_frame) + j));
15725 current_frame_pos++;
15728 case TNG_DOUBLE_DATA:
15730 size = sizeof(double);
15731 for(i=0; i<n_frames; i++)
15733 if(current_frame_pos == frame_set->n_frames)
15735 stat = tng_frame_set_read_next(tng_data, hash_mode);
15736 if(stat != TNG_SUCCESS)
15740 current_frame_pos = 0;
15742 for(j = 0; j < *n_values_per_frame; j++)
15744 (*values)[i][j].d = *(double *)((char *)data->values + size *
15745 (current_frame_pos *
15746 (*n_values_per_frame) + j));
15748 current_frame_pos++;
15752 data->last_retrieved_frame = end_frame_nr;
15754 return(TNG_SUCCESS);
15757 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15758 (tng_trajectory_t tng_data,
15759 const int64_t block_id,
15760 const int64_t start_frame_nr,
15761 const int64_t end_frame_nr,
15762 const char hash_mode,
15764 int64_t *stride_length,
15765 int64_t *n_values_per_frame,
15768 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15769 int64_t file_pos, current_frame_pos, data_size, frame_size;
15770 int64_t last_frame_pos;
15772 tng_trajectory_frame_set_t frame_set;
15773 tng_non_particle_data_t np_data;
15774 tng_gen_block_t block;
15775 void *current_values = 0, *temp;
15776 tng_function_status stat;
15778 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15779 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15780 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15781 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15782 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15784 frame_set = &tng_data->current_trajectory_frame_set;
15785 first_frame = frame_set->first_frame;
15787 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15788 if(stat != TNG_SUCCESS)
15793 /* Do not re-read the frame set and only need the requested block. */
15794 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15795 stat = tng_data_find(tng_data, block_id, &np_data);
15796 if(first_frame != frame_set->first_frame ||
15797 stat != TNG_SUCCESS)
15799 tng_block_init(&block);
15800 if(stat != TNG_SUCCESS)
15802 fseeko(tng_data->input_file,
15803 tng_data->current_trajectory_frame_set_input_file_pos,
15805 stat = tng_block_header_read(tng_data, block);
15806 if(stat != TNG_SUCCESS)
15808 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15809 __FILE__, __LINE__);
15813 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15815 file_pos = ftello(tng_data->input_file);
15816 /* Read until next frame set block */
15817 stat = tng_block_header_read(tng_data, block);
15818 while(file_pos < tng_data->input_file_len &&
15819 stat != TNG_CRITICAL &&
15820 block->id != TNG_TRAJECTORY_FRAME_SET &&
15823 if(block->id == block_id)
15825 stat = tng_block_read_next(tng_data, block,
15827 if(stat != TNG_CRITICAL)
15829 file_pos = ftello(tng_data->input_file);
15830 if(file_pos < tng_data->input_file_len)
15832 stat = tng_block_header_read(tng_data, block);
15838 file_pos += block->block_contents_size + block->header_contents_size;
15839 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
15840 if(file_pos < tng_data->input_file_len)
15842 stat = tng_block_header_read(tng_data, block);
15846 tng_block_destroy(&block);
15847 if(stat == TNG_CRITICAL)
15849 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15850 file_pos, __FILE__, __LINE__);
15855 stat = tng_data_find(tng_data, block_id, &np_data);
15856 if(stat != TNG_SUCCESS)
15861 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15862 &n_frames, stride_length,
15863 n_values_per_frame, type);
15865 if(stat != TNG_SUCCESS)
15869 free(current_values);
15874 if(n_frames == 1 && n_frames < frame_set->n_frames)
15880 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15885 case TNG_CHAR_DATA:
15886 return(TNG_FAILURE);
15888 size = sizeof(int64_t);
15890 case TNG_FLOAT_DATA:
15891 size = sizeof(float);
15893 case TNG_DOUBLE_DATA:
15895 size = sizeof(double);
15898 n_frames_div = (tot_n_frames % *stride_length) ?
15899 tot_n_frames / *stride_length + 1:
15900 tot_n_frames / *stride_length;
15901 data_size = n_frames_div * size * (*n_values_per_frame);
15903 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15904 size, n_frames_div, data_size);
15906 temp = realloc(*values, data_size);
15909 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15910 data_size, __FILE__, __LINE__);
15913 return(TNG_CRITICAL);
15918 if( n_frames == 1 && n_frames < frame_set->n_frames)
15920 memcpy(*values, current_values, size * (*n_values_per_frame));
15924 current_frame_pos = start_frame_nr - frame_set->first_frame;
15926 frame_size = size * (*n_values_per_frame);
15928 last_frame_pos = tng_min_i64(n_frames,
15929 end_frame_nr - start_frame_nr);
15931 n_frames_div = current_frame_pos / *stride_length;
15932 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15933 last_frame_pos / *stride_length + 1:
15934 last_frame_pos / *stride_length;
15935 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15937 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15938 n_frames_div_2 * frame_size);
15940 current_frame_pos += n_frames - current_frame_pos;
15942 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15944 stat = tng_frame_set_read_next(tng_data, hash_mode);
15945 if(stat != TNG_SUCCESS)
15949 free(current_values);
15956 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15957 &n_frames, stride_length,
15958 n_values_per_frame, type);
15960 if(stat != TNG_SUCCESS)
15964 free(current_values);
15971 last_frame_pos = tng_min_i64(n_frames,
15972 end_frame_nr - current_frame_pos);
15974 n_frames_div = current_frame_pos / *stride_length;
15975 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15976 last_frame_pos / *stride_length + 1:
15977 last_frame_pos / *stride_length;
15978 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15980 memcpy(((char *)*values) + n_frames_div * frame_size,
15982 n_frames_div_2 * frame_size);
15984 current_frame_pos += n_frames;
15990 free(current_values);
15993 np_data->last_retrieved_frame = end_frame_nr;
15995 return(TNG_SUCCESS);
15998 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15999 (tng_trajectory_t tng_data,
16000 const int64_t block_id,
16001 union data_values ****values,
16003 int64_t *n_particles,
16004 int64_t *n_values_per_frame,
16007 int64_t i, j, k, mapping, file_pos, i_step, block_index;
16010 tng_particle_data_t data;
16011 tng_trajectory_frame_set_t frame_set;
16012 tng_gen_block_t block;
16013 char block_type_flag;
16014 tng_function_status stat;
16016 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16017 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
16018 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16019 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16020 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16022 frame_set = &tng_data->current_trajectory_frame_set;
16027 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16029 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16031 block_type_flag = TNG_TRAJECTORY_BLOCK;
16035 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16038 tng_block_init(&block);
16039 file_pos = ftello(tng_data->input_file);
16040 /* Read all blocks until next frame set block */
16041 stat = tng_block_header_read(tng_data, block);
16042 while(file_pos < tng_data->input_file_len &&
16043 stat != TNG_CRITICAL &&
16044 block->id != TNG_TRAJECTORY_FRAME_SET &&
16047 /* Use hash by default */
16048 stat = tng_block_read_next(tng_data, block,
16050 if(stat != TNG_CRITICAL)
16052 file_pos = ftello(tng_data->input_file);
16053 if(file_pos < tng_data->input_file_len)
16055 stat = tng_block_header_read(tng_data, block);
16059 tng_block_destroy(&block);
16060 if(stat == TNG_CRITICAL)
16062 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16063 file_pos, __FILE__, __LINE__);
16067 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16069 data = &frame_set->tr_particle_data[i];
16070 if(data->block_id == block_id)
16073 block_type_flag = TNG_TRAJECTORY_BLOCK;
16077 if(block_index < 0)
16079 return(TNG_FAILURE);
16084 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16086 block_type_flag = TNG_TRAJECTORY_BLOCK;
16090 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16094 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16095 tng_data->var_num_atoms_flag)
16097 *n_particles = frame_set->n_particles;
16101 *n_particles = tng_data->n_particles;
16104 *n_frames = tng_max_i64(1, data->n_frames);
16105 *n_values_per_frame = data->n_values_per_frame;
16106 *type = data->datatype;
16110 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16111 *n_particles, *n_values_per_frame,
16115 return(TNG_CRITICAL);
16119 /* It's not very elegant to reuse so much of the code in the different case
16120 * statements, but it's unnecessarily slow to have the switch-case block
16121 * inside the for loops. */
16124 case TNG_CHAR_DATA:
16125 for(i = 0; i < *n_frames; i++)
16127 for(j = 0; j < *n_particles; j++)
16129 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16130 for(k = 0; k < *n_values_per_frame; k++)
16132 len = strlen(data->strings[i][j][k]) + 1;
16133 (*values)[i][mapping][k].c = malloc(len);
16134 strncpy((*values)[i][mapping][k].c,
16135 data->strings[i][j][k], len);
16141 size = sizeof(int);
16142 i_step = (*n_particles) * (*n_values_per_frame);
16143 for(i = 0; i < *n_frames; i++)
16145 for(j = 0; j < *n_particles; j++)
16147 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16148 for(k = 0; k < *n_values_per_frame; k++)
16150 (*values)[i][mapping][k].i = *(int *)
16151 ((char *)data->values + size *
16153 (*n_values_per_frame) + k));
16158 case TNG_FLOAT_DATA:
16159 size = sizeof(float);
16160 i_step = (*n_particles) * (*n_values_per_frame);
16161 for(i = 0; i < *n_frames; i++)
16163 for(j = 0; j < *n_particles; j++)
16165 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16166 for(k = 0; k < *n_values_per_frame; k++)
16168 (*values)[i][mapping][k].f = *(float *)
16169 ((char *)data->values + size *
16171 (*n_values_per_frame) + k));
16176 case TNG_DOUBLE_DATA:
16178 size = sizeof(double);
16179 i_step = (*n_particles) * (*n_values_per_frame);
16180 for(i = 0; i < *n_frames; i++)
16182 for(j = 0; j < *n_particles; j++)
16184 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16185 for(k = 0; k < *n_values_per_frame; k++)
16187 (*values)[i][mapping][k].d = *(double *)
16188 ((char *)data->values + size *
16190 (*n_values_per_frame) + k));
16196 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16198 return(TNG_SUCCESS);
16201 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16202 (tng_trajectory_t tng_data,
16203 const int64_t block_id,
16206 int64_t *stride_length,
16207 int64_t *n_particles,
16208 int64_t *n_values_per_frame,
16211 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16212 int64_t block_index;
16214 tng_particle_data_t data;
16215 tng_trajectory_frame_set_t frame_set;
16216 tng_gen_block_t block;
16218 char block_type_flag;
16219 tng_function_status stat;
16221 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16222 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16223 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16224 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16225 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16227 frame_set = &tng_data->current_trajectory_frame_set;
16232 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16234 tng_block_init(&block);
16235 file_pos = ftello(tng_data->input_file);
16236 /* Read all blocks until next frame set block */
16237 stat = tng_block_header_read(tng_data, block);
16238 while(file_pos < tng_data->input_file_len &&
16239 stat != TNG_CRITICAL &&
16240 block->id != TNG_TRAJECTORY_FRAME_SET &&
16243 /* Use hash by default */
16244 stat = tng_block_read_next(tng_data, block,
16246 if(stat != TNG_CRITICAL)
16248 file_pos = ftello(tng_data->input_file);
16249 if(file_pos < tng_data->input_file_len)
16251 stat = tng_block_header_read(tng_data, block);
16255 tng_block_destroy(&block);
16256 if(stat == TNG_CRITICAL)
16258 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16259 file_pos, __FILE__, __LINE__);
16263 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16265 data = &frame_set->tr_particle_data[i];
16266 if(data->block_id == block_id)
16272 if(block_index < 0)
16274 return(TNG_FAILURE);
16278 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16280 block_type_flag = TNG_TRAJECTORY_BLOCK;
16284 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16287 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16288 tng_data->var_num_atoms_flag)
16290 *n_particles = frame_set->n_particles;
16294 *n_particles = tng_data->n_particles;
16297 *type = data->datatype;
16301 case TNG_CHAR_DATA:
16302 return(TNG_FAILURE);
16304 size = sizeof(int64_t);
16306 case TNG_FLOAT_DATA:
16307 size = sizeof(float);
16309 case TNG_DOUBLE_DATA:
16311 size = sizeof(double);
16314 *n_frames = tng_max_i64(1, data->n_frames);
16315 *n_values_per_frame = data->n_values_per_frame;
16316 *stride_length = data->stride_length;
16318 n_frames_div = (*n_frames % *stride_length) ?
16319 *n_frames / *stride_length + 1:
16320 *n_frames / *stride_length;
16322 data_size = n_frames_div * size * (*n_particles) *
16323 (*n_values_per_frame);
16325 temp = realloc(*values, data_size);
16328 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16329 data_size, __FILE__, __LINE__);
16332 return(TNG_CRITICAL);
16337 if(frame_set->n_mapping_blocks <= 0)
16339 memcpy(*values, data->values, data_size);
16343 i_step = (*n_particles) * (*n_values_per_frame);
16344 for(i = 0; i < *n_frames; i++)
16346 for(j = 0; j < *n_particles; j++)
16348 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16349 memcpy(((char *)*values) + size * (i * i_step + mapping *
16350 (*n_values_per_frame)),
16351 (char *)data->values + size *
16352 (i * i_step + j * (*n_values_per_frame)),
16353 size * (*n_values_per_frame));
16358 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16360 return(TNG_SUCCESS);
16363 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16364 (tng_trajectory_t tng_data,
16365 const int64_t block_id,
16366 const int64_t start_frame_nr,
16367 const int64_t end_frame_nr,
16368 const char hash_mode,
16369 union data_values ****values,
16370 int64_t *n_particles,
16371 int64_t *n_values_per_frame,
16374 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16375 int64_t first_frame, block_index;
16378 tng_particle_data_t data;
16379 tng_trajectory_frame_set_t frame_set;
16380 tng_gen_block_t block;
16381 char block_type_flag;
16382 tng_function_status stat;
16384 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16385 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16386 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16387 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16388 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16392 frame_set = &tng_data->current_trajectory_frame_set;
16393 first_frame = frame_set->first_frame;
16395 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16396 if(stat != TNG_SUCCESS)
16401 /* Do not re-read the frame set. */
16402 if(first_frame != frame_set->first_frame ||
16403 frame_set->n_particle_data_blocks <= 0)
16405 tng_block_init(&block);
16406 file_pos = ftello(tng_data->input_file);
16407 /* Read all blocks until next frame set block */
16408 stat = tng_block_header_read(tng_data, block);
16409 while(file_pos < tng_data->input_file_len &&
16410 stat != TNG_CRITICAL &&
16411 block->id != TNG_TRAJECTORY_FRAME_SET &&
16414 stat = tng_block_read_next(tng_data, block,
16416 if(stat != TNG_CRITICAL)
16418 file_pos = ftello(tng_data->input_file);
16419 if(file_pos < tng_data->input_file_len)
16421 stat = tng_block_header_read(tng_data, block);
16425 tng_block_destroy(&block);
16426 if(stat == TNG_CRITICAL)
16428 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16429 file_pos, __FILE__, __LINE__);
16434 /* See if there is already a data block of this ID.
16435 * Start checking the last read frame set */
16436 for(i = frame_set->n_particle_data_blocks; i-- ;)
16438 data = &frame_set->tr_particle_data[i];
16439 if(data->block_id == block_id)
16442 block_type_flag = TNG_TRAJECTORY_BLOCK;
16447 if(block_index < 0)
16449 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16450 block_id, __FILE__, __LINE__);
16451 return(TNG_FAILURE);
16454 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16455 tng_data->var_num_atoms_flag)
16457 *n_particles = frame_set->n_particles;
16461 *n_particles = tng_data->n_particles;
16464 n_frames = end_frame_nr - start_frame_nr + 1;
16465 *n_values_per_frame = data->n_values_per_frame;
16466 *type = data->datatype;
16470 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16471 *n_particles, *n_values_per_frame,
16475 return(TNG_CRITICAL);
16479 current_frame_pos = start_frame_nr - frame_set->first_frame;
16480 /* It's not very elegant to reuse so much of the code in the different case
16481 * statements, but it's unnecessarily slow to have the switch-case block
16482 * inside the for loops. */
16485 case TNG_CHAR_DATA:
16486 for(i=0; i<n_frames; i++)
16488 if(current_frame_pos == frame_set->n_frames)
16490 stat = tng_frame_set_read_next(tng_data, hash_mode);
16491 if(stat != TNG_SUCCESS)
16495 current_frame_pos = 0;
16497 for(j = 0; j < *n_particles; j++)
16499 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16500 for(k = 0; k < *n_values_per_frame; k++)
16502 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16503 (*values)[i][mapping][k].c = malloc(len);
16504 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16507 current_frame_pos++;
16511 size = sizeof(int);
16512 i_step = (*n_particles) * (*n_values_per_frame);
16513 for(i=0; i<n_frames; i++)
16515 if(current_frame_pos == frame_set->n_frames)
16517 stat = tng_frame_set_read_next(tng_data, hash_mode);
16518 if(stat != TNG_SUCCESS)
16522 current_frame_pos = 0;
16524 for(j = 0; j < *n_particles; j++)
16526 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16527 for(k = 0; k < *n_values_per_frame; k++)
16529 (*values)[i][mapping][k].i = *(int *)
16530 ((char *)data->values + size *
16531 (current_frame_pos *
16533 (*n_values_per_frame) + k));
16536 current_frame_pos++;
16539 case TNG_FLOAT_DATA:
16540 size = sizeof(float);
16541 i_step = (*n_particles) * (*n_values_per_frame);
16542 for(i=0; i<n_frames; i++)
16544 if(current_frame_pos == frame_set->n_frames)
16546 stat = tng_frame_set_read_next(tng_data, hash_mode);
16547 if(stat != TNG_SUCCESS)
16551 current_frame_pos = 0;
16553 for(j=0; j<*n_particles; j++)
16555 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16556 for(k=0; k<*n_values_per_frame; k++)
16558 (*values)[i][mapping][k].f = *(float *)
16559 ((char *)data->values + size *
16560 (current_frame_pos *
16562 (*n_values_per_frame) + k));
16565 current_frame_pos++;
16568 case TNG_DOUBLE_DATA:
16570 size = sizeof(double);
16571 i_step = (*n_particles) * (*n_values_per_frame);
16572 for(i=0; i<n_frames; i++)
16574 if(current_frame_pos == frame_set->n_frames)
16576 stat = tng_frame_set_read_next(tng_data, hash_mode);
16577 if(stat != TNG_SUCCESS)
16581 current_frame_pos = 0;
16583 for(j=0; j<*n_particles; j++)
16585 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16586 for(k=0; k<*n_values_per_frame; k++)
16588 (*values)[i][mapping][k].d = *(double *)
16589 ((char *)data->values + size *
16590 (current_frame_pos *
16592 (*n_values_per_frame) + k));
16595 current_frame_pos++;
16599 data->last_retrieved_frame = end_frame_nr;
16601 return(TNG_SUCCESS);
16604 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16605 (tng_trajectory_t tng_data,
16606 const int64_t block_id,
16607 const int64_t start_frame_nr,
16608 const int64_t end_frame_nr,
16609 const char hash_mode,
16611 int64_t *n_particles,
16612 int64_t *stride_length,
16613 int64_t *n_values_per_frame,
16616 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16617 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16619 tng_trajectory_frame_set_t frame_set;
16620 tng_particle_data_t p_data;
16621 tng_gen_block_t block;
16622 void *current_values = 0, *temp;
16623 tng_function_status stat;
16625 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16626 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16627 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16628 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16629 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16630 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16632 frame_set = &tng_data->current_trajectory_frame_set;
16633 first_frame = frame_set->first_frame;
16635 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16636 if(stat != TNG_SUCCESS)
16641 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16642 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16643 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16644 if(first_frame != frame_set->first_frame ||
16645 stat != TNG_SUCCESS)
16647 tng_block_init(&block);
16648 if(stat != TNG_SUCCESS)
16650 fseeko(tng_data->input_file,
16651 tng_data->current_trajectory_frame_set_input_file_pos,
16653 stat = tng_block_header_read(tng_data, block);
16654 if(stat != TNG_SUCCESS)
16656 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16657 __FILE__, __LINE__);
16661 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16663 file_pos = ftello(tng_data->input_file);
16664 /* Read until next frame set block */
16665 stat = tng_block_header_read(tng_data, block);
16666 while(file_pos < tng_data->input_file_len &&
16667 stat != TNG_CRITICAL &&
16668 block->id != TNG_TRAJECTORY_FRAME_SET &&
16671 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16673 stat = tng_block_read_next(tng_data, block,
16675 if(stat != TNG_CRITICAL)
16677 file_pos = ftello(tng_data->input_file);
16678 if(file_pos < tng_data->input_file_len)
16680 stat = tng_block_header_read(tng_data, block);
16686 file_pos += block->block_contents_size + block->header_contents_size;
16687 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
16688 if(file_pos < tng_data->input_file_len)
16690 stat = tng_block_header_read(tng_data, block);
16694 tng_block_destroy(&block);
16695 if(stat == TNG_CRITICAL)
16697 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16698 file_pos, __FILE__, __LINE__);
16702 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16703 if(stat != TNG_SUCCESS)
16708 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16709 &n_frames, stride_length, n_particles,
16710 n_values_per_frame, type);
16712 if(stat != TNG_SUCCESS || *n_particles == 0)
16716 free(current_values);
16721 if(n_frames == 1 && n_frames < frame_set->n_frames)
16727 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16732 case TNG_CHAR_DATA:
16733 return(TNG_FAILURE);
16735 size = sizeof(int64_t);
16737 case TNG_FLOAT_DATA:
16738 size = sizeof(float);
16740 case TNG_DOUBLE_DATA:
16742 size = sizeof(double);
16745 n_frames_div = (tot_n_frames % *stride_length) ?
16746 tot_n_frames / *stride_length + 1:
16747 tot_n_frames / *stride_length;
16749 data_size = n_frames_div * size * (*n_particles) *
16750 (*n_values_per_frame);
16752 temp = realloc(*values, data_size);
16755 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16756 data_size, __FILE__, __LINE__);
16759 return(TNG_CRITICAL);
16764 if( n_frames == 1 && n_frames < frame_set->n_frames)
16766 memcpy(*values, current_values, size * (*n_particles) *
16767 (*n_values_per_frame));
16771 current_frame_pos = start_frame_nr - frame_set->first_frame;
16773 frame_size = size * (*n_particles) * (*n_values_per_frame);
16775 last_frame_pos = tng_min_i64(n_frames,
16776 end_frame_nr - start_frame_nr);
16778 n_frames_div = current_frame_pos / *stride_length;
16779 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16780 last_frame_pos / *stride_length + 1:
16781 last_frame_pos / *stride_length;
16782 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16784 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16785 n_frames_div_2 * frame_size);
16787 current_frame_pos += n_frames - current_frame_pos;
16789 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16791 stat = tng_frame_set_read_next(tng_data, hash_mode);
16792 if(stat != TNG_SUCCESS)
16796 free(current_values);
16803 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16804 &n_frames, stride_length, n_particles,
16805 n_values_per_frame, type);
16807 if(stat != TNG_SUCCESS)
16811 free(current_values);
16818 last_frame_pos = tng_min_i64(n_frames,
16819 end_frame_nr - current_frame_pos);
16821 n_frames_div = current_frame_pos / *stride_length;
16822 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16823 last_frame_pos / *stride_length + 1:
16824 last_frame_pos / *stride_length;
16825 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16827 memcpy(((char *)*values) + n_frames_div * frame_size,
16829 n_frames_div_2 * frame_size);
16831 current_frame_pos += n_frames;
16837 free(current_values);
16840 p_data->last_retrieved_frame = end_frame_nr;
16842 return(TNG_SUCCESS);
16845 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16846 (const tng_trajectory_t tng_data,
16847 const int64_t block_id,
16849 int64_t *stride_length)
16851 tng_function_status stat;
16852 tng_non_particle_data_t np_data;
16853 tng_particle_data_t p_data;
16854 int64_t orig_file_pos, file_pos;
16855 int is_particle_data;
16857 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16864 stat = tng_frame_set_of_frame_find(tng_data, frame);
16865 if(stat != TNG_SUCCESS)
16870 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16871 stat = tng_data_find(tng_data, block_id, &np_data);
16872 if(stat != TNG_SUCCESS)
16874 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16875 if(stat != TNG_SUCCESS)
16877 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16878 /* If no specific frame was required read until this data block is found */
16881 file_pos = ftello(tng_data->input_file);
16882 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16884 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16885 file_pos = ftello(tng_data->input_file);
16888 if(stat != TNG_SUCCESS)
16890 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16894 stat = tng_data_find(tng_data, block_id, &np_data);
16895 if(stat != TNG_SUCCESS)
16897 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16898 if(stat != TNG_SUCCESS)
16900 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16906 is_particle_data = 1;
16911 is_particle_data = 0;
16916 is_particle_data = 1;
16921 is_particle_data = 0;
16923 if(is_particle_data)
16925 *stride_length = p_data->stride_length;
16929 *stride_length = np_data->stride_length;
16931 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16933 return(TNG_SUCCESS);
16936 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16937 (const tng_trajectory_t tng_data,
16940 struct tm *time_data;
16943 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16944 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16946 secs = tng_data->time;
16948 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16949 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16950 "%4d-%02d-%02d %02d:%02d:%02d",
16951 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16952 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16954 return(TNG_SUCCESS);
16958 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16959 (const char *filename,
16961 tng_trajectory_t *tng_data_p)
16963 tng_function_status stat;
16965 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16967 if(mode != 'r' && mode != 'w' && mode != 'a')
16969 return(TNG_FAILURE);
16972 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16974 tng_trajectory_destroy(tng_data_p);
16975 return(TNG_CRITICAL);
16978 if(mode == 'r' || mode == 'a')
16980 tng_input_file_set(*tng_data_p, filename);
16982 /* Read the file headers */
16983 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16985 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16987 if(stat != TNG_SUCCESS)
16995 tng_output_file_set(*tng_data_p, filename);
16997 else if(mode == 'a')
16999 if((*tng_data_p)->output_file)
17001 fclose((*tng_data_p)->output_file);
17003 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
17004 fseeko((*tng_data_p)->input_file,
17005 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
17008 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
17009 if(stat != TNG_SUCCESS)
17011 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
17012 __FILE__, __LINE__);
17014 (*tng_data_p)->output_file = 0;
17016 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
17017 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
17018 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
17019 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
17020 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
17021 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
17022 if((*tng_data_p)->input_file)
17024 fclose((*tng_data_p)->input_file);
17025 (*tng_data_p)->input_file = 0;
17027 if((*tng_data_p)->input_file_path)
17029 free((*tng_data_p)->input_file_path);
17030 (*tng_data_p)->input_file_path = 0;
17032 tng_output_append_file_set(*tng_data_p, filename);
17034 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
17037 return(TNG_SUCCESS);
17040 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
17041 (tng_trajectory_t *tng_data_p)
17043 tng_trajectory_frame_set_t frame_set;
17045 if(tng_data_p == 0)
17047 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
17048 __FILE__, __LINE__);
17049 return(TNG_FAILURE);
17052 if(*tng_data_p == 0)
17054 return(TNG_SUCCESS);
17057 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
17059 if(frame_set->n_unwritten_frames > 0)
17061 frame_set->n_frames = frame_set->n_unwritten_frames;
17062 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
17065 return(tng_trajectory_destroy(tng_data_p));
17068 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
17069 (tng_trajectory_t tng_data,
17070 const int64_t frame_nr,
17073 int64_t first_frame;
17074 tng_trajectory_frame_set_t frame_set;
17075 tng_function_status stat;
17077 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17078 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
17080 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
17081 if(stat != TNG_SUCCESS)
17083 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
17084 frame_nr, __FILE__, __LINE__);
17088 frame_set = &tng_data->current_trajectory_frame_set;
17089 first_frame = frame_set->first_frame;
17091 if(tng_data->time_per_frame <= 0)
17093 return(TNG_FAILURE);
17096 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
17098 return(TNG_SUCCESS);
17102 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17103 (tng_trajectory_t tng_data,
17105 int64_t **molecule_cnt_list,
17106 tng_molecule_t *mols)
17108 tng_trajectory_frame_set_t frame_set;
17110 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17111 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17113 *n_mols = tng_data->n_molecules;
17115 frame_set = &tng_data->current_trajectory_frame_set;
17116 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17118 *molecule_cnt_list = frame_set->molecule_cnt_list;
17122 *molecule_cnt_list = tng_data->molecule_cnt_list;
17125 *mols = tng_data->molecules;
17127 return(TNG_SUCCESS);
17131 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17132 (tng_trajectory_t tng_data,
17135 tng_molecule_t *mol)
17137 tng_function_status stat;
17139 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17140 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17142 stat = tng_molecule_add(tng_data, name, mol);
17143 if(stat != TNG_SUCCESS)
17147 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17152 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17153 (tng_trajectory_t tng_data,
17154 const tng_molecule_t mol,
17155 int64_t *n_particles,
17160 char ***chain_names,
17161 int64_t **chain_ids)
17169 *n_particles = mol->n_atoms;
17171 *names = malloc(sizeof(char *) * *n_particles);
17172 *types = malloc(sizeof(char *) * *n_particles);
17173 *res_names = malloc(sizeof(char *) * *n_particles);
17174 *chain_names = malloc(sizeof(char *) * *n_particles);
17175 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17176 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17178 for(i = 0; i < *n_particles; i++)
17180 atom = &mol->atoms[i];
17181 res = atom->residue;
17182 chain = res->chain;
17183 (*names)[i] = malloc(strlen(atom->name));
17184 strcpy(*names[i], atom->name);
17185 (*types)[i] = malloc(strlen(atom->atom_type));
17186 strcpy(*types[i], atom->atom_type);
17187 (*res_names)[i] = malloc(strlen(res->name));
17188 strcpy(*res_names[i], res->name);
17189 (*chain_names)[i] = malloc(strlen(chain->name));
17190 strcpy(*chain_names[i], chain->name);
17191 (*res_ids)[i] = res->id;
17192 (*chain_ids)[i] = chain->id;
17195 return(TNG_SUCCESS);
17198 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17199 (tng_trajectory_t tng_data,
17200 tng_molecule_t mol,
17201 const int64_t n_particles,
17202 const char **names,
17203 const char **types,
17204 const char **res_names,
17205 const int64_t *res_ids,
17206 const char **chain_names,
17207 const int64_t *chain_ids)
17211 tng_residue_t residue;
17213 tng_function_status stat;
17215 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17216 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17217 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17218 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17219 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17220 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17221 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17223 for(i = 0; i < n_particles; i++)
17225 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17226 &chain) == TNG_FAILURE)
17228 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17230 if(stat != TNG_SUCCESS)
17235 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17236 &residue) == TNG_FAILURE)
17238 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17240 if(stat != TNG_SUCCESS)
17245 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17246 if(stat != TNG_SUCCESS)
17251 return(TNG_SUCCESS);
17254 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17255 (tng_trajectory_t tng_data,
17256 float **positions, int64_t *stride_length)
17258 int64_t n_frames, n_particles, n_values_per_frame;
17260 tng_function_status stat;
17262 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17263 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17264 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17266 stat = tng_num_frames_get(tng_data, &n_frames);
17267 if(stat != TNG_SUCCESS)
17272 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17273 0, n_frames - 1, TNG_USE_HASH,
17274 (void **)positions,
17277 &n_values_per_frame,
17283 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17284 (tng_trajectory_t tng_data,
17285 float **velocities, int64_t *stride_length)
17287 int64_t n_frames, n_particles, n_values_per_frame;
17289 tng_function_status stat;
17291 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17292 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17293 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17295 stat = tng_num_frames_get(tng_data, &n_frames);
17296 if(stat != TNG_SUCCESS)
17301 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17302 0, n_frames - 1, TNG_USE_HASH,
17303 (void **)velocities,
17306 &n_values_per_frame,
17312 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17313 (tng_trajectory_t tng_data,
17314 float **forces, int64_t *stride_length)
17316 int64_t n_frames, n_particles, n_values_per_frame;
17318 tng_function_status stat;
17320 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17321 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17322 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17324 stat = tng_num_frames_get(tng_data, &n_frames);
17325 if(stat != TNG_SUCCESS)
17330 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17331 0, n_frames - 1, TNG_USE_HASH,
17335 &n_values_per_frame,
17341 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17342 (tng_trajectory_t tng_data,
17344 int64_t *stride_length)
17346 int64_t n_frames, n_values_per_frame;
17348 tng_function_status stat;
17350 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17351 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17352 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17354 stat = tng_num_frames_get(tng_data, &n_frames);
17355 if(stat != TNG_SUCCESS)
17360 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17361 0, n_frames - 1, TNG_USE_HASH,
17362 (void **)box_shape,
17364 &n_values_per_frame,
17370 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17371 (tng_trajectory_t tng_data,
17372 const int64_t block_id,
17375 int64_t *retrieved_frame_number,
17376 double *retrieved_time)
17378 tng_trajectory_frame_set_t frame_set;
17379 tng_particle_data_t data = 0;
17380 tng_function_status stat;
17382 int64_t i, data_size, n_particles, file_pos;
17385 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17386 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17387 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17388 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17389 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17391 frame_set = &tng_data->current_trajectory_frame_set;
17393 stat = tng_particle_data_find(tng_data, block_id, &data);
17394 if(stat != TNG_SUCCESS)
17396 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17397 file_pos = ftello(tng_data->input_file);
17398 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17400 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17401 file_pos = ftello(tng_data->input_file);
17403 if(stat != TNG_SUCCESS)
17407 stat = tng_particle_data_find(tng_data, block_id, &data);
17408 if(stat != TNG_SUCCESS)
17413 if(data->last_retrieved_frame < 0)
17415 fseeko(tng_data->input_file,
17416 tng_data->first_trajectory_frame_set_input_file_pos,
17418 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17419 if(stat != TNG_SUCCESS)
17423 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17424 if(stat != TNG_SUCCESS)
17429 i = data->first_frame_with_data;
17433 if(data->n_frames == 1)
17435 i = data->last_retrieved_frame + 1;
17439 i = data->last_retrieved_frame + data->stride_length;
17441 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17443 stat = tng_frame_set_of_frame_find(tng_data, i);
17444 if(stat != TNG_SUCCESS)
17446 /* If the frame set search found the frame set after the starting
17447 * frame set there is a gap in the frame sets. So, even if the frame
17448 * was not found the next frame with data is still in the found
17450 if(stat == TNG_CRITICAL)
17454 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17456 return(TNG_FAILURE);
17458 i = frame_set->first_frame;
17461 if(data->last_retrieved_frame < frame_set->first_frame)
17463 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17464 if(stat != TNG_SUCCESS)
17470 data->last_retrieved_frame = i;
17471 *retrieved_frame_number = i;
17472 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17474 *retrieved_time = frame_set->first_frame_time +
17475 (i - frame_set->first_frame) *
17476 tng_data->time_per_frame;
17480 *retrieved_time = 0;
17483 if(data->stride_length > 1)
17485 i = (i - data->first_frame_with_data) / data->stride_length;
17489 i = (i - frame_set->first_frame);
17492 tng_num_particles_get(tng_data, &n_particles);
17494 *data_type = data->datatype;
17498 case TNG_CHAR_DATA:
17499 return(TNG_FAILURE);
17501 size = sizeof(int64_t);
17503 case TNG_FLOAT_DATA:
17504 size = sizeof(float);
17506 case TNG_DOUBLE_DATA:
17508 size = sizeof(double);
17511 data_size = size * n_particles * data->n_values_per_frame;
17513 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17514 // i, data_size, size, n_particles, data->n_values_per_frame);
17516 temp = realloc(*values, data_size);
17519 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17520 data_size, __FILE__, __LINE__);
17523 return(TNG_CRITICAL);
17528 memcpy(*values, (char *)data->values + i * data_size, data_size);
17530 return(TNG_SUCCESS);
17533 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17534 (tng_trajectory_t tng_data,
17535 const int64_t block_id,
17538 int64_t *retrieved_frame_number,
17539 double *retrieved_time)
17541 tng_trajectory_frame_set_t frame_set;
17542 tng_non_particle_data_t data = 0;
17543 tng_function_status stat;
17545 int64_t i, data_size, file_pos;
17548 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17549 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17550 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17551 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17552 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17554 frame_set = &tng_data->current_trajectory_frame_set;
17556 stat = tng_data_find(tng_data, block_id, &data);
17557 if(stat != TNG_SUCCESS)
17559 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17560 file_pos = ftello(tng_data->input_file);
17561 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17563 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17564 file_pos = ftello(tng_data->input_file);
17566 if(stat != TNG_SUCCESS)
17570 stat = tng_data_find(tng_data, block_id, &data);
17571 if(stat != TNG_SUCCESS)
17576 if(data->last_retrieved_frame < 0)
17578 fseeko(tng_data->input_file,
17579 tng_data->first_trajectory_frame_set_input_file_pos,
17581 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17582 if(stat != TNG_SUCCESS)
17586 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17587 if(stat != TNG_SUCCESS)
17592 i = data->first_frame_with_data;
17596 if(data->n_frames == 1)
17598 i = data->last_retrieved_frame + 1;
17602 i = data->last_retrieved_frame + data->stride_length;
17604 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17606 stat = tng_frame_set_of_frame_find(tng_data, i);
17607 if(stat != TNG_SUCCESS)
17609 /* If the frame set search found the frame set after the starting
17610 * frame set there is a gap in the frame sets. So, even if the frame
17611 * was not found the next frame with data is still in the found
17613 if(stat == TNG_CRITICAL)
17617 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17619 return(TNG_FAILURE);
17621 i = frame_set->first_frame;
17624 if(data->last_retrieved_frame < frame_set->first_frame)
17626 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17627 if(stat != TNG_SUCCESS)
17633 data->last_retrieved_frame = i;
17634 *retrieved_frame_number = i;
17635 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17637 *retrieved_time = frame_set->first_frame_time +
17638 (i - frame_set->first_frame) *
17639 tng_data->time_per_frame;
17643 *retrieved_time = 0;
17646 if(data->stride_length > 1)
17648 i = (i - data->first_frame_with_data) / data->stride_length;
17652 i = (i - frame_set->first_frame);
17655 *data_type = data->datatype;
17659 case TNG_CHAR_DATA:
17660 return(TNG_FAILURE);
17662 size = sizeof(int64_t);
17664 case TNG_FLOAT_DATA:
17665 size = sizeof(float);
17667 case TNG_DOUBLE_DATA:
17669 size = sizeof(double);
17672 data_size = size * data->n_values_per_frame;
17674 temp = realloc(*values, data_size);
17677 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17678 data_size, __FILE__, __LINE__);
17681 return(TNG_CRITICAL);
17686 memcpy(*values, (char *)data->values + i * data_size, data_size);
17688 return(TNG_SUCCESS);
17691 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17692 (tng_trajectory_t tng_data,
17693 const int64_t first_frame,
17694 const int64_t last_frame,
17696 int64_t *stride_length)
17698 int64_t n_particles, n_values_per_frame;
17700 tng_function_status stat;
17702 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17703 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17704 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17705 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17707 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17708 first_frame, last_frame,
17710 (void **)positions,
17713 &n_values_per_frame,
17719 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17720 (tng_trajectory_t tng_data,
17721 const int64_t first_frame,
17722 const int64_t last_frame,
17723 float **velocities,
17724 int64_t *stride_length)
17726 int64_t n_particles, n_values_per_frame;
17728 tng_function_status stat;
17730 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17731 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17732 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17733 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17735 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17736 first_frame, last_frame,
17738 (void **)velocities,
17741 &n_values_per_frame,
17747 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17748 (tng_trajectory_t tng_data,
17749 const int64_t first_frame,
17750 const int64_t last_frame,
17752 int64_t *stride_length)
17754 int64_t n_particles, n_values_per_frame;
17756 tng_function_status stat;
17758 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17759 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17760 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17761 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17763 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17764 first_frame, last_frame,
17769 &n_values_per_frame,
17775 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17776 (tng_trajectory_t tng_data,
17777 const int64_t first_frame,
17778 const int64_t last_frame,
17780 int64_t *stride_length)
17782 int64_t n_values_per_frame;
17784 tng_function_status stat;
17786 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17787 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17788 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17789 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17791 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17792 first_frame, last_frame,
17794 (void **)box_shape,
17796 &n_values_per_frame,
17802 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17803 (tng_trajectory_t tng_data,
17805 const int64_t n_values_per_frame,
17806 const int64_t block_id,
17807 const char *block_name,
17808 const char particle_dependency,
17809 const char compression)
17811 tng_trajectory_frame_set_t frame_set;
17812 tng_particle_data_t p_data;
17813 tng_non_particle_data_t np_data;
17814 int64_t n_particles, n_frames;
17815 tng_function_status stat;
17817 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17818 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17822 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17823 i, __FILE__, __LINE__);
17824 return(TNG_FAILURE);
17827 frame_set = &tng_data->current_trajectory_frame_set;
17829 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17831 n_frames = tng_data->frame_set_n_frames;
17833 stat = tng_frame_set_new(tng_data, 0, n_frames);
17834 if(stat != TNG_SUCCESS)
17836 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17843 n_frames = frame_set->n_frames;
17846 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17848 tng_num_particles_get(tng_data, &n_particles);
17849 if(n_particles <= 0)
17851 return(TNG_FAILURE);
17854 if(tng_particle_data_find(tng_data, block_id, &p_data)
17857 stat = tng_particle_data_block_add(tng_data, block_id,
17860 TNG_TRAJECTORY_BLOCK,
17861 n_frames, n_values_per_frame, i,
17864 if(stat != TNG_SUCCESS)
17866 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17867 __FILE__, __LINE__);
17870 p_data = &frame_set->tr_particle_data[frame_set->
17871 n_particle_data_blocks - 1];
17872 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17874 n_values_per_frame);
17875 if(stat != TNG_SUCCESS)
17877 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17878 __FILE__, __LINE__);
17884 if(p_data->stride_length != i)
17886 p_data->stride_length = i;
17887 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17889 n_values_per_frame);
17890 if(stat != TNG_SUCCESS)
17892 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17893 __FILE__, __LINE__);
17901 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17903 stat = tng_data_block_add(tng_data, block_id, block_name,
17904 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17905 n_frames, n_values_per_frame,
17906 i, compression, 0);
17907 if(stat != TNG_SUCCESS)
17909 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17910 __FILE__, __LINE__);
17913 np_data = &frame_set->tr_data[frame_set->
17914 n_data_blocks - 1];
17915 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17916 i, n_values_per_frame);
17917 if(stat != TNG_SUCCESS)
17919 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17920 __FILE__, __LINE__);
17926 if(np_data->stride_length != i)
17928 np_data->stride_length = i;
17929 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17930 i, n_values_per_frame);
17931 if(stat != TNG_SUCCESS)
17933 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17934 __FILE__, __LINE__);
17941 return(TNG_SUCCESS);
17944 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17945 (tng_trajectory_t tng_data,
17947 const int64_t n_values_per_frame,
17948 const int64_t block_id,
17949 const char *block_name,
17950 const char particle_dependency,
17951 const char compression)
17953 tng_trajectory_frame_set_t frame_set;
17954 tng_particle_data_t p_data;
17955 tng_non_particle_data_t np_data;
17956 int64_t n_particles, n_frames;
17957 tng_function_status stat;
17959 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17960 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17964 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17965 i, __FILE__, __LINE__);
17966 return(TNG_FAILURE);
17969 frame_set = &tng_data->current_trajectory_frame_set;
17971 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17973 n_frames = tng_data->frame_set_n_frames;
17975 stat = tng_frame_set_new(tng_data, 0, n_frames);
17976 if(stat != TNG_SUCCESS)
17978 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17985 n_frames = frame_set->n_frames;
17988 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17990 tng_num_particles_get(tng_data, &n_particles);
17992 if(n_particles <= 0)
17994 return(TNG_FAILURE);
17997 if(tng_particle_data_find(tng_data, block_id, &p_data)
18000 stat = tng_particle_data_block_add(tng_data, block_id,
18003 TNG_TRAJECTORY_BLOCK,
18004 n_frames, n_values_per_frame, i,
18007 if(stat != TNG_SUCCESS)
18009 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18010 __FILE__, __LINE__);
18013 p_data = &frame_set->tr_particle_data[frame_set->
18014 n_particle_data_blocks - 1];
18015 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18017 n_values_per_frame);
18018 if(stat != TNG_SUCCESS)
18020 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18021 __FILE__, __LINE__);
18027 p_data->stride_length = i;
18032 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18034 stat = tng_data_block_add(tng_data, block_id, block_name,
18035 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
18036 n_frames, n_values_per_frame,
18037 i, compression, 0);
18038 if(stat != TNG_SUCCESS)
18040 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18041 __FILE__, __LINE__);
18044 np_data = &frame_set->tr_data[frame_set->
18045 n_data_blocks - 1];
18046 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18047 i, n_values_per_frame);
18048 if(stat != TNG_SUCCESS)
18050 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18051 __FILE__, __LINE__);
18057 np_data->stride_length = i;
18061 return(TNG_SUCCESS);
18064 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
18065 (tng_trajectory_t tng_data,
18067 const int64_t n_values_per_frame,
18068 const int64_t block_id,
18069 const char *block_name,
18070 const char particle_dependency,
18071 const char compression)
18073 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
18074 "See documentation. %s: %d", __FILE__, __LINE__);
18075 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
18076 block_id, block_name,
18077 particle_dependency,
18080 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18081 (tng_trajectory_t tng_data,
18084 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18085 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18087 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18088 TNG_TRAJ_POSITIONS,
18090 TNG_PARTICLE_BLOCK_DATA,
18091 TNG_TNG_COMPRESSION));
18094 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18095 (tng_trajectory_t tng_data,
18098 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18099 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18101 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18102 TNG_TRAJ_POSITIONS,
18104 TNG_PARTICLE_BLOCK_DATA,
18105 TNG_TNG_COMPRESSION));
18108 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18109 (tng_trajectory_t tng_data,
18112 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18113 "See documentation. %s: %d", __FILE__, __LINE__);
18114 return(tng_util_pos_write_interval_set(tng_data, i));
18117 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18118 (tng_trajectory_t tng_data,
18121 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18122 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18124 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18125 TNG_TRAJ_VELOCITIES,
18127 TNG_PARTICLE_BLOCK_DATA,
18128 TNG_TNG_COMPRESSION));
18131 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18132 (tng_trajectory_t tng_data,
18135 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18136 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18138 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18139 TNG_TRAJ_VELOCITIES,
18141 TNG_PARTICLE_BLOCK_DATA,
18142 TNG_TNG_COMPRESSION));
18145 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18146 (tng_trajectory_t tng_data,
18149 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18150 "See documentation. %s: %d", __FILE__, __LINE__);
18151 return(tng_util_vel_write_interval_set(tng_data, i));
18154 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18155 (tng_trajectory_t tng_data,
18158 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18159 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18161 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18164 TNG_PARTICLE_BLOCK_DATA,
18165 TNG_GZIP_COMPRESSION));
18168 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18169 (tng_trajectory_t tng_data,
18172 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18173 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18175 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18178 TNG_PARTICLE_BLOCK_DATA,
18179 TNG_GZIP_COMPRESSION));
18182 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18183 (tng_trajectory_t tng_data,
18186 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18187 "See documentation. %s: %d", __FILE__, __LINE__);
18188 return(tng_util_force_write_interval_set(tng_data, i));
18191 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18192 (tng_trajectory_t tng_data,
18195 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18196 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18198 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18199 TNG_TRAJ_BOX_SHAPE,
18201 TNG_NON_PARTICLE_BLOCK_DATA,
18202 TNG_GZIP_COMPRESSION));
18205 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18206 (tng_trajectory_t tng_data,
18209 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18210 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18212 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18213 TNG_TRAJ_BOX_SHAPE,
18215 TNG_NON_PARTICLE_BLOCK_DATA,
18216 TNG_GZIP_COMPRESSION));
18219 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18220 (tng_trajectory_t tng_data,
18223 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18224 "See documentation. %s: %d", __FILE__, __LINE__);
18225 return(tng_util_box_shape_write_interval_set(tng_data, i));
18228 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18229 (tng_trajectory_t tng_data,
18230 const int64_t frame_nr,
18231 const float *values,
18232 const int64_t n_values_per_frame,
18233 const int64_t block_id,
18234 const char *block_name,
18235 const char particle_dependency,
18236 const char compression)
18238 tng_trajectory_frame_set_t frame_set;
18239 tng_particle_data_t p_data;
18240 tng_non_particle_data_t np_data;
18241 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18242 int64_t last_frame;
18243 int is_first_frame_flag = 0;
18244 char block_type_flag;
18245 tng_function_status stat;
18247 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18248 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18249 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18251 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18253 tng_num_particles_get(tng_data, &n_particles);
18254 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18259 return(TNG_FAILURE);
18262 frame_set = &tng_data->current_trajectory_frame_set;
18266 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18267 n_frames = stride_length = 1;
18271 block_type_flag = TNG_TRAJECTORY_BLOCK;
18273 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18275 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18276 if(stat != TNG_SUCCESS)
18278 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18283 last_frame = frame_set->first_frame +
18284 frame_set->n_frames - 1;
18285 if(frame_nr > last_frame)
18287 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18288 if(stat != TNG_SUCCESS)
18290 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18294 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18296 last_frame = frame_nr - 1;
18298 stat = tng_frame_set_new(tng_data, last_frame + 1,
18299 tng_data->frame_set_n_frames);
18300 if(stat != TNG_SUCCESS)
18302 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18307 if(frame_set->n_unwritten_frames == 0)
18309 is_first_frame_flag = 1;
18311 frame_set->n_unwritten_frames = frame_nr -
18312 frame_set->first_frame + 1;
18314 n_frames = frame_set->n_frames;
18317 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18319 if(tng_particle_data_find(tng_data, block_id, &p_data)
18322 stat = tng_particle_data_block_add(tng_data, block_id,
18326 n_frames, n_values_per_frame,
18330 if(stat != TNG_SUCCESS)
18332 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18333 __FILE__, __LINE__);
18336 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18338 p_data = &frame_set->tr_particle_data[frame_set->
18339 n_particle_data_blocks - 1];
18343 p_data = &tng_data->non_tr_particle_data[tng_data->
18344 n_particle_data_blocks - 1];
18346 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18347 stride_length, n_particles,
18348 n_values_per_frame);
18349 if(stat != TNG_SUCCESS)
18351 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18352 __FILE__, __LINE__);
18357 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18359 stride_length = p_data->stride_length;
18361 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18363 p_data->first_frame_with_data = frame_nr;
18368 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18371 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18372 n_values_per_frame, values, sizeof(float) *
18373 n_particles * n_values_per_frame);
18377 memcpy(p_data->values, values, sizeof(float) * n_particles *
18378 n_values_per_frame);
18383 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18385 stat = tng_data_block_add(tng_data, block_id, block_name,
18386 TNG_FLOAT_DATA, block_type_flag,
18387 n_frames, n_values_per_frame,
18388 stride_length, compression, 0);
18389 if(stat != TNG_SUCCESS)
18391 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18392 __FILE__, __LINE__);
18395 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18397 np_data = &frame_set->tr_data[frame_set->
18398 n_data_blocks - 1];
18402 np_data = &tng_data->non_tr_data[tng_data->
18403 n_data_blocks - 1];
18405 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18406 stride_length, n_values_per_frame);
18407 if(stat != TNG_SUCCESS)
18409 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18410 __FILE__, __LINE__);
18415 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18417 stride_length = np_data->stride_length;
18419 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18421 np_data->first_frame_with_data = frame_nr;
18426 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18429 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18430 n_values_per_frame, values, sizeof(float) *
18431 n_values_per_frame);
18435 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18439 return(TNG_SUCCESS);
18442 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18443 (tng_trajectory_t tng_data,
18444 const int64_t frame_nr,
18445 const double *values,
18446 const int64_t n_values_per_frame,
18447 const int64_t block_id,
18448 const char *block_name,
18449 const char particle_dependency,
18450 const char compression)
18452 tng_trajectory_frame_set_t frame_set;
18453 tng_particle_data_t p_data;
18454 tng_non_particle_data_t np_data;
18455 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18456 int64_t last_frame;
18457 int is_first_frame_flag = 0;
18458 char block_type_flag;
18459 tng_function_status stat;
18461 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18462 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18463 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18465 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18467 tng_num_particles_get(tng_data, &n_particles);
18468 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18473 return(TNG_FAILURE);
18476 frame_set = &tng_data->current_trajectory_frame_set;
18480 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18481 n_frames = stride_length = 1;
18485 block_type_flag = TNG_TRAJECTORY_BLOCK;
18487 n_frames = tng_data->frame_set_n_frames;
18489 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18491 stat = tng_frame_set_new(tng_data, 0, n_frames);
18492 if(stat != TNG_SUCCESS)
18494 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18501 n_frames = frame_set->n_frames;
18503 last_frame = frame_set->first_frame +
18504 frame_set->n_frames - 1;
18505 if(frame_nr > last_frame)
18507 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18508 if(stat != TNG_SUCCESS)
18510 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18514 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18516 last_frame = frame_nr - 1;
18518 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18519 if(stat != TNG_SUCCESS)
18521 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18526 if(frame_set->n_unwritten_frames == 0)
18528 is_first_frame_flag = 1;
18530 frame_set->n_unwritten_frames = frame_nr -
18531 frame_set->first_frame + 1;
18534 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18536 if(tng_particle_data_find(tng_data, block_id, &p_data)
18539 stat = tng_particle_data_block_add(tng_data, block_id,
18543 n_frames, n_values_per_frame,
18547 if(stat != TNG_SUCCESS)
18549 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18550 __FILE__, __LINE__);
18553 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18555 p_data = &frame_set->tr_particle_data[frame_set->
18556 n_particle_data_blocks - 1];
18560 p_data = &tng_data->non_tr_particle_data[tng_data->
18561 n_particle_data_blocks - 1];
18563 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18564 stride_length, n_particles,
18565 n_values_per_frame);
18566 if(stat != TNG_SUCCESS)
18568 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18569 __FILE__, __LINE__);
18574 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18576 stride_length = p_data->stride_length;
18578 if(is_first_frame_flag)
18580 p_data->first_frame_with_data = frame_nr;
18585 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18588 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18589 n_values_per_frame, values, sizeof(double) *
18590 n_particles * n_values_per_frame);
18594 memcpy(p_data->values, values, sizeof(double) * n_particles *
18595 n_values_per_frame);
18600 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18602 stat = tng_data_block_add(tng_data, block_id, block_name,
18603 TNG_DOUBLE_DATA, block_type_flag,
18604 n_frames, n_values_per_frame,
18605 stride_length, compression, 0);
18606 if(stat != TNG_SUCCESS)
18608 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18609 __FILE__, __LINE__);
18612 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18614 np_data = &frame_set->tr_data[frame_set->
18615 n_data_blocks - 1];
18619 np_data = &tng_data->non_tr_data[tng_data->
18620 n_data_blocks - 1];
18622 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18623 stride_length, n_values_per_frame);
18624 if(stat != TNG_SUCCESS)
18626 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18627 __FILE__, __LINE__);
18632 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18634 stride_length = np_data->stride_length;
18636 if(is_first_frame_flag)
18638 np_data->first_frame_with_data = frame_nr;
18643 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18646 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18647 n_values_per_frame, values, sizeof(double) *
18648 n_values_per_frame);
18652 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18656 return(TNG_SUCCESS);
18659 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18660 (tng_trajectory_t tng_data,
18661 const int64_t frame_nr,
18662 const float *positions)
18664 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18665 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18666 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18668 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18669 TNG_TRAJ_POSITIONS, "POSITIONS",
18670 TNG_PARTICLE_BLOCK_DATA,
18671 TNG_TNG_COMPRESSION));
18674 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18675 (tng_trajectory_t tng_data,
18676 const int64_t frame_nr,
18677 const double *positions)
18679 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18680 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18681 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18683 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18684 TNG_TRAJ_POSITIONS, "POSITIONS",
18685 TNG_PARTICLE_BLOCK_DATA,
18686 TNG_TNG_COMPRESSION));
18689 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18690 (tng_trajectory_t tng_data,
18691 const int64_t frame_nr,
18692 const float *velocities)
18694 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18695 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18696 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18698 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18699 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18700 TNG_PARTICLE_BLOCK_DATA,
18701 TNG_TNG_COMPRESSION));
18704 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18705 (tng_trajectory_t tng_data,
18706 const int64_t frame_nr,
18707 const double *velocities)
18709 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18710 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18711 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18713 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18714 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18715 TNG_PARTICLE_BLOCK_DATA,
18716 TNG_TNG_COMPRESSION));
18719 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18720 (tng_trajectory_t tng_data,
18721 const int64_t frame_nr,
18722 const float *forces)
18724 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18725 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18726 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18728 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18729 TNG_TRAJ_FORCES, "FORCES",
18730 TNG_PARTICLE_BLOCK_DATA,
18731 TNG_GZIP_COMPRESSION));
18734 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18735 (tng_trajectory_t tng_data,
18736 const int64_t frame_nr,
18737 const double *forces)
18739 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18740 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18741 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18743 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18744 TNG_TRAJ_FORCES, "FORCES",
18745 TNG_PARTICLE_BLOCK_DATA,
18746 TNG_GZIP_COMPRESSION));
18749 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18750 (tng_trajectory_t tng_data,
18751 const int64_t frame_nr,
18752 const float *box_shape)
18754 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18755 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18756 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18758 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18759 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18760 TNG_NON_PARTICLE_BLOCK_DATA,
18761 TNG_GZIP_COMPRESSION));
18764 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18765 (tng_trajectory_t tng_data,
18766 const int64_t frame_nr,
18767 const double *box_shape)
18769 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18770 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18771 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18773 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18774 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18775 TNG_NON_PARTICLE_BLOCK_DATA,
18776 TNG_GZIP_COMPRESSION));
18779 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18780 (tng_trajectory_t tng_data,
18781 const int64_t frame_nr,
18783 const float *values,
18784 const int64_t n_values_per_frame,
18785 const int64_t block_id,
18786 const char *block_name,
18787 const char particle_dependency,
18788 const char compression)
18790 tng_trajectory_frame_set_t frame_set;
18791 tng_function_status stat;
18793 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18794 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18795 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18796 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18798 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18799 block_id, block_name,
18800 particle_dependency,
18803 if(stat != TNG_SUCCESS)
18808 frame_set = &tng_data->current_trajectory_frame_set;
18810 /* first_frame_time is -1 when it is not yet set. */
18811 if(frame_set->first_frame_time < -0.1)
18813 if(frame_nr > frame_set->first_frame)
18815 stat = tng_frame_set_first_frame_time_set(tng_data,
18818 frame_set->first_frame) *
18819 tng_data->time_per_frame);
18823 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18829 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18830 (tng_trajectory_t tng_data,
18831 const int64_t frame_nr,
18833 const double *values,
18834 const int64_t n_values_per_frame,
18835 const int64_t block_id,
18836 const char *block_name,
18837 const char particle_dependency,
18838 const char compression)
18840 tng_trajectory_frame_set_t frame_set;
18841 tng_function_status stat;
18843 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18844 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18845 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18846 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18848 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18849 block_id, block_name,
18850 particle_dependency,
18853 if(stat != TNG_SUCCESS)
18858 frame_set = &tng_data->current_trajectory_frame_set;
18860 /* first_frame_time is -1 when it is not yet set. */
18861 if(frame_set->first_frame_time < -0.1)
18863 if(frame_nr > frame_set->first_frame)
18865 stat = tng_frame_set_first_frame_time_set(tng_data,
18868 frame_set->first_frame) *
18869 tng_data->time_per_frame);
18873 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18879 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18880 (tng_trajectory_t tng_data,
18881 const int64_t frame_nr,
18883 const float *positions)
18885 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18886 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18887 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18888 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18890 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18891 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18892 TNG_PARTICLE_BLOCK_DATA,
18893 TNG_TNG_COMPRESSION));
18896 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18897 (tng_trajectory_t tng_data,
18898 const int64_t frame_nr,
18900 const double *positions)
18902 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18903 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18904 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18905 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18907 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18909 TNG_TRAJ_POSITIONS,
18911 TNG_PARTICLE_BLOCK_DATA,
18912 TNG_TNG_COMPRESSION));
18915 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18916 (tng_trajectory_t tng_data,
18917 const int64_t frame_nr,
18919 const float *velocities)
18921 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18922 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18923 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18924 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18926 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18928 TNG_TRAJ_VELOCITIES,
18930 TNG_PARTICLE_BLOCK_DATA,
18931 TNG_TNG_COMPRESSION));
18934 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18935 (tng_trajectory_t tng_data,
18936 const int64_t frame_nr,
18938 const double *velocities)
18940 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18941 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18942 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18943 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18945 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18947 TNG_TRAJ_VELOCITIES,
18949 TNG_PARTICLE_BLOCK_DATA,
18950 TNG_TNG_COMPRESSION));
18953 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18954 (tng_trajectory_t tng_data,
18955 const int64_t frame_nr,
18957 const float *forces)
18959 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18960 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18961 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18962 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18964 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18965 3, TNG_TRAJ_FORCES, "FORCES",
18966 TNG_PARTICLE_BLOCK_DATA,
18967 TNG_GZIP_COMPRESSION));
18970 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18971 (tng_trajectory_t tng_data,
18972 const int64_t frame_nr,
18974 const double *forces)
18976 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18977 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18978 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18979 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18981 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18983 TNG_TRAJ_FORCES, "FORCES",
18984 TNG_PARTICLE_BLOCK_DATA,
18985 TNG_GZIP_COMPRESSION));
18988 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18989 (tng_trajectory_t tng_data,
18990 const int64_t frame_nr,
18992 const float *box_shape)
18994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18995 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18996 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18997 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18999 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
19000 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
19001 TNG_NON_PARTICLE_BLOCK_DATA,
19002 TNG_GZIP_COMPRESSION));
19005 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
19006 (tng_trajectory_t tng_data,
19007 const int64_t frame_nr,
19009 const double *box_shape)
19011 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19012 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
19013 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
19014 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
19016 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
19017 time, box_shape, 9,
19018 TNG_TRAJ_BOX_SHAPE,
19020 TNG_NON_PARTICLE_BLOCK_DATA,
19021 TNG_GZIP_COMPRESSION));
19024 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
19025 (tng_trajectory_t tng_data,
19026 const int64_t block_id,
19030 tng_trajectory_frame_set_t frame_set;
19031 tng_particle_data_t p_data = 0;
19032 tng_non_particle_data_t np_data = 0;
19033 tng_function_status stat;
19035 int block_type = -1;
19037 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19038 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
19039 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
19041 frame_set = &tng_data->current_trajectory_frame_set;
19043 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19044 if(stat == TNG_SUCCESS)
19046 block_type = TNG_PARTICLE_BLOCK_DATA;
19050 stat = tng_data_find(tng_data, block_id, &np_data);
19051 if(stat == TNG_SUCCESS)
19053 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19057 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19058 if(stat != TNG_SUCCESS)
19062 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19063 if(stat == TNG_SUCCESS)
19065 block_type = TNG_PARTICLE_BLOCK_DATA;
19069 stat = tng_data_find(tng_data, block_id, &np_data);
19070 if(stat == TNG_SUCCESS)
19072 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19081 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19083 if(p_data->last_retrieved_frame < 0)
19085 i = p_data->first_frame_with_data;
19089 i = p_data->last_retrieved_frame;
19092 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19094 if(np_data->last_retrieved_frame < 0)
19096 i = np_data->first_frame_with_data;
19100 i = np_data->last_retrieved_frame;
19105 return(TNG_FAILURE);
19107 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
19109 stat = tng_frame_set_of_frame_find(tng_data, i);
19110 if(stat != TNG_SUCCESS)
19114 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19115 if(stat != TNG_SUCCESS)
19117 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19118 __FILE__, __LINE__);
19122 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19124 *codec_id = p_data->codec_id;
19125 *factor = p_data->compression_multiplier;
19127 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19129 *codec_id = np_data->codec_id;
19130 *factor = np_data->compression_multiplier;
19132 return(TNG_SUCCESS);
19135 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19136 (tng_trajectory_t tng_data,
19137 int64_t current_frame,
19138 const int64_t n_requested_data_block_ids,
19139 const int64_t *requested_data_block_ids,
19140 int64_t *next_frame,
19141 int64_t *n_data_blocks_in_next_frame,
19142 int64_t **data_block_ids_in_next_frame)
19144 tng_trajectory_frame_set_t frame_set;
19145 tng_function_status stat;
19146 tng_particle_data_t p_data;
19147 tng_non_particle_data_t np_data;
19148 tng_gen_block_t block;
19149 int64_t i, j, block_id, *temp;
19150 int64_t data_frame, frame_diff, min_diff;
19151 int64_t size, frame_set_file_pos, file_pos;
19152 int found, read_all = 0;
19154 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19155 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19156 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19157 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19159 if(n_requested_data_block_ids)
19161 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.");
19162 size = sizeof(int64_t) * n_requested_data_block_ids;
19163 temp = realloc(*data_block_ids_in_next_frame, size);
19166 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
19167 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19168 __FILE__, __LINE__);
19169 free(*data_block_ids_in_next_frame);
19170 *data_block_ids_in_next_frame = 0;
19171 return(TNG_CRITICAL);
19173 *data_block_ids_in_next_frame = temp;
19176 frame_set = &tng_data->current_trajectory_frame_set;
19178 current_frame += 1;
19180 if(current_frame < frame_set->first_frame ||
19181 current_frame >= frame_set->first_frame + frame_set->n_frames)
19183 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19184 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19185 if(stat != TNG_SUCCESS)
19187 /* If the frame set search found the frame set after the starting
19188 * frame set there is a gap in the frame sets. So, even if the frame
19189 * was not found the next frame with data is still in the found
19191 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19192 frame_set_file_pos)
19196 current_frame = frame_set->first_frame;
19200 /* Check for data blocks only if they have not already been found. */
19201 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19203 file_pos = ftello(tng_data->input_file);
19204 if(file_pos < tng_data->input_file_len)
19206 tng_block_init(&block);
19207 stat = tng_block_header_read(tng_data, block);
19208 while(file_pos < tng_data->input_file_len &&
19209 stat != TNG_CRITICAL &&
19210 block->id != TNG_TRAJECTORY_FRAME_SET &&
19213 stat = tng_block_read_next(tng_data, block,
19215 if(stat != TNG_CRITICAL)
19217 file_pos = ftello(tng_data->input_file);
19218 if(file_pos < tng_data->input_file_len)
19220 stat = tng_block_header_read(tng_data, block);
19224 tng_block_destroy(&block);
19225 if(stat == TNG_CRITICAL)
19227 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
19228 file_pos, __FILE__, __LINE__);
19237 *n_data_blocks_in_next_frame = 0;
19239 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19241 p_data = &frame_set->tr_particle_data[i];
19242 block_id = p_data->block_id;
19244 if(n_requested_data_block_ids > 0)
19247 for(j = 0; j < n_requested_data_block_ids; j++)
19249 if(block_id == requested_data_block_ids[j])
19261 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19262 p_data->last_retrieved_frame >=
19263 frame_set->first_frame + frame_set->n_frames))
19265 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19266 TNG_USE_HASH, block_id);
19267 if(stat == TNG_CRITICAL)
19269 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19270 __FILE__, __LINE__);
19273 if(stat == TNG_FAILURE)
19278 if(frame_set->first_frame != current_frame &&
19279 p_data->last_retrieved_frame >= 0)
19281 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19285 data_frame = p_data->first_frame_with_data;
19287 frame_diff = data_frame - current_frame;
19292 if(min_diff == -1 || frame_diff <= min_diff)
19294 if(frame_diff < min_diff)
19296 *n_data_blocks_in_next_frame = 1;
19300 *n_data_blocks_in_next_frame += 1;
19302 if(n_requested_data_block_ids <= 0)
19304 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19305 temp = realloc(*data_block_ids_in_next_frame, size);
19308 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
19309 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19310 __FILE__, __LINE__);
19311 free(*data_block_ids_in_next_frame);
19312 *data_block_ids_in_next_frame = 0;
19313 return(TNG_CRITICAL);
19315 *data_block_ids_in_next_frame = temp;
19319 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19321 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19323 min_diff = frame_diff;
19326 for(i = 0; i < frame_set->n_data_blocks; i++)
19328 np_data = &frame_set->tr_data[i];
19329 block_id = np_data->block_id;
19331 if(n_requested_data_block_ids > 0)
19334 for(j = 0; j < n_requested_data_block_ids; j++)
19336 if(block_id == requested_data_block_ids[j])
19348 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19349 np_data->last_retrieved_frame >=
19350 frame_set->first_frame + frame_set->n_frames))
19352 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19353 TNG_USE_HASH, block_id);
19354 if(stat == TNG_CRITICAL)
19356 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19357 __FILE__, __LINE__);
19360 if(stat == TNG_FAILURE)
19365 if(frame_set->first_frame != current_frame &&
19366 np_data->last_retrieved_frame >= 0)
19368 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19372 data_frame = np_data->first_frame_with_data;
19374 frame_diff = data_frame - current_frame;
19379 if(min_diff == -1 || frame_diff <= min_diff)
19381 if(frame_diff < min_diff)
19383 *n_data_blocks_in_next_frame = 1;
19387 *n_data_blocks_in_next_frame += 1;
19389 if(n_requested_data_block_ids <= 0)
19391 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19392 temp = realloc(*data_block_ids_in_next_frame, size);
19395 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
19396 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19397 __FILE__, __LINE__);
19398 free(*data_block_ids_in_next_frame);
19399 *data_block_ids_in_next_frame = 0;
19400 return(TNG_CRITICAL);
19402 *data_block_ids_in_next_frame = temp;
19406 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19408 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19410 min_diff = frame_diff;
19415 return(TNG_FAILURE);
19417 *next_frame = current_frame + min_diff;
19419 return(TNG_SUCCESS);
19423 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19424 (tng_trajectory_t tng_data,
19425 int64_t *n_data_blocks,
19426 int64_t **data_block_ids,
19427 char ***data_block_names,
19428 int64_t **stride_lengths,
19429 int64_t **n_values_per_frame,
19430 char **block_types,
19431 char **dependencies,
19432 char **compressions)
19434 tng_gen_block_t block;
19435 int64_t orig_file_pos, file_pos;
19437 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19438 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19439 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19440 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19441 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19443 orig_file_pos = ftello(tng_data->input_file);
19445 if(!tng_data->input_file_len)
19447 fseeko(tng_data->input_file, 0, SEEK_END);
19448 tng_data->input_file_len = ftello(tng_data->input_file);
19451 fseeko(tng_data->input_file, 0, SEEK_SET);
19454 *n_data_blocks = 0;
19456 tng_block_init(&block);
19458 while(file_pos < tng_data->input_file_len &&
19459 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19461 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19465 file_pos += (block->block_contents_size + block->header_contents_size);
19466 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
19469 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
19471 return(TNG_SUCCESS);
19474 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19475 (tng_trajectory_t tng_data,
19476 const int64_t prev_frame)
19478 tng_function_status stat;
19479 FILE *temp = tng_data->input_file;
19481 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19482 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19484 tng_data->input_file = tng_data->output_file;
19486 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19487 if(stat != TNG_SUCCESS)
19492 tng_data->current_trajectory_frame_set_output_file_pos =
19493 tng_data->current_trajectory_frame_set_input_file_pos;
19495 tng_data->input_file = temp;
19497 return(TNG_SUCCESS);