1 /* This code is part of the tng binary trajectory format.
5 * Written by Magnus Lundborg
6 * Copyright (c) 2012-2013, The GROMACS development team.
7 * Check out http://www.gromacs.org for more information.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the Revised BSD License.
14 #ifdef USE_STD_INTTYPES_H
27 #include "../../include/tng_io.h"
28 #include "../../include/md5.h"
29 #include "../../include/compression/tng_compress.h"
33 /** One of the atoms of the bond */
35 /** The other atom of the bond */
40 /** The residue containing this atom */
41 tng_residue_t residue;
42 /** A unique (per molecule) ID number of the atom */
44 /** The atom_type (depending on the forcefield) */
46 /** The name of the atom */
51 /** The chain containing this residue */
53 /** A unique (per chain) ID number of the residue */
55 /** The name of the residue */
57 /** The number of atoms in the residue */
59 /** A list of atoms in the residue */
64 /** The molecule containing this chain */
65 tng_molecule_t molecule;
66 /** A unique (per molecule) ID number of the chain */
68 /** The name of the chain */
70 /** The number of residues in the chain */
72 /** A list of residues in the chain */
73 tng_residue_t residues;
77 /** A unique ID number of the molecule */
79 /** Quaternary structure of the molecule.
84 int64_t quaternary_str;
85 /** The number of chains in the molecule */
87 /** The number of residues in the molecule */
89 /** The number of atoms in the molecule */
91 /** The number of bonds in the molecule. If the bonds are not specified this
94 /** The name of the molecule */
96 /** A list of chains in the molecule */
98 /** A list of residues in the molecule */
99 tng_residue_t residues;
100 /** A list of the atoms in the molecule */
102 /** A list of the bonds in the molecule */
106 struct tng_gen_block {
107 /** The size of the block header in bytes */
108 int64_t header_contents_size;
109 /** The size of the block contents in bytes */
110 int64_t block_contents_size;
111 /** The ID of the block to determine its type */
113 /** The MD5 hash of the block to verify integrity */
114 char md5_hash[TNG_MD5_HASH_LEN];
115 /** The name of the block */
117 /** The library version used to write the block */
118 int64_t block_version;
119 int64_t alt_hash_type;
120 int64_t alt_hash_len;
122 int64_t signature_type;
123 int64_t signature_len;
125 /** The full block header contents */
126 char *header_contents;
127 /** The full block contents */
128 char *block_contents;
131 struct tng_particle_mapping {
132 /** The index number of the first particle in this mapping block */
133 int64_t num_first_particle;
134 /** The number of particles list in this mapping block */
136 /** the mapping of index numbers to the real particle numbers in the
137 * trajectory. real_particle_numbers[0] is the real particle number
138 * (as it is numbered in the molecular system) of the first particle
139 * in the data blocks covered by this particle mapping block */
140 int64_t *real_particle_numbers;
143 struct tng_trajectory_frame_set {
144 /** The number of different particle mapping blocks present. */
145 int64_t n_mapping_blocks;
146 /** The atom mappings of this frame set */
147 struct tng_particle_mapping *mappings;
148 /** The first frame of this frame set */
150 /** The number of frames in this frame set */
152 /** The number of written frames in this frame set (used when writing one
153 * frame at a time). */
154 int64_t n_written_frames;
155 /** The number of frames not yet written to file in this frame set
156 * (used from the utility functions to finish the writing properly. */
157 int64_t n_unwritten_frames;
160 /** A list of the number of each molecule type - only used when using
161 * variable number of atoms */
162 int64_t *molecule_cnt_list;
163 /** The number of particles/atoms - only used when using variable number
166 /** The file position of the next frame set */
167 int64_t next_frame_set_file_pos;
168 /** The file position of the previous frame set */
169 int64_t prev_frame_set_file_pos;
170 /** The file position of the frame set one long stride step ahead */
171 int64_t medium_stride_next_frame_set_file_pos;
172 /** The file position of the frame set one long stride step behind */
173 int64_t medium_stride_prev_frame_set_file_pos;
174 /** The file position of the frame set one long stride step ahead */
175 int64_t long_stride_next_frame_set_file_pos;
176 /** The file position of the frame set one long stride step behind */
177 int64_t long_stride_prev_frame_set_file_pos;
178 /** Time stamp (in seconds) of first frame in frame set */
179 double first_frame_time;
181 /* The data blocks in a frame set are trajectory data blocks */
182 /** The number of trajectory data blocks of particle dependent data */
183 int n_particle_data_blocks;
184 /** A list of data blocks containing particle dependent data */
185 struct tng_particle_data *tr_particle_data;
186 /** The number of trajectory data blocks independent of particles */
188 /** A list of data blocks containing particle indepdendent data */
189 struct tng_non_particle_data *tr_data;
192 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
193 struct tng_particle_data {
194 /** The block ID of the data block containing this particle data.
195 * This is used to determine the kind of data that is stored */
197 /** The name of the data block. This is used to determine the kind of
198 * data that is stored */
200 /** The type of data stored. */
202 /** The frame number of the first data value */
203 int64_t first_frame_with_data;
204 /** The number of frames in this frame set */
206 /** The number of values stored per frame */
207 int64_t n_values_per_frame;
208 /** The number of frames between each data point - e.g. when
209 * storing sparse data. */
210 int64_t stride_length;
211 /** ID of the CODEC used for compression 0 == no compression. */
213 /** If reading one frame at a time this is the last read frame */
214 int64_t last_retrieved_frame;
215 /** The multiplier used for getting integer values for compression */
216 double compression_multiplier;
217 /** A 1-dimensional array of values of length
218 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
220 /** If storing character data store it in a 3-dimensional array */
224 struct tng_non_particle_data {
225 /** The ID of the data block */
227 /** The name of the data block. This is used to determine the kind of
228 * data that is stored */
230 /** The type of data stored. */
232 /** The first frame number of the first data value */
233 int64_t first_frame_with_data;
234 /** The number of frames in this data block */
236 /** The number of values stored per frame */
237 int64_t n_values_per_frame;
238 /** The number of frames between each data value, e.g. if storing data
239 * that is not saved every frame. */
240 int64_t stride_length;
241 /** ID of the CODEC used for compression. 0 == no compression. */
243 /** If reading one frame at a time this is the last read frame */
244 int64_t last_retrieved_frame;
245 /** Compressed data is stored as integers. This compression multiplier is
246 * the multiplication factor to convert from integer to float/double */
247 double compression_multiplier;
248 /** A 1-dimensional array of values of length
249 * [sizeof (datatype)] * n_frames * n_values_per_frame */
251 /** If storing character data store it in a 3-dimensional array */
257 struct tng_trajectory {
258 /** The path of the input trajectory file */
259 char *input_file_path;
260 /** A handle to the input file */
262 /** The length of the input file */
264 /** The path of the output trajectory file */
265 char *output_file_path;
266 /** A handle to the output file */
268 /** Function to swap 32 bit values to and from the endianness of the
270 tng_function_status (*input_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
271 /** Function to swap 64 bit values to and from the endianness of the
273 tng_function_status (*input_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
274 /** Function to swap 32 bit values to and from the endianness of the
276 tng_function_status (*output_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
277 /** Function to swap 64 bit values to and from the endianness of the
279 tng_function_status (*output_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
280 /** The endianness of 32 bit values of the current computer */
282 /** The endianness of 64 bit values of the current computer */
285 /** The name of the program producing this trajectory */
286 char *first_program_name;
287 /** The forcefield used in the simulations */
288 char *forcefield_name;
289 /** The name of the user running the simulations */
290 char *first_user_name;
291 /** The name of the computer on which the simulations were performed */
292 char *first_computer_name;
293 /** The PGP signature of the user creating the file. */
294 char *first_pgp_signature;
295 /** The name of the program used when making last modifications to the
297 char *last_program_name;
298 /** The name of the user making the last modifications to the file */
299 char *last_user_name;
300 /** The name of the computer on which the last modifications were made */
301 char *last_computer_name;
302 /** The PGP signature of the user making the last modifications to the
304 char *last_pgp_signature;
305 /** The time (n seconds since 1970) when the file was created */
307 /** The exponential of the value of the distance unit used. The default
308 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
309 * the measurements are in Ã… the distance_unit_exponential = -10. */
310 int64_t distance_unit_exponential;
312 /** A flag indicating if the number of atoms can vary throughout the
313 * simulation, e.g. using a grand canonical ensemble */
314 char var_num_atoms_flag;
315 /** The number of frames in a frame set. It is allowed to have frame sets
316 * with fewer frames, but this will help searching for specific frames */
317 int64_t frame_set_n_frames;
318 /** The number of frame sets in a medium stride step */
319 int64_t medium_stride_length;
320 /** The number of frame sets in a long stride step */
321 int64_t long_stride_length;
322 /** The current (can change from one frame set to another) time length
323 * (in seconds) of one frame */
324 double time_per_frame;
326 /** The number of different kinds of molecules in the trajectory */
328 /** A list of molecules in the trajectory */
329 tng_molecule_t molecules;
330 /** A list of the count of each molecule - if using variable number of
331 * particles this will be specified in each frame set */
332 int64_t *molecule_cnt_list;
333 /** The total number of particles/atoms. If using variable number of
334 * particles this will be specified in each frame set */
337 /** The pos in the src file of the first frame set */
338 int64_t first_trajectory_frame_set_input_file_pos;
339 /** The pos in the dest file of the first frame set */
340 int64_t first_trajectory_frame_set_output_file_pos;
341 /** The pos in the src file of the last frame set */
342 int64_t last_trajectory_frame_set_input_file_pos;
343 /** The pos in the dest file of the last frame set */
344 int64_t last_trajectory_frame_set_output_file_pos;
345 /** The currently active frame set */
346 struct tng_trajectory_frame_set current_trajectory_frame_set;
347 /** The pos in the src file of the current frame set */
348 long current_trajectory_frame_set_input_file_pos;
349 /** The pos in the dest file of the current frame set */
350 long current_trajectory_frame_set_output_file_pos;
351 /** The number of frame sets in the trajectory N.B. Not saved in file and
352 * cannot be trusted to be up-to-date */
353 int64_t n_trajectory_frame_sets;
355 /** The number of trajectory blocks in the file */
356 int64_t n_trajectory_blocks;
358 /* These data blocks are non-trajectory data blocks */
359 /** The number of non-frame dependent particle dependent data blocks */
360 int n_particle_data_blocks;
361 /** A list of data blocks containing particle dependent data */
362 struct tng_particle_data *non_tr_particle_data;
364 /** The number of frame and particle independent data blocks */
366 /** A list of frame and particle indepdendent data blocks */
367 struct tng_non_particle_data *non_tr_data;
369 /** TNG compression algorithm for compressing positions */
370 int *compress_algo_pos;
371 /** TNG compression algorithm for compressing velocities */
372 int *compress_algo_vel;
373 /** The precision used for lossy compression */
374 double compression_precision;
378 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
380 #endif /* win32... */
381 #endif /* not defined USE_WINDOWS */
384 #define TNG_INLINE __inline
385 #define TNG_SNPRINTF _snprintf
387 #define TNG_INLINE inline
388 #define TNG_SNPRINTF snprintf
391 static TNG_INLINE int tng_min_i(int a, int b)
393 return (a < b ? a : b);
397 static TNG_INLINE int tng_max_i(int a, int b)
399 return (a > b ? a : b);
402 static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
404 return (a < b ? a : b);
407 static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
409 return (a > b ? a : b);
413 static TNG_INLINE float tng_min_f(float a, float b)
415 return (a < b ? a : b);
418 static TNG_INLINE float tng_max_f(float a, float b)
420 return (a > b ? a : b);
423 static TNG_INLINE double tng_min_d(double a, double b)
425 return (a < b ? a : b);
428 static TNG_INLINE double tng_max_d(double a, double b)
430 return (a > b ? a : b);
434 /** This function swaps the byte order of a 32 bit numerical variable
436 * It does not only work with integer, but e.g. floats need casting.
437 * If the byte order is already big endian no change is needed.
438 * @param tng_data is a trajectory data container.
439 * @param v is a pointer to a 32 bit numerical value (float or integer).
440 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
441 * byte order is not recognised.
443 static tng_function_status tng_swap_byte_order_big_endian_32
444 (const tng_trajectory_t tng_data, int32_t *v)
446 switch(tng_data->endianness_32)
448 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
449 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
450 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
451 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
452 ((*v & 0x000000FF) << 24); /* Move last byte to first */
456 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
457 *v = ((*v & 0xFFFF0000) >> 16) |
458 ((*v & 0x0000FFFF) << 16);
462 case TNG_BIG_ENDIAN_32: /* Already correct */
470 /** This function swaps the byte order of a 64 bit numerical variable
472 * It does not only work with integer, but e.g. floats need casting.
473 * The byte order swapping routine can convert four different byte
474 * orders to big endian.
475 * If the byte order is already big endian no change is needed.
476 * @param tng_data is a trajectory data container.
477 * @param v is a pointer to a 64 bit numerical value (double or integer).
478 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
479 * byte order is not recognised.
481 static tng_function_status tng_swap_byte_order_big_endian_64
482 (const tng_trajectory_t tng_data, int64_t *v)
484 switch(tng_data->endianness_64)
486 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
487 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
488 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
489 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
490 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
491 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
492 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
493 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
494 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
498 case TNG_QUAD_SWAP_64: /* Byte quad swap */
499 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
500 ((*v & 0x00000000FFFFFFFFLL) << 32);
504 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
505 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
506 ((*v & 0x0000FFFF0000FFFFLL) << 16);
510 case TNG_BYTE_SWAP_64: /* Byte swap */
511 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
512 ((*v & 0x00FF00FF00FF00FFLL) << 8);
516 case TNG_BIG_ENDIAN_64: /* Already correct */
524 /** This function swaps the byte order of a 32 bit numerical variable
526 * It does not only work with integer, but e.g. floats need casting.
527 * If the byte order is already little endian no change is needed.
528 * @param tng_data is a trajectory data container.
529 * @param v is a pointer to a 32 bit numerical value (float or integer).
530 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
531 * byte order is not recognised.
533 static tng_function_status tng_swap_byte_order_little_endian_32
534 (const tng_trajectory_t tng_data, int32_t *v)
536 switch(tng_data->endianness_32)
538 case TNG_LITTLE_ENDIAN_32: /* Already correct */
541 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
542 *v = ((*v & 0xFF00FF00) >> 8) |
543 ((*v & 0x00FF00FF) << 8);
547 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
548 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
549 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
550 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
551 ((*v & 0x000000FF) << 24); /* Move last byte to first */
560 /** This function swaps the byte order of a 64 bit numerical variable
562 * It does not only work with integer, but e.g. floats need casting.
563 * The byte order swapping routine can convert four different byte
564 * orders to little endian.
565 * If the byte order is already little endian no change is needed.
566 * @param tng_data is a trajectory data container.
567 * @param v is a pointer to a 64 bit numerical value (double or integer).
568 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
569 * byte order is not recognised.
571 static tng_function_status tng_swap_byte_order_little_endian_64
572 (const tng_trajectory_t tng_data, int64_t *v)
574 switch(tng_data->endianness_64)
576 case TNG_LITTLE_ENDIAN_64: /* Already correct */
579 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
580 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
581 ((*v & 0x00FF000000FF0000LL) >> 8) |
582 ((*v & 0x0000FF000000FF00LL) << 8) |
583 ((*v & 0x000000FF000000FFLL) << 24);
587 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
588 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
589 ((*v & 0x00FF00FF00000000LL) >> 24) |
590 ((*v & 0x00000000FF00FF00LL) << 24) |
591 ((*v & 0x0000000000FF00FFLL) << 40);
595 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
596 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
597 ((*v & 0x0000FFFF00000000LL) >> 16) |
598 ((*v & 0x00000000FFFF0000LL) << 16) |
599 ((*v & 0x000000000000FFFFLL) << 48);
603 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
604 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
605 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
606 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
607 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
608 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
609 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
610 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
611 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
619 /** Generate the md5 hash of a block.
620 * The hash is created based on the actual block contents.
621 * @param block is a general block container.
622 * @return TNG_SUCCESS (0) if successful.
624 static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
626 md5_state_t md5_state;
628 md5_init(&md5_state);
629 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
630 (int)block->block_contents_size);
631 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
636 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
637 * calculated from the current contents.
638 * If the current md5 hash is not set skip the comparison.
639 * @param block is a general block container.
640 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
641 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
642 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
645 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
648 md5_state_t md5_state;
649 char hash[TNG_MD5_HASH_LEN];
651 TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
654 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
658 md5_init(&md5_state);
659 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
660 (int)block->block_contents_size);
661 md5_finish(&md5_state, (md5_byte_t *)hash);
663 if(strncmp(block->md5_hash, hash, 16) != 0)
665 *results = TNG_FALSE;
671 /** Open the input file if it is not already opened.
672 * @param tng_data is a trajectory data container.
673 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
676 static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
678 if(!tng_data->input_file)
680 if(!tng_data->input_file_path)
682 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
684 return(TNG_CRITICAL);
686 tng_data->input_file = fopen(tng_data->input_file_path, "r");
687 if(!tng_data->input_file)
689 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
690 tng_data->input_file_path, __FILE__, __LINE__);
691 return(TNG_CRITICAL);
697 /** Open the output file if it is not already opened
698 * @param tng_data is a trajectory data container.
699 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
702 static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
704 if(!tng_data->output_file)
706 if(!tng_data->output_file_path)
708 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
710 return(TNG_CRITICAL);
713 tng_data->output_file = fopen(tng_data->output_file_path, "w+");
715 if(!tng_data->output_file)
717 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
718 tng_data->output_file_path, __FILE__, __LINE__);
719 return(TNG_CRITICAL);
725 /** Setup a file block container.
726 * @param block_p a pointer to memory to initialise as a file block container.
727 * @details Memory is allocated during initialisation.
728 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
731 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
733 tng_gen_block_t block;
735 *block_p = malloc(sizeof(struct tng_gen_block));
739 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
740 sizeof(struct tng_gen_block), __FILE__, __LINE__);
741 return(TNG_CRITICAL);
747 /* Reset the md5_hash */
748 memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
750 block->block_version = TNG_VERSION;
751 block->header_contents = 0;
752 block->header_contents_size = 0;
753 block->block_contents = 0;
754 block->block_contents_size = 0;
760 * @brief Clean up a file block container.
761 * @param block_p a pointer to the file block container to destroy.
762 * @details All allocated memory in the data structure is freed, as well as
764 * @return TNG_SUCCESS (0) if successful.
766 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
768 tng_gen_block_t block = *block_p;
775 /* fprintf(stderr, "TNG library: Destroying block\n"); */
781 if(block->header_contents)
783 free(block->header_contents);
784 block->header_contents = 0;
786 if(block->block_contents)
788 free(block->block_contents);
789 block->block_contents = 0;
798 /** Read the header of a data block, regardless of its type
799 * @param tng_data is a trajectory data container.
800 * @param block is a general block container.
801 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
804 static tng_function_status tng_block_header_read
805 (tng_trajectory_t tng_data, tng_gen_block_t block)
809 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
811 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
813 return(TNG_CRITICAL);
816 /* First read the header size to be able to read the whole header. */
817 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
818 1, tng_data->input_file) == 0)
820 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
822 return(TNG_CRITICAL);
825 /* If this was the size of the general info block check the endianness */
826 if(ftell(tng_data->input_file) < 9)
828 /* File is little endian */
829 if ( *((const char*)&block->header_contents_size) != 0x00 &&
830 *((const char*)(&block->header_contents_size) + 7) == 0x00)
832 /* If the architecture endianness is little endian no byte swap
833 * will be needed. Otherwise use the functions to swap to little
835 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
837 tng_data->input_endianness_swap_func_32 = 0;
841 tng_data->input_endianness_swap_func_32 =
842 &tng_swap_byte_order_little_endian_32;
844 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
846 tng_data->input_endianness_swap_func_64 = 0;
850 tng_data->input_endianness_swap_func_64 =
851 &tng_swap_byte_order_little_endian_64;
854 /* File is big endian */
857 /* If the architecture endianness is big endian no byte swap
858 * will be needed. Otherwise use the functions to swap to big
860 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
862 tng_data->input_endianness_swap_func_32 = 0;
866 tng_data->input_endianness_swap_func_32 =
867 &tng_swap_byte_order_big_endian_32;
869 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
871 tng_data->input_endianness_swap_func_64 = 0;
875 tng_data->input_endianness_swap_func_64 =
876 &tng_swap_byte_order_big_endian_64;
881 if(tng_data->input_endianness_swap_func_64)
883 if(tng_data->input_endianness_swap_func_64(tng_data,
884 &block->header_contents_size)
887 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
892 /* Move the reading position to the beginning of the header. */
893 fseek(tng_data->input_file, -(long)sizeof(block->header_contents_size),
896 /* If there is already memory allocated for the contents free it (we do not
897 * know if the size is correct). */
898 if(block->header_contents)
900 free(block->header_contents);
903 block->header_contents = malloc(block->header_contents_size);
904 if(!block->header_contents)
906 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
907 block->header_contents_size, __FILE__, __LINE__);
908 return(TNG_CRITICAL);
911 /* Read the whole header into header_contents. This way it can be saved
912 * even if it cannot be interpreted
913 * for one reason or another. */
914 if(fread(block->header_contents, block->header_contents_size, 1,
915 tng_data->input_file) == 0)
917 fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
918 return(TNG_CRITICAL);
921 /* The header contents size has already been read. Skip ahead. */
922 offset = sizeof(block->header_contents_size);
925 /* Copy the respective parameters from the header contents block */
926 memcpy(&block->block_contents_size, block->header_contents+offset,
927 sizeof(block->block_contents_size));
928 if(tng_data->input_endianness_swap_func_64)
930 if(tng_data->input_endianness_swap_func_64(tng_data,
931 &block->block_contents_size)
934 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
939 offset += sizeof(block->block_contents_size);
941 memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
942 if(tng_data->input_endianness_swap_func_64)
944 if(tng_data->input_endianness_swap_func_64(tng_data,
948 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
953 offset += sizeof(block->id);
955 memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
956 offset += TNG_MD5_HASH_LEN;
958 if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
963 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
966 block->name = malloc(len);
969 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
971 return(TNG_CRITICAL);
973 strncpy(block->name, block->header_contents+offset, len);
977 memcpy(&block->block_version, block->header_contents+offset,
978 sizeof(block->block_version));
979 if(tng_data->input_endianness_swap_func_64)
981 if(tng_data->input_endianness_swap_func_64(tng_data,
982 &block->block_version)
985 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
993 /** Write a whole block, both header and contents, regardless of it type
994 * @param tng_data is a trajectory data container.
995 * @param block is a general block container.
996 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
997 * has occurred or TNG_CRITICAL (2) if a major error has occured.
999 /* Disabled until it is used.*/
1001 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1002 // tng_gen_block_t block)
1004 // if(!block->header_contents)
1006 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1007 // return(TNG_FAILURE);
1009 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1010 // tng_data->output_file) != 1)
1012 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1013 // __FILE__, __LINE__);
1014 // return(TNG_CRITICAL);
1017 // if(!block->block_contents)
1019 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1020 // __FILE__, __LINE__);
1021 // return(TNG_FAILURE);
1023 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1024 // tng_data->output_file) != 1)
1026 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1027 // __FILE__, __LINE__);
1028 // return(TNG_CRITICAL);
1030 // return(TNG_SUCCESS);
1033 /** Write the header of a data block, regardless of its type
1034 * @param tng_data is a trajectory data container.
1035 * @param block is a general block container.
1036 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1037 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1038 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1039 * error has occured.
1041 static tng_function_status tng_block_header_write
1042 (tng_trajectory_t tng_data,
1043 tng_gen_block_t block,
1044 const char hash_mode)
1046 int name_len, offset = 0;
1048 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1050 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1052 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1053 __FILE__, __LINE__);
1054 return(TNG_CRITICAL);
1059 block->name = malloc(1);
1062 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1063 __FILE__, __LINE__);
1064 return(TNG_CRITICAL);
1069 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1071 if(hash_mode == TNG_USE_HASH)
1073 tng_block_md5_hash_generate(block);
1076 /* Calculate the size of the header to write */
1077 block->header_contents_size = sizeof(block->header_contents_size) +
1078 sizeof(block->block_contents_size) +
1080 sizeof(block->block_version) +
1084 if(block->header_contents)
1086 free(block->header_contents);
1089 block->header_contents = malloc(block->header_contents_size);
1090 if(!block->header_contents)
1092 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1093 block->header_contents_size, __FILE__, __LINE__);
1094 return(TNG_CRITICAL);
1097 /* First copy all data into the header_contents block and finally write
1098 * the whole block at once. */
1099 memcpy(block->header_contents, &block->header_contents_size,
1100 sizeof(block->header_contents_size));
1101 if(tng_data->output_endianness_swap_func_64)
1103 if(tng_data->output_endianness_swap_func_64(tng_data,
1104 (int64_t *)block->header_contents+offset)
1107 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1108 __FILE__, __LINE__);
1111 offset += sizeof(block->header_contents_size);
1113 memcpy(block->header_contents+offset, &block->block_contents_size,
1114 sizeof(block->block_contents_size));
1115 if(tng_data->output_endianness_swap_func_64)
1117 if(tng_data->output_endianness_swap_func_64(tng_data,
1118 (int64_t *)block->header_contents+offset)
1121 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1122 __FILE__, __LINE__);
1125 offset += sizeof(block->block_contents_size);
1127 memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
1128 if(tng_data->output_endianness_swap_func_64)
1130 if(tng_data->output_endianness_swap_func_64(tng_data,
1131 (int64_t *)block->header_contents+offset)
1134 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1135 __FILE__, __LINE__);
1138 offset += sizeof(block->id);
1140 memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
1141 offset += TNG_MD5_HASH_LEN;
1143 strncpy(block->header_contents+offset, block->name, name_len);
1146 memcpy(block->header_contents+offset, &block->block_version,
1147 sizeof(block->block_version));
1148 if(tng_data->output_endianness_swap_func_64)
1150 if(tng_data->output_endianness_swap_func_64(tng_data,
1151 (int64_t *)block->header_contents+offset)
1154 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1155 __FILE__, __LINE__);
1159 if(fwrite(block->header_contents, block->header_contents_size,
1160 1, tng_data->output_file) != 1)
1162 fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
1163 return(TNG_CRITICAL);
1165 return(TNG_SUCCESS);
1168 /** Read a general info block. This is the first block of a TNG file.
1169 * Populate the fields in tng_data.
1170 * @param tng_data is a trajectory data container.
1171 * @param block is a general block container.
1172 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1173 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
1174 * compared to the md5 hash of the read contents to ensure valid data.
1175 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1176 * error has occured.
1178 static tng_function_status tng_general_info_block_read
1179 (tng_trajectory_t tng_data, tng_gen_block_t block,
1180 const char hash_mode)
1182 int len, offset = 0;
1187 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
1189 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1191 return(TNG_CRITICAL);
1194 temp = realloc(block->block_contents, block->block_contents_size);
1197 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1198 block->block_contents_size, __FILE__, __LINE__);
1199 free(block->block_contents);
1200 block->block_contents = 0;
1201 return(TNG_CRITICAL);
1203 block->block_contents = temp;
1205 /* Read the whole block into block_contents to be able to write it to disk
1206 * even if it cannot be interpreted. */
1207 if(fread(block->block_contents, block->block_contents_size, 1,
1208 tng_data->input_file) == 0)
1210 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1211 return(TNG_CRITICAL);
1214 /* FIXME: Does not check if the size of the contents matches the expected
1215 * size or if the contents can be read. */
1217 if(hash_mode == TNG_USE_HASH)
1219 tng_md5_hash_match_verify(block, &same_hash);
1220 if(same_hash != TNG_TRUE)
1222 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
1224 __FILE__, __LINE__);
1225 /* return(TNG_FAILURE); */
1229 len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
1230 temp = realloc(tng_data->first_program_name, len);
1233 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1234 __FILE__, __LINE__);
1235 free(tng_data->first_program_name);
1236 tng_data->first_program_name = 0;
1237 return(TNG_CRITICAL);
1239 tng_data->first_program_name = temp;
1240 strncpy(tng_data->first_program_name, block->block_contents, len);
1243 len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
1244 temp = realloc(tng_data->last_program_name, len);
1247 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1248 __FILE__, __LINE__);
1249 free(tng_data->last_program_name);
1250 tng_data->last_program_name = 0;
1251 return(TNG_CRITICAL);
1253 tng_data->last_program_name = temp;
1254 strncpy(tng_data->last_program_name, block->block_contents + offset, len);
1257 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1258 temp = realloc(tng_data->first_user_name, len);
1261 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1262 __FILE__, __LINE__);
1263 free(tng_data->first_user_name);
1264 tng_data->first_user_name = 0;
1265 return(TNG_CRITICAL);
1267 tng_data->first_user_name = temp;
1268 strncpy(tng_data->first_user_name, block->block_contents+offset, len);
1271 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1272 temp = realloc(tng_data->last_user_name, len);
1275 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1276 __FILE__, __LINE__);
1277 free(tng_data->last_user_name);
1278 tng_data->last_user_name = 0;
1279 return(TNG_CRITICAL);
1281 tng_data->last_user_name = temp;
1282 strncpy(tng_data->last_user_name, block->block_contents+offset, len);
1285 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1286 temp = realloc(tng_data->first_computer_name, len);
1289 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1290 __FILE__, __LINE__);
1291 free(tng_data->first_computer_name);
1292 tng_data->first_computer_name = 0;
1293 return(TNG_CRITICAL);
1295 tng_data->first_computer_name = temp;
1296 strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
1299 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1300 temp = realloc(tng_data->last_computer_name, len);
1303 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1304 __FILE__, __LINE__);
1305 free(tng_data->last_computer_name);
1306 tng_data->last_computer_name = 0;
1307 return(TNG_CRITICAL);
1309 tng_data->last_computer_name = temp;
1310 strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
1313 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1314 temp = realloc(tng_data->first_pgp_signature, len);
1317 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1318 __FILE__, __LINE__);
1319 free(tng_data->first_pgp_signature);
1320 tng_data->first_pgp_signature = 0;
1321 return(TNG_CRITICAL);
1323 tng_data->first_pgp_signature = temp;
1324 strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
1327 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1328 temp = realloc(tng_data->last_pgp_signature, len);
1331 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1332 __FILE__, __LINE__);
1333 free(tng_data->last_pgp_signature);
1334 tng_data->last_pgp_signature = 0;
1335 return(TNG_CRITICAL);
1337 tng_data->last_pgp_signature = temp;
1338 strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
1341 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
1342 temp = realloc(tng_data->forcefield_name, len);
1345 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
1346 __FILE__, __LINE__);
1347 free(tng_data->forcefield_name);
1348 tng_data->forcefield_name = 0;
1349 return(TNG_CRITICAL);
1351 tng_data->forcefield_name = temp;
1352 strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
1355 memcpy(&tng_data->time, block->block_contents+offset,
1356 sizeof(tng_data->time));
1357 if(tng_data->input_endianness_swap_func_64)
1359 if(tng_data->input_endianness_swap_func_64(tng_data,
1363 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1364 __FILE__, __LINE__);
1367 offset += sizeof(tng_data->time);
1369 memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
1370 sizeof(tng_data->var_num_atoms_flag));
1371 offset += sizeof(tng_data->var_num_atoms_flag);
1373 memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
1374 sizeof(tng_data->frame_set_n_frames));
1375 if(tng_data->input_endianness_swap_func_64)
1377 if(tng_data->input_endianness_swap_func_64(tng_data,
1378 &tng_data->frame_set_n_frames)
1381 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1382 __FILE__, __LINE__);
1385 offset += sizeof(tng_data->frame_set_n_frames);
1387 memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
1388 block->block_contents+offset,
1389 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
1390 if(tng_data->input_endianness_swap_func_64)
1392 if(tng_data->input_endianness_swap_func_64(tng_data,
1393 &tng_data->first_trajectory_frame_set_input_file_pos)
1396 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1397 __FILE__, __LINE__);
1400 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
1402 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
1403 tng_data->first_trajectory_frame_set_input_file_pos;
1406 memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
1407 block->block_contents+offset,
1408 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
1409 if(tng_data->input_endianness_swap_func_64)
1411 if(tng_data->input_endianness_swap_func_64(tng_data,
1412 &tng_data->last_trajectory_frame_set_input_file_pos)
1415 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1416 __FILE__, __LINE__);
1419 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
1421 memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
1422 sizeof(tng_data->medium_stride_length));
1423 if(tng_data->input_endianness_swap_func_64)
1425 if(tng_data->input_endianness_swap_func_64(tng_data,
1426 &tng_data->medium_stride_length)
1429 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1430 __FILE__, __LINE__);
1433 offset += sizeof(tng_data->medium_stride_length);
1435 memcpy(&tng_data->long_stride_length, block->block_contents+offset,
1436 sizeof(tng_data->long_stride_length));
1437 if(tng_data->input_endianness_swap_func_64)
1439 if(tng_data->input_endianness_swap_func_64(tng_data,
1440 &tng_data->long_stride_length)
1443 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1444 __FILE__, __LINE__);
1447 offset += sizeof(tng_data->long_stride_length);
1449 if(block->block_version >= 3)
1451 memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
1452 sizeof(tng_data->distance_unit_exponential));
1453 if(tng_data->input_endianness_swap_func_64)
1455 if(tng_data->input_endianness_swap_func_64(tng_data,
1456 &tng_data->distance_unit_exponential)
1459 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1460 __FILE__, __LINE__);
1465 return(TNG_SUCCESS);
1468 /** Write a general info block. This is the first block of a TNG file.
1469 * @param tng_data is a trajectory data container.
1470 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1471 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1472 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1473 * error has occured.
1475 static tng_function_status tng_general_info_block_write
1476 (tng_trajectory_t tng_data,
1477 const char hash_mode)
1479 int first_program_name_len, first_user_name_len;
1480 int first_computer_name_len, first_pgp_signature_len;
1481 int last_program_name_len, last_user_name_len;
1482 int last_computer_name_len, last_pgp_signature_len;
1483 int forcefield_name_len, name_len;
1485 tng_gen_block_t block;
1487 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1489 return(TNG_CRITICAL);
1492 fseek(tng_data->output_file, 0, SEEK_SET);
1494 /* If the strings are unallocated allocate memory for just string
1496 if(!tng_data->first_program_name)
1498 tng_data->first_program_name = malloc(1);
1499 if(!tng_data->first_program_name)
1501 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1502 __FILE__, __LINE__);
1503 return(TNG_CRITICAL);
1505 tng_data->first_program_name[0] = 0;
1507 if(!tng_data->last_program_name)
1509 tng_data->last_program_name = malloc(1);
1510 if(!tng_data->last_program_name)
1512 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1513 __FILE__, __LINE__);
1514 return(TNG_CRITICAL);
1516 tng_data->last_program_name[0] = 0;
1518 if(!tng_data->first_user_name)
1520 tng_data->first_user_name = malloc(1);
1521 if(!tng_data->first_user_name)
1523 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1524 __FILE__, __LINE__);
1525 return(TNG_CRITICAL);
1527 tng_data->first_user_name[0] = 0;
1529 if(!tng_data->last_user_name)
1531 tng_data->last_user_name = malloc(1);
1532 if(!tng_data->last_user_name)
1534 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1535 __FILE__, __LINE__);
1536 return(TNG_CRITICAL);
1538 tng_data->last_user_name[0] = 0;
1540 if(!tng_data->first_computer_name)
1542 tng_data->first_computer_name = malloc(1);
1543 if(!tng_data->first_computer_name)
1545 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1546 __FILE__, __LINE__);
1547 return(TNG_CRITICAL);
1549 tng_data->first_computer_name[0] = 0;
1551 if(!tng_data->last_computer_name)
1553 tng_data->last_computer_name = malloc(1);
1554 if(!tng_data->last_computer_name)
1556 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1557 __FILE__, __LINE__);
1558 return(TNG_CRITICAL);
1560 tng_data->last_computer_name[0] = 0;
1562 if(!tng_data->first_pgp_signature)
1564 tng_data->first_pgp_signature = malloc(1);
1565 if(!tng_data->first_pgp_signature)
1567 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1568 __FILE__, __LINE__);
1569 return(TNG_CRITICAL);
1571 tng_data->first_pgp_signature[0] = 0;
1573 if(!tng_data->last_pgp_signature)
1575 tng_data->last_pgp_signature = malloc(1);
1576 if(!tng_data->last_pgp_signature)
1578 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1579 __FILE__, __LINE__);
1580 return(TNG_CRITICAL);
1582 tng_data->last_pgp_signature[0] = 0;
1584 if(!tng_data->forcefield_name)
1586 tng_data->forcefield_name = malloc(1);
1587 if(!tng_data->forcefield_name)
1589 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1590 __FILE__, __LINE__);
1591 return(TNG_CRITICAL);
1593 tng_data->forcefield_name[0] = 0;
1596 tng_block_init(&block);
1598 name_len = (int)strlen("GENERAL INFO");
1600 block->name = malloc(name_len + 1);
1603 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
1604 name_len+1, __FILE__, __LINE__);
1605 tng_block_destroy(&block);
1606 return(TNG_CRITICAL);
1609 strcpy(block->name, "GENERAL INFO");
1610 block->id = TNG_GENERAL_INFO;
1612 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
1614 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
1616 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
1618 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
1620 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
1622 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
1624 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
1626 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
1628 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
1631 block->block_contents_size = sizeof(tng_data->time) +
1632 sizeof(tng_data->var_num_atoms_flag) +
1633 sizeof(tng_data->frame_set_n_frames) +
1634 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
1635 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
1636 sizeof(tng_data->medium_stride_length) +
1637 sizeof(tng_data->long_stride_length) +
1638 sizeof(tng_data->distance_unit_exponential) +
1639 first_program_name_len +
1640 last_program_name_len +
1641 first_user_name_len +
1642 last_user_name_len +
1643 first_computer_name_len +
1644 last_computer_name_len +
1645 first_pgp_signature_len +
1646 last_pgp_signature_len +
1647 forcefield_name_len;
1649 if(block->block_contents)
1651 free(block->block_contents);
1653 block->block_contents = malloc(block->block_contents_size);
1654 if(!block->block_contents)
1656 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1657 block->block_contents_size, __FILE__, __LINE__);
1658 tng_block_destroy(&block);
1659 return(TNG_CRITICAL);
1662 strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
1663 offset += first_program_name_len;
1665 strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
1666 offset += last_program_name_len;
1668 strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
1669 offset += first_user_name_len;
1671 strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
1672 offset += last_user_name_len;
1674 strncpy(block->block_contents+offset, tng_data->first_computer_name,
1675 first_computer_name_len);
1676 offset += first_computer_name_len;
1678 strncpy(block->block_contents+offset, tng_data->last_computer_name,
1679 last_computer_name_len);
1680 offset += last_computer_name_len;
1682 strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
1683 first_pgp_signature_len);
1684 offset += first_pgp_signature_len;
1686 strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
1687 last_pgp_signature_len);
1688 offset += last_pgp_signature_len;
1690 strncpy(block->block_contents+offset, tng_data->forcefield_name,
1691 forcefield_name_len);
1692 offset += forcefield_name_len;
1694 memcpy(block->block_contents+offset, &tng_data->time,
1695 sizeof(tng_data->time));
1696 if(tng_data->output_endianness_swap_func_64)
1698 if(tng_data->output_endianness_swap_func_64(tng_data,
1699 (int64_t *)block->header_contents+offset)
1702 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1703 __FILE__, __LINE__);
1706 offset += sizeof(tng_data->time);
1708 memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
1709 sizeof(tng_data->var_num_atoms_flag));
1710 offset += sizeof(tng_data->var_num_atoms_flag);
1712 memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
1713 sizeof(tng_data->frame_set_n_frames));
1714 if(tng_data->output_endianness_swap_func_64)
1716 if(tng_data->output_endianness_swap_func_64(tng_data,
1717 (int64_t *)block->header_contents+offset)
1720 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1721 __FILE__, __LINE__);
1724 offset += sizeof(tng_data->frame_set_n_frames);
1726 memcpy(block->block_contents+offset,
1727 &tng_data->first_trajectory_frame_set_input_file_pos,
1728 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
1729 if(tng_data->output_endianness_swap_func_64)
1731 if(tng_data->output_endianness_swap_func_64(tng_data,
1732 (int64_t *)block->header_contents+offset)
1735 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1736 __FILE__, __LINE__);
1739 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
1741 memcpy(block->block_contents+offset,
1742 &tng_data->last_trajectory_frame_set_input_file_pos,
1743 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
1744 if(tng_data->output_endianness_swap_func_64)
1746 if(tng_data->output_endianness_swap_func_64(tng_data,
1747 (int64_t *)block->header_contents+offset)
1750 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1751 __FILE__, __LINE__);
1754 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
1756 memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
1757 sizeof(tng_data->medium_stride_length));
1758 if(tng_data->output_endianness_swap_func_64)
1760 if(tng_data->output_endianness_swap_func_64(tng_data,
1761 (int64_t *)block->header_contents+offset)
1764 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1765 __FILE__, __LINE__);
1768 offset += sizeof(tng_data->medium_stride_length);
1770 memcpy(block->block_contents+offset, &tng_data->long_stride_length,
1771 sizeof(tng_data->long_stride_length));
1772 if(tng_data->output_endianness_swap_func_64)
1774 if(tng_data->output_endianness_swap_func_64(tng_data,
1775 (int64_t *)block->header_contents+offset)
1778 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1779 __FILE__, __LINE__);
1782 offset += sizeof(tng_data->long_stride_length);
1784 memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
1785 sizeof(tng_data->distance_unit_exponential));
1786 if(tng_data->output_endianness_swap_func_64)
1788 if(tng_data->output_endianness_swap_func_64(tng_data,
1789 (int64_t *)block->header_contents+offset)
1792 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1793 __FILE__, __LINE__);
1797 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
1799 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
1800 tng_data->output_file_path, __FILE__, __LINE__);
1801 tng_block_destroy(&block);
1802 return(TNG_CRITICAL);
1805 if(fwrite(block->block_contents, block->block_contents_size, 1,
1806 tng_data->output_file) != 1)
1808 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
1809 tng_block_destroy(&block);
1810 return(TNG_CRITICAL);
1813 tng_block_destroy(&block);
1815 return(TNG_SUCCESS);
1818 /** Read the chain data of a molecules block.
1819 * @param tng_data is a trajectory data container.
1820 * @param block is a general block container.
1821 * @param chain is the chain data container.
1822 * @param offset is the offset of the block input and is updated when reading.
1823 * @return TNG_SUCCESS(0) is successful.
1825 static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
1826 tng_gen_block_t block,
1832 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1834 memcpy(&chain->id, block->block_contents+*offset,
1836 if(tng_data->input_endianness_swap_func_64)
1838 if(tng_data->input_endianness_swap_func_64(tng_data,
1842 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1843 __FILE__, __LINE__);
1846 *offset += sizeof(chain->id);
1848 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
1850 chain->name = malloc(len);
1851 strncpy(chain->name,
1852 block->block_contents+*offset, len);
1855 memcpy(&chain->n_residues, block->block_contents+*offset,
1856 sizeof(chain->n_residues));
1857 if(tng_data->input_endianness_swap_func_64)
1859 if(tng_data->input_endianness_swap_func_64(tng_data,
1863 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1864 __FILE__, __LINE__);
1867 *offset += sizeof(chain->n_residues);
1869 return(TNG_SUCCESS);
1872 /** Write the chain data of a molecules block.
1873 * @param tng_data is a trajectory data container.
1874 * @param block is a general block container.
1875 * @param chain is the chain data container.
1876 * @param offset is the offset of the block output and is updated when writing.
1877 * @return TNG_SUCCESS(0) is successful.
1879 static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
1880 tng_gen_block_t block,
1886 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1888 memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
1889 if(tng_data->output_endianness_swap_func_64)
1891 if(tng_data->output_endianness_swap_func_64(tng_data,
1892 (int64_t *)block->header_contents+*offset)
1895 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1896 __FILE__, __LINE__);
1899 *offset += sizeof(chain->id);
1901 len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
1902 strncpy(block->block_contents + *offset, chain->name, len);
1905 memcpy(block->block_contents+*offset, &chain->n_residues,
1906 sizeof(chain->n_residues));
1907 if(tng_data->output_endianness_swap_func_64)
1909 if(tng_data->output_endianness_swap_func_64(tng_data,
1910 (int64_t *)block->header_contents+*offset)
1913 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1914 __FILE__, __LINE__);
1917 *offset += sizeof(chain->n_residues);
1919 return(TNG_SUCCESS);
1922 /** Read the residue data of a molecules block.
1923 * @param tng_data is a trajectory data container.
1924 * @param block is a general block container.
1925 * @param residue is the residue data container.
1926 * @param offset is the offset of the block input and is updated when reading.
1927 * @return TNG_SUCCESS(0) is successful.
1929 static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
1930 tng_gen_block_t block,
1931 tng_residue_t residue,
1936 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1938 memcpy(&residue->id, block->block_contents+*offset,
1939 sizeof(residue->id));
1940 if(tng_data->input_endianness_swap_func_64)
1942 if(tng_data->input_endianness_swap_func_64(tng_data,
1946 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1947 __FILE__, __LINE__);
1950 *offset += sizeof(residue->id);
1952 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
1954 residue->name = malloc(len);
1955 strncpy(residue->name,
1956 block->block_contents+*offset, len);
1959 memcpy(&residue->n_atoms, block->block_contents+*offset,
1960 sizeof(residue->n_atoms));
1961 if(tng_data->input_endianness_swap_func_64)
1963 if(tng_data->input_endianness_swap_func_64(tng_data,
1967 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1968 __FILE__, __LINE__);
1971 *offset += sizeof(residue->n_atoms);
1973 return(TNG_SUCCESS);
1976 /** Write the residue data of a molecules block.
1977 * @param tng_data is a trajectory data container.
1978 * @param block is a general block container.
1979 * @param residue is the residue data container.
1980 * @param offset is the offset of the block output and is updated when writing.
1981 * @return TNG_SUCCESS(0) is successful.
1983 static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
1984 tng_gen_block_t block,
1985 tng_residue_t residue,
1990 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
1992 memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
1993 if(tng_data->output_endianness_swap_func_64)
1995 if(tng_data->output_endianness_swap_func_64(tng_data,
1996 (int64_t *)block->header_contents+*offset)
1999 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2000 __FILE__, __LINE__);
2003 *offset += sizeof(residue->id);
2005 len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2006 strncpy(block->block_contents + *offset, residue->name, len);
2009 memcpy(block->block_contents+*offset, &residue->n_atoms,
2010 sizeof(residue->n_atoms));
2011 if(tng_data->output_endianness_swap_func_64)
2013 if(tng_data->output_endianness_swap_func_64(tng_data,
2014 (int64_t *)block->header_contents+*offset)
2017 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2018 __FILE__, __LINE__);
2021 *offset += sizeof(residue->n_atoms);
2023 return(TNG_SUCCESS);
2026 /** Read the atom data of a molecules block.
2027 * @param tng_data is a trajectory data container.
2028 * @param block is a general block container.
2029 * @param atom is the atom data container.
2030 * @param offset is the offset of the block input and is updated when reading.
2031 * @return TNG_SUCCESS(0) is successful.
2033 static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
2034 tng_gen_block_t block,
2040 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2042 memcpy(&atom->id, block->block_contents+*offset,
2044 if(tng_data->input_endianness_swap_func_64)
2046 if(tng_data->input_endianness_swap_func_64(tng_data,
2050 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2051 __FILE__, __LINE__);
2054 *offset += sizeof(atom->id);
2056 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2058 atom->name = malloc(len);
2060 block->block_contents+*offset, len);
2063 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2065 atom->atom_type = malloc(len);
2066 strncpy(atom->atom_type,
2067 block->block_contents+*offset, len);
2070 return(TNG_SUCCESS);
2073 /** Write the atom data of a molecules block.
2074 * @param tng_data is a trajectory data container.
2075 * @param block is a general block container.
2076 * @param atom is the atom data container.
2077 * @param offset is the offset of the block output and is updated when writing.
2078 * @return TNG_SUCCESS(0) is successful.
2080 static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
2081 tng_gen_block_t block,
2087 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2089 memcpy(block->block_contents+*offset, &atom->id,
2091 if(tng_data->output_endianness_swap_func_64)
2093 if(tng_data->output_endianness_swap_func_64(tng_data,
2094 (int64_t *)block->header_contents+*offset)
2097 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2098 __FILE__, __LINE__);
2101 *offset += sizeof(atom->id);
2103 len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2104 strncpy(block->block_contents + *offset, atom->name, len);
2107 len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2108 strncpy(block->block_contents + *offset, atom->atom_type, len);
2111 return(TNG_SUCCESS);
2114 /** Read a molecules block. Contains chain, residue and atom data
2115 * @param tng_data is a trajectory data container.
2116 * @param block is a general block container.
2117 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2118 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2119 * compared to the md5 hash of the read contents to ensure valid data.
2120 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2121 * error has occured.
2123 static tng_function_status tng_molecules_block_read
2124 (tng_trajectory_t tng_data,
2125 tng_gen_block_t block,
2126 const char hash_mode)
2129 int len, offset = 0;
2130 tng_molecule_t molecule;
2132 tng_residue_t residue;
2137 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2139 return(TNG_CRITICAL);
2142 if(block->block_contents)
2144 free(block->block_contents);
2147 block->block_contents = malloc(block->block_contents_size);
2148 if(!block->block_contents)
2150 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2151 block->block_contents_size, __FILE__, __LINE__);
2152 return(TNG_CRITICAL);
2155 /* Read the whole block into block_contents to be able to write it to disk
2156 * even if it cannot be interpreted. */
2157 if(fread(block->block_contents, block->block_contents_size, 1,
2158 tng_data->input_file) == 0)
2160 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
2163 /* FIXME: Does not check if the size of the contents matches the expected
2164 * size or if the contents can be read. */
2166 if(hash_mode == TNG_USE_HASH)
2168 tng_md5_hash_match_verify(block, &same_hash);
2169 if(same_hash != TNG_TRUE)
2171 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
2173 __FILE__, __LINE__);
2177 if(tng_data->molecules)
2179 for(i=tng_data->n_molecules; i--;)
2181 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
2183 free(tng_data->molecules);
2184 tng_data->molecules = 0;
2185 tng_data->n_molecules = 0;
2188 memcpy(&tng_data->n_molecules, block->block_contents,
2189 sizeof(tng_data->n_molecules));
2190 if(tng_data->input_endianness_swap_func_64)
2192 if(tng_data->input_endianness_swap_func_64(tng_data,
2193 &tng_data->n_molecules)
2196 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2197 __FILE__, __LINE__);
2200 offset += sizeof(tng_data->n_molecules);
2202 if(tng_data->molecules)
2204 free(tng_data->molecules);
2207 tng_data->n_particles = 0;
2209 tng_data->molecules = malloc(tng_data->n_molecules *
2210 sizeof(struct tng_molecule));
2211 if(!tng_data->molecules)
2213 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2214 tng_data->n_molecules * sizeof(struct tng_molecule),
2215 __FILE__, __LINE__);
2216 return(TNG_CRITICAL);
2219 if(!tng_data->var_num_atoms_flag)
2221 if(tng_data->molecule_cnt_list)
2223 free(tng_data->molecule_cnt_list);
2225 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
2226 tng_data->n_molecules);
2227 if(!tng_data->molecule_cnt_list)
2229 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2230 tng_data->n_molecules * sizeof(struct tng_molecule),
2231 __FILE__, __LINE__);
2232 return(TNG_CRITICAL);
2236 /* Read each molecule from file */
2237 for(i=0; i < tng_data->n_molecules; i++)
2239 molecule = &tng_data->molecules[i];
2241 memcpy(&molecule->id, block->block_contents+offset,
2242 sizeof(molecule->id));
2243 if(tng_data->input_endianness_swap_func_64)
2245 if(tng_data->input_endianness_swap_func_64(tng_data,
2249 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2250 __FILE__, __LINE__);
2253 offset += sizeof(molecule->id);
2255 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
2256 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2257 molecule->name = malloc(len);
2258 strncpy(molecule->name, block->block_contents+offset, len);
2261 memcpy(&molecule->quaternary_str, block->block_contents+offset,
2262 sizeof(molecule->quaternary_str));
2263 if(tng_data->input_endianness_swap_func_64)
2265 if(tng_data->input_endianness_swap_func_64(tng_data,
2266 &molecule->quaternary_str)
2269 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2270 __FILE__, __LINE__);
2273 offset += sizeof(molecule->quaternary_str);
2275 if(!tng_data->var_num_atoms_flag)
2277 memcpy(&tng_data->molecule_cnt_list[i],
2278 block->block_contents+offset,
2280 if(tng_data->input_endianness_swap_func_64)
2282 if(tng_data->input_endianness_swap_func_64(tng_data,
2283 &tng_data->molecule_cnt_list[i])
2286 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2287 __FILE__, __LINE__);
2290 offset += sizeof(int64_t);
2294 memcpy(&molecule->n_chains, block->block_contents+offset,
2295 sizeof(molecule->n_chains));
2296 if(tng_data->input_endianness_swap_func_64)
2298 if(tng_data->input_endianness_swap_func_64(tng_data,
2299 &molecule->n_chains)
2302 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2303 __FILE__, __LINE__);
2306 offset += sizeof(molecule->n_chains);
2308 memcpy(&molecule->n_residues, block->block_contents+offset,
2309 sizeof(molecule->n_residues));
2310 if(tng_data->input_endianness_swap_func_64)
2312 if(tng_data->input_endianness_swap_func_64(tng_data,
2313 &molecule->n_residues)
2316 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2317 __FILE__, __LINE__);
2320 offset += sizeof(molecule->n_residues);
2322 memcpy(&molecule->n_atoms, block->block_contents+offset,
2323 sizeof(molecule->n_atoms));
2324 if(tng_data->input_endianness_swap_func_64)
2326 if(tng_data->input_endianness_swap_func_64(tng_data,
2330 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2331 __FILE__, __LINE__);
2334 offset += sizeof(molecule->n_atoms);
2336 tng_data->n_particles += molecule->n_atoms *
2337 tng_data->molecule_cnt_list[i];
2339 if(molecule->n_chains > 0)
2341 molecule->chains = malloc(molecule->n_chains *
2342 sizeof(struct tng_chain));
2343 if(!molecule->chains)
2345 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2346 molecule->n_chains * sizeof(struct tng_chain),
2347 __FILE__, __LINE__);
2348 return(TNG_CRITICAL);
2351 chain = molecule->chains;
2358 if(molecule->n_residues > 0)
2360 molecule->residues = malloc(molecule->n_residues *
2361 sizeof(struct tng_residue));
2362 if(!molecule->residues)
2364 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2365 molecule->n_residues * sizeof(struct tng_residue),
2366 __FILE__, __LINE__);
2367 if(molecule->chains)
2369 free(molecule->chains);
2370 molecule->chains = 0;
2372 return(TNG_CRITICAL);
2375 residue = molecule->residues;
2382 molecule->atoms = malloc(molecule->n_atoms *
2383 sizeof(struct tng_atom));
2384 if(!molecule->atoms)
2386 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2387 molecule->n_atoms * sizeof(struct tng_atom),
2388 __FILE__, __LINE__);
2389 if(molecule->chains)
2391 free(molecule->chains);
2392 molecule->chains = 0;
2394 if(molecule->residues)
2396 free(molecule->residues);
2397 molecule->residues = 0;
2399 return(TNG_CRITICAL);
2402 atom = molecule->atoms;
2404 if(molecule->n_chains > 0)
2406 /* Read the chains of the molecule */
2407 for(j=molecule->n_chains; j--;)
2409 chain->molecule = molecule;
2411 tng_chain_data_read(tng_data, block, chain, &offset);
2413 chain->residues = molecule->residues;
2414 residue = chain->residues;
2416 /* Read the residues of the chain */
2417 for(k=chain->n_residues; k--;)
2419 residue->chain = chain;
2421 tng_residue_data_read(tng_data, block, residue, &offset);
2423 residue->atoms_offset = atom - molecule->atoms;
2424 /* Read the atoms of the residue */
2425 for(l=residue->n_atoms; l--;)
2427 atom->residue = residue;
2429 tng_atom_data_read(tng_data, block, atom, &offset);
2440 if(molecule->n_residues > 0)
2442 for(k=molecule->n_residues; k--;)
2446 tng_residue_data_read(tng_data, block, residue, &offset);
2448 residue->atoms_offset = atom - molecule->atoms;
2449 /* Read the atoms of the residue */
2450 for(l=residue->n_atoms; l--;)
2452 atom->residue = residue;
2454 tng_atom_data_read(tng_data, block, atom, &offset);
2463 for(l=molecule->n_atoms; l--;)
2467 tng_atom_data_read(tng_data, block, atom, &offset);
2474 memcpy(&molecule->n_bonds, block->block_contents+offset,
2475 sizeof(molecule->n_bonds));
2476 if(tng_data->input_endianness_swap_func_64)
2478 if(tng_data->input_endianness_swap_func_64(tng_data,
2482 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2483 __FILE__, __LINE__);
2486 offset += sizeof(molecule->n_bonds);
2488 if(molecule->n_bonds > 0)
2490 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
2491 sizeof(struct tng_bond));
2492 if(!molecule->bonds)
2494 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2495 molecule->n_bonds * sizeof(struct tng_bond),
2496 __FILE__, __LINE__);
2497 if(molecule->chains)
2499 free(molecule->chains);
2500 molecule->chains = 0;
2502 if(molecule->residues)
2504 free(molecule->residues);
2505 molecule->residues = 0;
2509 free(molecule->atoms);
2510 molecule->atoms = 0;
2512 return(TNG_CRITICAL);
2515 bond = molecule->bonds;
2517 for(j=molecule->n_bonds; j--;)
2519 memcpy(&bond->from_atom_id, block->block_contents+offset,
2520 sizeof(bond->from_atom_id));
2521 if(tng_data->input_endianness_swap_func_64)
2523 if(tng_data->input_endianness_swap_func_64(tng_data,
2524 &bond->from_atom_id)
2527 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2528 __FILE__, __LINE__);
2531 offset += sizeof(bond->from_atom_id);
2533 memcpy(&bond->to_atom_id, block->block_contents+offset,
2534 sizeof(bond->to_atom_id));
2535 if(tng_data->input_endianness_swap_func_64)
2537 if(tng_data->input_endianness_swap_func_64(tng_data,
2541 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2542 __FILE__, __LINE__);
2545 offset += sizeof(bond->to_atom_id);
2552 molecule->bonds = 0;
2556 return(TNG_SUCCESS);
2559 /** Write a molecules block.
2560 * @param tng_data is a trajectory data container.
2561 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2562 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2563 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2564 * error has occured.
2566 static tng_function_status tng_molecules_block_write
2567 (tng_trajectory_t tng_data,
2568 const char hash_mode)
2570 int len = 0, name_len, offset = 0;
2572 tng_molecule_t molecule;
2574 tng_residue_t residue;
2577 tng_gen_block_t block;
2579 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2581 return(TNG_CRITICAL);
2584 /* First predict the size of the block */
2585 for(i = 0; i < tng_data->n_molecules; i++)
2587 molecule = &tng_data->molecules[i];
2590 molecule->name = malloc(1);
2593 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2594 __FILE__, __LINE__);
2595 return(TNG_CRITICAL);
2597 molecule->name[0] = 0;
2599 len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
2601 chain = molecule->chains;
2602 for(j = molecule->n_chains; j--;)
2604 len += sizeof(chain->id);
2608 chain->name = malloc(1);
2611 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2612 __FILE__, __LINE__);
2613 return(TNG_CRITICAL);
2617 len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2619 len += sizeof(chain->n_residues);
2624 residue = molecule->residues;
2625 for(j = molecule->n_residues; j--;)
2627 len += sizeof(residue->id);
2631 residue->name = malloc(1);
2634 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2635 __FILE__, __LINE__);
2636 return(TNG_CRITICAL);
2638 residue->name[0] = 0;
2640 len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2642 len += sizeof(residue->n_atoms);
2647 atom = molecule->atoms;
2648 for(j = molecule->n_atoms; j--;)
2650 len += sizeof(atom->id);
2653 atom->name = malloc(1);
2656 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2657 __FILE__, __LINE__);
2658 return(TNG_CRITICAL);
2662 len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2664 if(!atom->atom_type)
2666 atom->atom_type = malloc(1);
2667 if(!atom->atom_type)
2669 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2670 __FILE__, __LINE__);
2671 return(TNG_CRITICAL);
2673 atom->atom_type[0] = 0;
2675 len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2680 for(j = molecule->n_bonds; j--;)
2682 len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
2686 tng_block_init(&block);
2688 name_len = (int)strlen("MOLECULES");
2690 block->name = malloc(name_len + 1);
2693 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2694 name_len+1, __FILE__, __LINE__);
2695 tng_block_destroy(&block);
2696 return(TNG_CRITICAL);
2699 strcpy(block->name, "MOLECULES");
2700 block->id = TNG_MOLECULES;
2702 block->block_contents_size = sizeof(tng_data->n_molecules) +
2703 (sizeof(molecule->id) +
2704 sizeof(molecule->quaternary_str) +
2705 sizeof(molecule->n_chains) +
2706 sizeof(molecule->n_residues) +
2707 sizeof(molecule->n_atoms) +
2708 sizeof(molecule->n_bonds)) *
2709 tng_data->n_molecules +
2712 if(!tng_data->var_num_atoms_flag)
2714 block->block_contents_size += tng_data->n_molecules * sizeof(int64_t);
2717 block->block_contents = malloc(block->block_contents_size);
2718 if(!block->block_contents)
2720 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2721 block->block_contents_size, __FILE__, __LINE__);
2722 tng_block_destroy(&block);
2723 return(TNG_CRITICAL);
2726 memcpy(block->block_contents+offset, &tng_data->n_molecules,
2727 sizeof(tng_data->n_molecules));
2728 if(tng_data->output_endianness_swap_func_64)
2730 if(tng_data->output_endianness_swap_func_64(tng_data,
2731 (int64_t *)block->header_contents+offset)
2734 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2735 __FILE__, __LINE__);
2738 offset += sizeof(tng_data->n_molecules);
2740 for(i = 0; i < tng_data->n_molecules; i++)
2742 molecule = &tng_data->molecules[i];
2743 memcpy(block->block_contents+offset, &molecule->id,
2744 sizeof(molecule->id));
2745 if(tng_data->output_endianness_swap_func_64)
2747 if(tng_data->output_endianness_swap_func_64(tng_data,
2748 (int64_t *)block->header_contents+offset)
2751 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2752 __FILE__, __LINE__);
2755 offset += sizeof(molecule->id);
2757 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
2758 len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
2759 strncpy(block->block_contents + offset, molecule->name, len);
2762 memcpy(block->block_contents+offset, &molecule->quaternary_str,
2763 sizeof(molecule->quaternary_str));
2764 if(tng_data->output_endianness_swap_func_64)
2766 if(tng_data->output_endianness_swap_func_64(tng_data,
2767 (int64_t *)block->header_contents+offset)
2770 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2771 __FILE__, __LINE__);
2774 offset += sizeof(molecule->quaternary_str);
2776 if(!tng_data->var_num_atoms_flag)
2778 memcpy(block->block_contents+offset,
2779 &tng_data->molecule_cnt_list[i], sizeof(int64_t));
2780 if(tng_data->output_endianness_swap_func_64)
2782 if(tng_data->output_endianness_swap_func_64(tng_data,
2783 (int64_t *)block->header_contents+offset)
2786 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2787 __FILE__, __LINE__);
2790 offset += sizeof(int64_t);
2793 memcpy(block->block_contents+offset, &molecule->n_chains,
2794 sizeof(molecule->n_chains));
2795 if(tng_data->output_endianness_swap_func_64)
2797 if(tng_data->output_endianness_swap_func_64(tng_data,
2798 (int64_t *)block->header_contents+offset)
2801 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2802 __FILE__, __LINE__);
2805 offset += sizeof(molecule->n_chains);
2807 memcpy(block->block_contents+offset, &molecule->n_residues,
2808 sizeof(molecule->n_residues));
2809 if(tng_data->output_endianness_swap_func_64)
2811 if(tng_data->output_endianness_swap_func_64(tng_data,
2812 (int64_t *)block->header_contents+offset)
2815 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2816 __FILE__, __LINE__);
2819 offset += sizeof(molecule->n_residues);
2821 memcpy(block->block_contents+offset, &molecule->n_atoms,
2822 sizeof(molecule->n_atoms));
2823 if(tng_data->output_endianness_swap_func_64)
2825 if(tng_data->output_endianness_swap_func_64(tng_data,
2826 (int64_t *)block->header_contents+offset)
2829 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2830 __FILE__, __LINE__);
2833 offset += sizeof(molecule->n_atoms);
2835 if(molecule->n_chains > 0)
2837 chain = molecule->chains;
2838 for(j = molecule->n_chains; j--;)
2840 tng_chain_data_write(tng_data, block, chain, &offset);
2842 residue = chain->residues;
2843 for(k = chain->n_residues; k--;)
2845 tng_residue_data_write(tng_data, block, residue, &offset);
2847 atom = molecule->atoms + residue->atoms_offset;
2848 for(l = residue->n_atoms; l--;)
2850 tng_atom_data_write(tng_data, block, atom, &offset);
2861 if(molecule->n_residues > 0)
2863 residue = molecule->residues;
2864 for(k = molecule->n_residues; k--;)
2866 tng_residue_data_write(tng_data, block, residue, &offset);
2868 atom = molecule->atoms + residue->atoms_offset;
2869 for(l = residue->n_atoms; l--;)
2871 tng_atom_data_write(tng_data, block, atom, &offset);
2880 atom = molecule->atoms;
2881 for(l = molecule->n_atoms; l--;)
2883 tng_atom_data_write(tng_data, block, atom, &offset);
2890 memcpy(block->block_contents+offset, &molecule->n_bonds,
2891 sizeof(molecule->n_bonds));
2892 if(tng_data->output_endianness_swap_func_64)
2894 if(tng_data->output_endianness_swap_func_64(tng_data,
2895 (int64_t *)block->header_contents+offset)
2898 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2899 __FILE__, __LINE__);
2902 offset += sizeof(molecule->n_bonds);
2904 bond = molecule->bonds;
2905 for(j = molecule->n_bonds; j--;)
2907 memcpy(block->block_contents+offset, &bond->from_atom_id,
2908 sizeof(bond->from_atom_id));
2909 if(tng_data->output_endianness_swap_func_64)
2911 if(tng_data->output_endianness_swap_func_64(tng_data,
2912 (int64_t *)block->header_contents+offset)
2915 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2916 __FILE__, __LINE__);
2919 offset += sizeof(bond->from_atom_id);
2921 memcpy(block->block_contents+offset, &bond->to_atom_id,
2922 sizeof(bond->to_atom_id));
2923 if(tng_data->output_endianness_swap_func_64)
2925 if(tng_data->output_endianness_swap_func_64(tng_data,
2926 (int64_t *)block->header_contents+offset)
2929 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2930 __FILE__, __LINE__);
2933 offset += sizeof(bond->to_atom_id);
2939 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
2941 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2942 tng_data->output_file_path, __FILE__, __LINE__);
2943 tng_block_destroy(&block);
2944 return(TNG_CRITICAL);
2947 if(fwrite(block->block_contents, block->block_contents_size, 1,
2948 tng_data->output_file) != 1)
2950 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
2951 __FILE__, __LINE__);
2952 tng_block_destroy(&block);
2953 return(TNG_CRITICAL);
2956 tng_block_destroy(&block);
2958 return(TNG_SUCCESS);
2961 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
2962 * @param tng_data is a trajectory data container.
2963 * @param block is a general block container.
2964 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2965 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2966 * compared to the md5 hash of the read contents to ensure valid data.
2967 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2968 * error has occured.
2970 static tng_function_status tng_frame_set_block_read
2971 (tng_trajectory_t tng_data,
2972 tng_gen_block_t block,
2973 const char hash_mode)
2977 int64_t i, prev_n_particles;
2979 tng_trajectory_frame_set_t frame_set =
2980 &tng_data->current_trajectory_frame_set;
2982 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2984 return(TNG_CRITICAL);
2987 if(block->block_contents)
2989 free(block->block_contents);
2992 block->block_contents = malloc(block->block_contents_size);
2993 if(!block->block_contents)
2995 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2996 block->block_contents_size, __FILE__, __LINE__);
2997 return(TNG_CRITICAL);
3000 /* Read the whole block into block_contents to be able to write it to
3001 * disk even if it cannot be interpreted. */
3002 if(fread(block->block_contents, block->block_contents_size, 1,
3003 tng_data->input_file) == 0)
3005 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3006 return(TNG_CRITICAL);
3009 /* FIXME: Does not check if the size of the contents matches the expected
3010 * size or if the contents can be read. */
3012 file_pos = (int64_t)ftell(tng_data->input_file) -
3013 (long)(block->block_contents_size + block->header_contents_size);
3015 if(hash_mode == TNG_USE_HASH)
3017 tng_md5_hash_match_verify(block, &same_hash);
3018 if(same_hash != TNG_TRUE)
3020 fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %ld Hashes do not match. "
3022 file_pos, __FILE__, __LINE__);
3023 /* return(TNG_FAILURE); */
3027 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3029 tng_frame_set_particle_mapping_free(tng_data);
3031 if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
3033 tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
3035 /* FIXME: Should check the frame number instead of the file_pos, in case
3036 * frame sets are not in order */
3037 if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
3039 tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
3042 memcpy(&frame_set->first_frame, block->block_contents,
3043 sizeof(frame_set->first_frame));
3044 if(tng_data->input_endianness_swap_func_64)
3046 if(tng_data->input_endianness_swap_func_64(tng_data,
3047 &frame_set->first_frame)
3050 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3051 __FILE__, __LINE__);
3054 offset += sizeof(frame_set->first_frame);
3056 memcpy(&frame_set->n_frames, block->block_contents + offset,
3057 sizeof(frame_set->n_frames));
3058 if(tng_data->input_endianness_swap_func_64)
3060 if(tng_data->input_endianness_swap_func_64(tng_data,
3061 &frame_set->n_frames)
3064 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3065 __FILE__, __LINE__);
3068 offset += sizeof(frame_set->n_frames);
3070 if(tng_data->var_num_atoms_flag)
3072 prev_n_particles = frame_set->n_particles;
3073 frame_set->n_particles = 0;
3074 /* If the list of molecule counts has already been created assume that
3075 * it is of correct size. */
3076 if(!frame_set->molecule_cnt_list)
3078 frame_set->molecule_cnt_list =
3079 malloc(sizeof(int64_t) * tng_data->n_molecules);
3081 if(!frame_set->molecule_cnt_list)
3083 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3084 sizeof(int64_t) * tng_data->n_molecules,
3085 __FILE__, __LINE__);
3086 return(TNG_CRITICAL);
3089 for(i = 0; i < tng_data->n_molecules; i++)
3091 memcpy(&frame_set->molecule_cnt_list[i],
3092 block->block_contents + offset,
3094 if(tng_data->input_endianness_swap_func_64)
3096 if(tng_data->input_endianness_swap_func_64(tng_data,
3097 &frame_set->molecule_cnt_list[i])
3100 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3101 __FILE__, __LINE__);
3104 offset += sizeof(int64_t);
3105 frame_set->n_particles += tng_data->molecules[i].n_atoms *
3106 frame_set->molecule_cnt_list[i];
3108 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
3110 /* FIXME: Particle dependent data memory management */
3114 memcpy(&frame_set->next_frame_set_file_pos,
3115 block->block_contents + offset,
3116 sizeof(frame_set->next_frame_set_file_pos));
3117 if(tng_data->input_endianness_swap_func_64)
3119 if(tng_data->input_endianness_swap_func_64(tng_data,
3120 &frame_set->next_frame_set_file_pos)
3123 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3124 __FILE__, __LINE__);
3127 offset += sizeof(frame_set->next_frame_set_file_pos);
3129 memcpy(&frame_set->prev_frame_set_file_pos,
3130 block->block_contents + offset,
3131 sizeof(frame_set->prev_frame_set_file_pos));
3132 if(tng_data->input_endianness_swap_func_64)
3134 if(tng_data->input_endianness_swap_func_64(tng_data,
3135 &frame_set->prev_frame_set_file_pos)
3138 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3139 __FILE__, __LINE__);
3142 offset += sizeof(frame_set->prev_frame_set_file_pos);
3144 memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
3145 block->block_contents + offset,
3146 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
3147 if(tng_data->input_endianness_swap_func_64)
3149 if(tng_data->input_endianness_swap_func_64(tng_data,
3150 &frame_set->medium_stride_next_frame_set_file_pos)
3153 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3154 __FILE__, __LINE__);
3157 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
3159 memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
3160 block->block_contents + offset,
3161 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
3162 if(tng_data->input_endianness_swap_func_64)
3164 if(tng_data->input_endianness_swap_func_64(tng_data,
3165 &frame_set->medium_stride_prev_frame_set_file_pos)
3168 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3169 __FILE__, __LINE__);
3172 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
3174 memcpy(&frame_set->long_stride_next_frame_set_file_pos,
3175 block->block_contents + offset,
3176 sizeof(frame_set->long_stride_next_frame_set_file_pos));
3177 if(tng_data->input_endianness_swap_func_64)
3179 if(tng_data->input_endianness_swap_func_64(tng_data,
3180 &frame_set->long_stride_next_frame_set_file_pos)
3183 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3184 __FILE__, __LINE__);
3187 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
3189 memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
3190 block->block_contents + offset,
3191 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
3192 if(tng_data->input_endianness_swap_func_64)
3194 if(tng_data->input_endianness_swap_func_64(tng_data,
3195 &frame_set->long_stride_prev_frame_set_file_pos)
3198 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3199 __FILE__, __LINE__);
3202 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
3204 if(block->block_version >= 3)
3206 memcpy(&frame_set->first_frame_time,
3207 block->block_contents + offset,
3208 sizeof(frame_set->first_frame_time));
3209 if(tng_data->input_endianness_swap_func_64)
3211 if(tng_data->input_endianness_swap_func_64(tng_data,
3212 (int64_t *)&frame_set->first_frame_time)
3215 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3216 __FILE__, __LINE__);
3219 offset += sizeof(frame_set->first_frame_time);
3221 memcpy(&tng_data->time_per_frame,
3222 block->block_contents + offset,
3223 sizeof(tng_data->time_per_frame));
3224 if(tng_data->input_endianness_swap_func_64)
3226 if(tng_data->input_endianness_swap_func_64(tng_data,
3227 (int64_t *)&tng_data->time_per_frame)
3230 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3231 __FILE__, __LINE__);
3237 frame_set->first_frame_time = -1;
3238 tng_data->time_per_frame = -1;
3241 frame_set->n_written_frames = frame_set->n_frames;
3243 return(TNG_SUCCESS);
3246 /** Write tng_data->current_trajectory_frame_set to file
3247 * @param tng_data is a trajectory data container.
3248 * @param block is a general block container.
3249 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3250 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3251 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3252 * error has occured.
3254 static tng_function_status tng_frame_set_block_write
3255 (tng_trajectory_t tng_data,
3256 tng_gen_block_t block,
3257 const char hash_mode)
3262 unsigned int name_len;
3263 tng_trajectory_frame_set_t frame_set =
3264 &tng_data->current_trajectory_frame_set;
3266 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3268 return(TNG_CRITICAL);
3271 name_len = (int)strlen("TRAJECTORY FRAME SET");
3273 if(!block->name || strlen(block->name) < name_len)
3275 temp_name = realloc(block->name, name_len + 1);
3278 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3279 name_len+1, __FILE__, __LINE__);
3282 return(TNG_CRITICAL);
3284 block->name = temp_name;
3286 strcpy(block->name, "TRAJECTORY FRAME SET");
3287 block->id = TNG_TRAJECTORY_FRAME_SET;
3289 block->block_contents_size = sizeof(int64_t) * 8;
3290 block->block_contents_size += sizeof(double) * 2;
3292 if(tng_data->var_num_atoms_flag)
3294 block->block_contents_size += sizeof(int64_t) * tng_data->n_molecules;
3297 if(block->block_contents)
3299 free(block->block_contents);
3301 block->block_contents = malloc(block->block_contents_size);
3302 if(!block->block_contents)
3304 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3305 block->block_contents_size, __FILE__, __LINE__);
3306 return(TNG_CRITICAL);
3309 memcpy(block->block_contents, &frame_set->first_frame,
3310 sizeof(frame_set->first_frame));
3311 if(tng_data->output_endianness_swap_func_64)
3313 if(tng_data->output_endianness_swap_func_64(tng_data,
3314 (int64_t *)block->header_contents+offset)
3317 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3318 __FILE__, __LINE__);
3321 offset += sizeof(frame_set->first_frame);
3323 memcpy(block->block_contents+offset, &frame_set->n_frames,
3324 sizeof(frame_set->n_frames));
3325 if(tng_data->output_endianness_swap_func_64)
3327 if(tng_data->output_endianness_swap_func_64(tng_data,
3328 (int64_t *)block->header_contents+offset)
3331 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3332 __FILE__, __LINE__);
3335 offset += sizeof(frame_set->n_frames);
3337 if(tng_data->var_num_atoms_flag)
3339 for(i = 0; i < tng_data->n_molecules; i++)
3341 memcpy(block->block_contents+offset,
3342 &frame_set->molecule_cnt_list[i],
3344 if(tng_data->output_endianness_swap_func_64)
3346 if(tng_data->output_endianness_swap_func_64(tng_data,
3347 (int64_t *)block->header_contents+offset)
3350 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3351 __FILE__, __LINE__);
3354 offset += sizeof(int64_t);
3359 memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
3360 sizeof(frame_set->next_frame_set_file_pos));
3361 if(tng_data->output_endianness_swap_func_64)
3363 if(tng_data->output_endianness_swap_func_64(tng_data,
3364 (int64_t *)block->header_contents+offset)
3367 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3368 __FILE__, __LINE__);
3371 offset += sizeof(frame_set->next_frame_set_file_pos);
3373 memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
3374 sizeof(frame_set->prev_frame_set_file_pos));
3375 if(tng_data->output_endianness_swap_func_64)
3377 if(tng_data->output_endianness_swap_func_64(tng_data,
3378 (int64_t *)block->header_contents+offset)
3381 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3382 __FILE__, __LINE__);
3385 offset += sizeof(frame_set->prev_frame_set_file_pos);
3387 memcpy(block->block_contents+offset,
3388 &frame_set->medium_stride_next_frame_set_file_pos,
3389 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
3390 if(tng_data->output_endianness_swap_func_64)
3392 if(tng_data->output_endianness_swap_func_64(tng_data,
3393 (int64_t *)block->header_contents+offset)
3396 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3397 __FILE__, __LINE__);
3400 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
3402 memcpy(block->block_contents+offset,
3403 &frame_set->medium_stride_prev_frame_set_file_pos,
3404 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
3405 if(tng_data->output_endianness_swap_func_64)
3407 if(tng_data->output_endianness_swap_func_64(tng_data,
3408 (int64_t *)block->header_contents+offset)
3411 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3412 __FILE__, __LINE__);
3415 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
3417 memcpy(block->block_contents+offset,
3418 &frame_set->long_stride_next_frame_set_file_pos,
3419 sizeof(frame_set->long_stride_next_frame_set_file_pos));
3420 if(tng_data->output_endianness_swap_func_64)
3422 if(tng_data->output_endianness_swap_func_64(tng_data,
3423 (int64_t *)block->header_contents+offset)
3426 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3427 __FILE__, __LINE__);
3430 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
3432 memcpy(block->block_contents+offset,
3433 &frame_set->long_stride_prev_frame_set_file_pos,
3434 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
3435 if(tng_data->output_endianness_swap_func_64)
3437 if(tng_data->output_endianness_swap_func_64(tng_data,
3438 (int64_t *)block->header_contents+offset)
3441 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3442 __FILE__, __LINE__);
3445 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
3447 memcpy(block->block_contents+offset,
3448 &frame_set->first_frame_time,
3449 sizeof(frame_set->first_frame_time));
3450 if(tng_data->output_endianness_swap_func_64)
3452 if(tng_data->output_endianness_swap_func_64(tng_data,
3453 (int64_t *)block->header_contents+offset)
3456 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3457 __FILE__, __LINE__);
3460 offset += sizeof(frame_set->first_frame_time);
3462 memcpy(block->block_contents+offset,
3463 &tng_data->time_per_frame,
3464 sizeof(tng_data->time_per_frame));
3465 if(tng_data->output_endianness_swap_func_64)
3467 if(tng_data->output_endianness_swap_func_64(tng_data,
3468 (int64_t *)block->header_contents+offset)
3471 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3472 __FILE__, __LINE__);
3476 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3478 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3479 tng_data->output_file_path, __FILE__, __LINE__);
3480 return(TNG_CRITICAL);
3483 if(fwrite(block->block_contents, block->block_contents_size, 1,
3484 tng_data->output_file) != 1)
3486 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
3487 return(TNG_CRITICAL);
3490 return(TNG_SUCCESS);
3494 /** Read an atom mappings block (translating between real atom indexes and how
3495 * the atom info is written in this frame set).
3496 * @param tng_data is a trajectory data container.
3497 * @param block is a general block container.
3498 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3499 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3500 * compared to the md5 hash of the read contents to ensure valid data.
3501 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3502 * error has occured.
3504 static tng_function_status tng_trajectory_mapping_block_read
3505 (tng_trajectory_t tng_data,
3506 tng_gen_block_t block,
3507 const char hash_mode)
3512 tng_trajectory_frame_set_t frame_set =
3513 &tng_data->current_trajectory_frame_set;
3515 tng_particle_mapping_t mapping, mappings;
3517 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3519 return(TNG_CRITICAL);
3522 if(block->block_contents)
3524 free(block->block_contents);
3527 block->block_contents = malloc(block->block_contents_size);
3528 if(!block->block_contents)
3530 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3531 block->block_contents_size, __FILE__, __LINE__);
3532 return(TNG_CRITICAL);
3535 /* Read the whole block into block_contents to be able to write it to disk
3536 * even if it cannot be interpreted. */
3537 if(fread(block->block_contents, block->block_contents_size, 1,
3538 tng_data->input_file) == 0)
3540 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3541 return(TNG_CRITICAL);
3544 /* FIXME: Does not check if the size of the contents matches the expected
3545 * size or if the contents can be read. */
3547 if(hash_mode == TNG_USE_HASH)
3549 tng_md5_hash_match_verify(block, &same_hash);
3550 if(same_hash != TNG_TRUE)
3552 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
3554 __FILE__, __LINE__);
3555 /* return(TNG_FAILURE); */
3559 frame_set->n_mapping_blocks++;
3560 mappings = realloc(frame_set->mappings,
3561 sizeof(struct tng_particle_mapping) *
3562 frame_set->n_mapping_blocks);
3565 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3566 block->block_contents_size, __FILE__, __LINE__);
3567 free(frame_set->mappings);
3568 frame_set->mappings = 0;
3569 return(TNG_CRITICAL);
3571 frame_set->mappings = mappings;
3572 mapping = &mappings[frame_set->n_mapping_blocks - 1];
3575 memcpy(&mapping->num_first_particle, block->block_contents+offset,
3576 sizeof(mapping->num_first_particle));
3577 if(tng_data->input_endianness_swap_func_64)
3579 if(tng_data->input_endianness_swap_func_64(tng_data,
3580 &mapping->num_first_particle)
3583 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3584 __FILE__, __LINE__);
3587 offset += sizeof(mapping->num_first_particle);
3589 memcpy(&mapping->n_particles, block->block_contents+offset,
3590 sizeof(mapping->n_particles));
3591 if(tng_data->input_endianness_swap_func_64)
3593 if(tng_data->input_endianness_swap_func_64(tng_data,
3594 &mapping->n_particles)
3597 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3598 __FILE__, __LINE__);
3601 offset += sizeof(mapping->n_particles);
3603 mapping->real_particle_numbers = malloc(mapping->n_particles *
3605 if(!mapping->real_particle_numbers)
3607 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3608 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
3609 return(TNG_CRITICAL);
3612 /* If the byte order needs to be swapped the data must be read one value at
3613 * a time and swapped */
3614 if(tng_data->input_endianness_swap_func_64)
3616 for(i = 0; i < mapping->n_particles; i++)
3618 memcpy(&mapping->real_particle_numbers[i],
3619 block->block_contents + offset,
3621 if(tng_data->input_endianness_swap_func_64(tng_data,
3622 &mapping->real_particle_numbers[i])
3625 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3626 __FILE__, __LINE__);
3628 offset += sizeof(int64_t);
3631 /* Otherwise the data can be read all at once */
3634 memcpy(mapping->real_particle_numbers, block->block_contents + offset,
3635 mapping->n_particles * sizeof(int64_t));
3639 return(TNG_SUCCESS);
3642 /** Write the atom mappings of the current trajectory frame set
3643 * @param tng_data is a trajectory data container.
3644 * @param block is a general block container.
3645 * @param mapping_block_nr is the index of the mapping block to write.
3646 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3647 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3648 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
3649 * has occurred or TNG_CRITICAL (2) if a major error has occured.
3651 static tng_function_status tng_trajectory_mapping_block_write
3652 (tng_trajectory_t tng_data,
3653 tng_gen_block_t block,
3654 int mapping_block_nr,
3655 const char hash_mode)
3659 unsigned int name_len;
3660 tng_particle_mapping_t mapping =
3661 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
3663 if(mapping_block_nr >=
3664 tng_data->current_trajectory_frame_set.n_mapping_blocks)
3666 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
3667 __FILE__, __LINE__);
3668 return(TNG_FAILURE);
3671 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3673 return(TNG_CRITICAL);
3676 name_len = (int)strlen("PARTICLE MAPPING");
3678 if(!block->name || strlen(block->name) < name_len)
3680 temp_name = realloc(block->name, name_len + 1);
3683 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3684 name_len+1, __FILE__, __LINE__);
3687 return(TNG_CRITICAL);
3689 block->name = temp_name;
3691 strcpy(block->name, "PARTICLE MAPPING");
3692 block->id = TNG_PARTICLE_MAPPING;
3694 block->block_contents_size = sizeof(int64_t) * (2 + mapping->n_particles);
3696 if(block->block_contents)
3698 free(block->block_contents);
3700 block->block_contents = malloc(block->block_contents_size);
3701 if(!block->block_contents)
3703 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3704 block->block_contents_size, __FILE__, __LINE__);
3705 return(TNG_CRITICAL);
3708 memcpy(block->block_contents, &mapping->num_first_particle,
3709 sizeof(mapping->num_first_particle));
3710 if(tng_data->output_endianness_swap_func_64)
3712 if(tng_data->output_endianness_swap_func_64(tng_data,
3713 (int64_t *)block->header_contents+offset)
3716 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3717 __FILE__, __LINE__);
3720 offset += sizeof(mapping->num_first_particle);
3722 memcpy(block->block_contents+offset, &mapping->n_particles,
3723 sizeof(mapping->n_particles));
3724 if(tng_data->output_endianness_swap_func_64)
3726 if(tng_data->output_endianness_swap_func_64(tng_data,
3727 (int64_t *)block->header_contents+offset)
3730 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3731 __FILE__, __LINE__);
3734 offset += sizeof(mapping->n_particles);
3736 if(tng_data->output_endianness_swap_func_64)
3738 for(i = 0; i < mapping->n_particles; i++)
3740 memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
3742 if(tng_data->output_endianness_swap_func_64(tng_data,
3743 (int64_t *)block->header_contents+offset)
3746 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3747 __FILE__, __LINE__);
3749 offset += sizeof(int64_t);
3754 memcpy(block->block_contents+offset, mapping->real_particle_numbers,
3755 mapping->n_particles * sizeof(int64_t));
3759 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3761 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3762 tng_data->output_file_path, __FILE__, __LINE__);
3763 return(TNG_CRITICAL);
3766 if(fwrite(block->block_contents, block->block_contents_size, 1,
3767 tng_data->output_file) != 1)
3769 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
3770 return(TNG_CRITICAL);
3773 return(TNG_SUCCESS);
3776 /** Prepare a block for storing particle data
3777 * @param tng_data is a trajectory data container.
3778 * @param block_type_flag specifies if this is a trajectory block or a
3779 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
3780 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3781 * error has occured.
3783 static tng_function_status tng_particle_data_block_create
3784 (tng_trajectory_t tng_data,
3785 const char block_type_flag)
3787 tng_trajectory_frame_set_t frame_set =
3788 &tng_data->current_trajectory_frame_set;
3790 tng_particle_data_t data;
3792 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
3794 frame_set->n_particle_data_blocks++;
3795 data = realloc(frame_set->tr_particle_data,
3796 sizeof(struct tng_particle_data) *
3797 frame_set->n_particle_data_blocks);
3800 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
3801 sizeof(struct tng_particle_data) *
3802 frame_set->n_particle_data_blocks,
3803 __FILE__, __LINE__);
3804 free(frame_set->tr_particle_data);
3805 frame_set->tr_particle_data = 0;
3806 return(TNG_CRITICAL);
3808 frame_set->tr_particle_data = data;
3812 tng_data->n_particle_data_blocks++;
3813 data = realloc(tng_data->non_tr_particle_data,
3814 sizeof(struct tng_particle_data) *
3815 tng_data->n_particle_data_blocks);
3818 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
3819 sizeof(struct tng_particle_data) *
3820 tng_data->n_particle_data_blocks,
3821 __FILE__, __LINE__);
3822 free(tng_data->non_tr_particle_data);
3823 tng_data->non_tr_particle_data = 0;
3824 return(TNG_CRITICAL);
3826 tng_data->non_tr_particle_data = data;
3829 return(TNG_SUCCESS);
3832 static tng_function_status tng_compress(tng_trajectory_t tng_data,
3833 tng_gen_block_t block,
3834 const int64_t n_frames,
3835 const int64_t n_particles,
3843 int64_t algo_find_n_frames;
3844 unsigned long offset;
3848 if(block->id != TNG_TRAJ_POSITIONS &&
3849 block->id != TNG_TRAJ_VELOCITIES)
3851 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
3852 "TNG method. %s: %d\n", __FILE__, __LINE__);
3853 return(TNG_FAILURE);
3855 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
3857 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
3858 return(TNG_FAILURE);
3861 if(n_frames <= 0 || n_particles <= 0)
3863 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
3864 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
3865 return(TNG_FAILURE);
3868 f_precision = 1/tng_data->compression_precision;
3869 d_precision = 1/tng_data->compression_precision;
3871 if(block->id == TNG_TRAJ_POSITIONS)
3873 /* If there is only one frame in this frame set and there might be more
3874 * do not store the algorithm as the compression algorithm, but find
3875 * the best one without storing it */
3876 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
3878 nalgo = tng_compress_nalgo();
3879 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
3880 if(type == TNG_FLOAT_DATA)
3882 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
3891 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
3898 else if(!tng_data->compress_algo_pos)
3902 algo_find_n_frames = 5;
3906 algo_find_n_frames = n_frames;
3909 nalgo = tng_compress_nalgo();
3910 tng_data->compress_algo_pos=malloc(nalgo *
3911 sizeof *tng_data->compress_algo_pos);
3912 if(type == TNG_FLOAT_DATA)
3914 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
3915 (int)algo_find_n_frames,
3921 if(algo_find_n_frames < n_frames)
3923 dest = tng_compress_pos_float(start_pos, (int)n_particles,
3926 0, tng_data->compress_algo_pos,
3932 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
3933 (int)algo_find_n_frames,
3939 if(algo_find_n_frames < n_frames)
3941 dest = tng_compress_pos(start_pos, (int)n_particles,
3944 tng_data->compress_algo_pos,
3951 if(type == TNG_FLOAT_DATA)
3953 dest = tng_compress_pos_float(start_pos, (int)n_particles,
3956 tng_data->compress_algo_pos, &new_len);
3960 dest = tng_compress_pos(start_pos, (int)n_particles,
3963 tng_data->compress_algo_pos,
3968 else if(block->id == TNG_TRAJ_VELOCITIES)
3970 /* If there is only one frame in this frame set and there might be more
3971 * do not store the algorithm as the compression algorithm, but find
3972 * the best one without storing it */
3973 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
3975 nalgo = tng_compress_nalgo();
3976 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
3977 if(type == TNG_FLOAT_DATA)
3979 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
3988 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
3995 else if(!tng_data->compress_algo_vel)
3999 algo_find_n_frames = 5;
4003 algo_find_n_frames = n_frames;
4006 nalgo = tng_compress_nalgo();
4007 tng_data->compress_algo_vel=malloc(nalgo *
4008 sizeof *tng_data->compress_algo_vel);
4010 if(type == TNG_FLOAT_DATA)
4012 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4013 (int)algo_find_n_frames,
4018 if(algo_find_n_frames < n_frames)
4020 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4023 0, tng_data->compress_algo_vel,
4029 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4030 (int)algo_find_n_frames,
4035 if(algo_find_n_frames < n_frames)
4037 dest = tng_compress_vel(start_pos, (int)n_particles,
4040 0, tng_data->compress_algo_vel,
4047 if(type == TNG_FLOAT_DATA)
4049 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4058 dest = tng_compress_vel(start_pos, (int)n_particles,
4069 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4070 return(TNG_FAILURE);
4073 offset = (unsigned long)((char *)start_pos - block->block_contents);
4080 block->block_contents_size = new_len + offset;
4082 temp = realloc(block->block_contents, block->block_contents_size);
4085 free(block->block_contents);
4086 block->block_contents = 0;
4087 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4088 block->block_contents_size, __FILE__, __LINE__);
4089 return(TNG_CRITICAL);
4091 block->block_contents = temp;
4094 memcpy(temp + offset, dest, new_len);
4099 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
4100 return(TNG_FAILURE);
4103 return(TNG_SUCCESS);
4106 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
4107 tng_gen_block_t block,
4110 const unsigned long uncompressed_len)
4115 unsigned long offset;
4119 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
4121 if(block->id != TNG_TRAJ_POSITIONS &&
4122 block->id != TNG_TRAJ_VELOCITIES)
4124 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
4126 return(TNG_FAILURE);
4128 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4130 fprintf(stderr, "TNG library: Data type not supported.\n");
4131 return(TNG_FAILURE);
4134 if(type == TNG_FLOAT_DATA)
4136 f_dest = malloc(uncompressed_len);
4139 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4140 uncompressed_len, __FILE__, __LINE__);
4141 return(TNG_CRITICAL);
4143 result = tng_compress_uncompress_float(start_pos, f_dest);
4147 d_dest = malloc(uncompressed_len);
4150 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4151 uncompressed_len, __FILE__, __LINE__);
4152 return(TNG_CRITICAL);
4154 result = tng_compress_uncompress(start_pos, d_dest);
4159 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
4160 return(TNG_FAILURE);
4163 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
4165 block->block_contents_size = (int64_t)(uncompressed_len + offset);
4167 temp = realloc(block->block_contents, uncompressed_len + offset);
4170 free(block->block_contents);
4171 block->block_contents = 0;
4180 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4181 block->block_contents_size, __FILE__, __LINE__);
4182 return(TNG_CRITICAL);
4185 if(type == TNG_FLOAT_DATA)
4187 memcpy(temp + offset, f_dest, uncompressed_len);
4191 memcpy(temp + offset, d_dest, uncompressed_len);
4194 block->block_contents = temp;
4204 return(TNG_SUCCESS);
4208 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
4209 tng_gen_block_t block,
4210 void *start_pos, const int len)
4214 unsigned long max_len, stat, offset;
4217 max_len = compressBound(len);
4218 dest = malloc(max_len);
4220 stat = compress(dest, &max_len, start_pos, len);
4221 if(stat != (unsigned long)Z_OK)
4224 if(stat == (unsigned long)Z_MEM_ERROR)
4226 fprintf(stderr, "TNG library: Not enough memory. ");
4228 else if(stat == (unsigned long)Z_BUF_ERROR)
4230 fprintf(stderr, "TNG library: Destination buffer too small. ");
4232 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
4233 return(TNG_FAILURE);
4236 offset = (char *)start_pos - block->block_contents;
4238 block->block_contents_size = max_len + offset;
4240 temp = realloc(block->block_contents, block->block_contents_size);
4243 free(block->block_contents);
4245 block->block_contents = 0;
4246 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4247 block->block_contents_size, __FILE__, __LINE__);
4248 return(TNG_CRITICAL);
4251 block->block_contents = temp;
4253 memcpy(temp + offset, dest, max_len);
4257 return(TNG_SUCCESS);
4260 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
4261 tng_gen_block_t block,
4263 unsigned long uncompressed_len)
4271 offset = (char *)start_pos - (char *)block->block_contents;
4273 dest = malloc(uncompressed_len);
4275 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
4276 block->block_contents_size - offset);
4281 if(stat == (unsigned long)Z_MEM_ERROR)
4283 fprintf(stderr, "TNG library: Not enough memory. ");
4285 else if(stat == (unsigned long)Z_BUF_ERROR)
4287 fprintf(stderr, "TNG library: Destination buffer too small. ");
4289 else if(stat == (unsigned long)Z_DATA_ERROR)
4291 fprintf(stderr, "TNG library: Data corrupt. ");
4293 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
4295 return(TNG_FAILURE);
4299 block->block_contents_size = uncompressed_len + offset;
4301 temp = realloc(block->block_contents, uncompressed_len + offset);
4304 free(block->block_contents);
4305 block->block_contents = 0;
4307 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4308 block->block_contents_size, __FILE__, __LINE__);
4309 return(TNG_CRITICAL);
4312 memcpy(temp + offset, dest, uncompressed_len);
4314 block->block_contents = temp;
4317 return(TNG_SUCCESS);
4321 /** Allocate memory for storing particle data.
4322 * The allocated block will be refered to by data->values.
4323 * @param tng_data is a trajectory data container.
4324 * @param data is the data struct, which will contain the allocated memory in
4326 * @param n_frames is the number of frames of data to store.
4327 * @param n_particles is the number of particles with data.
4328 * @param n_values_per_frame is the number of data values per particle and
4330 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4331 * error has occured.
4333 static tng_function_status tng_allocate_particle_data_mem
4334 (tng_trajectory_t tng_data,
4335 tng_particle_data_t data,
4337 int64_t stride_length,
4338 const int64_t n_particles,
4339 const int64_t n_values_per_frame)
4342 int64_t i, j, k, size, frame_alloc;
4345 if(n_particles == 0 || n_values_per_frame == 0)
4347 return(TNG_FAILURE);
4350 if(data->strings && data->datatype == TNG_CHAR_DATA)
4352 for(i = data->n_frames; i--;)
4354 for(j = n_particles; j--;)
4356 for(k = data->n_values_per_frame; k--;)
4358 if(data->strings[i][j][k])
4360 free(data->strings[i][j][k]);
4363 free(data->strings[i][j]);
4365 free(data->strings[i]);
4367 free(data->strings);
4369 data->n_frames = n_frames;
4370 n_frames = tng_max_i64(1, n_frames);
4371 data->stride_length = tng_max_i64(1, stride_length);
4372 data->n_values_per_frame = n_values_per_frame;
4373 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
4375 if(data->datatype == TNG_CHAR_DATA)
4377 data->strings = malloc(sizeof(char ***) * frame_alloc);
4378 for(i = frame_alloc; i-- ;)
4380 data->strings[i] = malloc(sizeof(char **) *
4382 if(!data->strings[i])
4384 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4385 sizeof(union data_values *) * n_particles,
4386 __FILE__, __LINE__);
4387 return(TNG_CRITICAL);
4389 for(j = n_particles; j--;)
4391 data->strings[i][j] = malloc(sizeof(char *) *
4392 n_values_per_frame);
4393 if(!data->strings[i][j])
4395 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4396 sizeof(union data_values) * n_values_per_frame,
4397 __FILE__, __LINE__);
4398 return(TNG_CRITICAL);
4400 for(k = n_values_per_frame; k--;)
4402 data->strings[i][j][k] = 0;
4409 switch(data->datatype)
4412 size = sizeof(int64_t);
4414 case TNG_FLOAT_DATA:
4415 size = sizeof(float);
4417 case TNG_DOUBLE_DATA:
4419 size = sizeof(double);
4422 values = realloc(data->values,
4423 size * frame_alloc *
4424 n_particles * n_values_per_frame);
4427 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4428 size * frame_alloc *
4429 n_particles * n_values_per_frame,
4430 __FILE__, __LINE__);
4433 return(TNG_CRITICAL);
4435 data->values = values;
4437 return(TNG_SUCCESS);
4440 static tng_function_status tng_particle_data_find
4441 (tng_trajectory_t tng_data,
4443 tng_particle_data_t *data)
4445 int64_t block_index, i;
4446 tng_trajectory_frame_set_t frame_set = &tng_data->
4447 current_trajectory_frame_set;
4448 char block_type_flag;
4450 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4451 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4453 block_type_flag = TNG_TRAJECTORY_BLOCK;
4457 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4461 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4463 for(i = frame_set->n_particle_data_blocks; i-- ;)
4465 *data = &frame_set->tr_particle_data[i];
4466 if((*data)->block_id == id)
4475 for(i = tng_data->n_particle_data_blocks; i-- ;)
4477 *data = &tng_data->non_tr_particle_data[i];
4478 if((*data)->block_id == id)
4485 if(block_index == -1)
4487 return(TNG_FAILURE);
4489 return(TNG_SUCCESS);
4492 static tng_function_status tng_data_find
4493 (tng_trajectory_t tng_data,
4495 tng_non_particle_data_t *data)
4497 int64_t block_index, i;
4498 tng_trajectory_frame_set_t frame_set = &tng_data->
4499 current_trajectory_frame_set;
4500 char block_type_flag;
4502 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4503 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4505 block_type_flag = TNG_TRAJECTORY_BLOCK;
4509 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4513 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4515 for(i = frame_set->n_data_blocks; i-- ;)
4517 *data = &frame_set->tr_data[i];
4518 if((*data)->block_id == id)
4524 if(block_index == -1)
4526 for(i = tng_data->n_data_blocks; i-- ;)
4528 *data = &tng_data->non_tr_data[i];
4529 if((*data)->block_id == id)
4539 for(i = tng_data->n_data_blocks; i-- ;)
4541 *data = &tng_data->non_tr_data[i];
4542 if((*data)->block_id == id)
4549 if(block_index == -1)
4551 return(TNG_FAILURE);
4553 return(TNG_SUCCESS);
4556 /** Read the values of a particle data block
4557 * @param tng_data is a trajectory data container.
4558 * @param block is the block to store the data (should already contain
4559 * the block headers and the block contents).
4560 * @param offset is the reading offset to point at the place where the actual
4561 * values are stored, starting from the beginning of the block_contents. The
4562 * offset is changed during the reading.
4563 * @param datatype is the type of data of the data block (char, int, float or
4565 * @param num_first_particle is the number of the first particle in the data
4566 * block. This should be the same as in the corresponding particle mapping
4568 * @param n_particles is the number of particles in the data block. This should
4569 * be the same as in the corresponding particle mapping block.
4570 * @param first_frame_with_data is the frame number of the first frame with data
4571 * in this data block.
4572 * @param stride_length is the number of frames between each data entry.
4573 * @param n_frames is the number of frames in this data block.
4574 * @param n_values is the number of values per particle and frame stored in this
4576 * @param codec_id is the ID of the codec to compress the data.
4577 * @param multiplier is the multiplication factor applied to each data value
4578 * before compression. This factor is applied since some compression algorithms
4579 * work only on integers.
4580 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4581 * error has occured.
4583 static tng_function_status tng_particle_data_read
4584 (tng_trajectory_t tng_data,
4585 tng_gen_block_t block,
4587 const char datatype,
4588 const int64_t num_first_particle,
4589 const int64_t n_particles,
4590 const int64_t first_frame_with_data,
4591 const int64_t stride_length,
4593 const int64_t n_values,
4594 const int64_t codec_id,
4595 const double multiplier)
4597 int64_t i, j, k, tot_n_particles, n_frames_div;
4599 unsigned long data_size;
4600 char ***first_dim_values, **second_dim_values;
4601 tng_particle_data_t data;
4602 tng_trajectory_frame_set_t frame_set =
4603 &tng_data->current_trajectory_frame_set;
4604 char block_type_flag;
4606 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
4614 size = sizeof(int64_t);
4616 case TNG_FLOAT_DATA:
4617 size = sizeof(float);
4619 case TNG_DOUBLE_DATA:
4621 size = sizeof(double);
4624 /* If the block does not exist, create it */
4625 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
4627 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
4629 block_type_flag = TNG_TRAJECTORY_BLOCK;
4633 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4636 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
4639 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
4640 __FILE__, __LINE__);
4641 return(TNG_CRITICAL);
4643 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4645 data = &frame_set->tr_particle_data[frame_set->
4646 n_particle_data_blocks - 1];
4650 data = &tng_data->non_tr_particle_data[tng_data->
4651 n_particle_data_blocks - 1];
4653 data->block_id = block->id;
4655 data->block_name = malloc(strlen(block->name) + 1);
4656 if(!data->block_name)
4658 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4659 (int)strlen(block->name)+1, __FILE__, __LINE__);
4660 return(TNG_CRITICAL);
4662 strcpy(data->block_name, block->name);
4664 data->datatype = datatype;
4667 /* FIXME: Memory leak from strings. */
4670 data->codec_id = codec_id;
4671 data->compression_multiplier = multiplier;
4672 data->last_retrieved_frame = -1;
4675 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
4676 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
4677 tng_data->var_num_atoms_flag)
4679 tot_n_particles = frame_set->n_particles;
4683 tot_n_particles = tng_data->n_particles;
4686 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
4688 if(codec_id != TNG_UNCOMPRESSED)
4690 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
4693 case TNG_XTC_COMPRESSION:
4694 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
4696 case TNG_TNG_COMPRESSION:
4697 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
4698 if(tng_uncompress(tng_data, block, datatype,
4699 block->block_contents + *offset,
4700 data_size) != TNG_SUCCESS)
4702 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
4703 __FILE__, __LINE__);
4704 return(TNG_CRITICAL);
4706 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
4709 case TNG_GZIP_COMPRESSION:
4710 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
4711 if(tng_gzip_uncompress(tng_data, block,
4712 block->block_contents + *offset,
4713 data_size) != TNG_SUCCESS)
4715 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
4717 return(TNG_CRITICAL);
4719 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
4724 /* Allocate memory */
4725 if(!data->values || data->n_frames != n_frames ||
4726 data->n_values_per_frame != n_values)
4728 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
4730 tot_n_particles, n_values) !=
4733 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
4734 __FILE__, __LINE__);
4735 return(TNG_CRITICAL);
4739 data->first_frame_with_data = first_frame_with_data;
4741 if(datatype == TNG_CHAR_DATA)
4743 for(i = 0; i < n_frames_div; i++)
4745 first_dim_values = data->strings[i];
4746 for(j = num_first_particle; j < num_first_particle + n_particles;
4749 second_dim_values = first_dim_values[j];
4750 for(k = 0; k < n_values; k++)
4752 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
4754 if(second_dim_values[k])
4756 free(second_dim_values[k]);
4758 second_dim_values[k] = malloc(len);
4759 if(!second_dim_values[k])
4761 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4762 len, __FILE__, __LINE__);
4763 return(TNG_CRITICAL);
4765 strncpy(second_dim_values[k],
4766 block->block_contents+*offset, len);
4774 memcpy((char *)data->values + n_frames_div * size * n_values *
4776 block->block_contents + *offset,
4777 block->block_contents_size - *offset);
4780 case TNG_FLOAT_DATA:
4781 if(tng_data->input_endianness_swap_func_32)
4783 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
4785 if(tng_data->input_endianness_swap_func_32(tng_data,
4786 (int32_t *)((char *)data->values + i))
4789 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4790 __FILE__, __LINE__);
4796 case TNG_DOUBLE_DATA:
4797 if(tng_data->input_endianness_swap_func_64)
4799 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
4801 if(tng_data->input_endianness_swap_func_64(tng_data,
4802 (int64_t *)((char *)data->values + i))
4805 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4806 __FILE__, __LINE__);
4815 return(TNG_SUCCESS);
4818 /** Write a particle data block
4819 * @param tng_data is a trajectory data container.
4820 * @param block is the block to store the data (should already contain
4821 * the block headers and the block contents).
4822 * @param block_index is the index number of the data block in the frame set.
4823 * @param mapping is the particle mapping that is relevant for the data block.
4824 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4825 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4826 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4827 * error has occured.
4829 static tng_function_status tng_particle_data_block_write
4830 (tng_trajectory_t tng_data,
4831 tng_gen_block_t block,
4832 const int64_t block_index,
4833 const tng_particle_mapping_t mapping,
4834 const char hash_mode)
4836 int64_t n_particles, num_first_particle, n_frames, stride_length;
4837 int64_t frame_step, data_start_pos;
4840 size_t len, offset = 0;
4841 char dependency, temp, *temp_name;
4843 char ***first_dim_values, **second_dim_values;
4844 tng_trajectory_frame_set_t frame_set;
4845 tng_function_status stat;
4847 tng_particle_data_t data;
4848 char block_type_flag;
4850 frame_set = &tng_data->current_trajectory_frame_set;
4852 /* If we have already started writing frame sets it is too late to write
4853 * non-trajectory data blocks */
4854 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
4856 block_type_flag = TNG_TRAJECTORY_BLOCK;
4860 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4863 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4865 return(TNG_CRITICAL);
4868 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4870 data = &frame_set->tr_particle_data[block_index];
4872 /* If this data block has not had any data added in this frame set
4873 * do not write it. */
4874 if(data->first_frame_with_data < frame_set->first_frame)
4876 return(TNG_SUCCESS);
4879 stride_length = tng_max_i64(1, data->stride_length);
4883 data = &tng_data->non_tr_particle_data[block_index];
4887 switch(data->datatype)
4893 size = sizeof(int64_t);
4895 case TNG_FLOAT_DATA:
4896 size = sizeof(float);
4898 case TNG_DOUBLE_DATA:
4900 size = sizeof(double);
4903 len = strlen(data->block_name) + 1;
4905 if(!block->name || strlen(block->name) < len)
4907 temp_name = realloc(block->name, len);
4910 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
4911 __FILE__, __LINE__);
4914 return(TNG_CRITICAL);
4916 block->name = temp_name;
4918 strncpy(block->name, data->block_name, len);
4919 block->id = data->block_id;
4921 /* If writing frame independent data data->n_frames is 0, but n_frames
4922 is used for the loop writing the data (and reserving memory) and needs
4924 n_frames = tng_max_i64(1, data->n_frames);
4926 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4928 /* If the frame set is finished before writing the full number of frames
4929 make sure the data block is not longer than the frame set. */
4930 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
4932 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
4935 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
4936 n_frames / stride_length;
4938 /* TNG compression will use compression precision to get integers from
4939 * floating point data. The compression multiplier stores that information
4940 * to be able to return the precision of the compressed data. */
4941 if(data->codec_id == TNG_TNG_COMPRESSION)
4943 data->compression_multiplier = tng_data->compression_precision;
4945 /* Uncompressed data blocks do not use compression multipliers at all.
4946 * GZip compression does not need it either. */
4947 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
4949 data->compression_multiplier = 1.0;
4952 if(mapping && mapping->n_particles != 0)
4954 n_particles = mapping->n_particles;
4955 num_first_particle = mapping->num_first_particle;
4959 num_first_particle = 0;
4960 if(tng_data->var_num_atoms_flag)
4962 n_particles = frame_set->n_particles;
4966 n_particles = tng_data->n_particles;
4970 block->block_contents_size = sizeof(char) * 2 +
4971 sizeof(data->n_values_per_frame) +
4972 sizeof(data->codec_id) +
4973 sizeof(num_first_particle) +
4974 sizeof(n_particles);
4976 if(stride_length > 1)
4978 block->block_contents_size += sizeof(data->first_frame_with_data) +
4979 sizeof(data->stride_length);
4982 if(data->codec_id != TNG_UNCOMPRESSED)
4984 block->block_contents_size += sizeof(data->compression_multiplier);
4987 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
4989 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
4993 dependency = TNG_PARTICLE_DEPENDENT;
4995 if(dependency & TNG_FRAME_DEPENDENT)
4997 block->block_contents_size += sizeof(char);
5000 data_start_pos = block->block_contents_size;
5002 if(data->datatype == TNG_CHAR_DATA)
5004 for(i = n_frames; i--;)
5006 first_dim_values = data->strings[i];
5007 for(j = num_first_particle; j < num_first_particle + n_particles;
5010 second_dim_values = first_dim_values[j];
5011 for(k = data->n_values_per_frame; k--;)
5013 block->block_contents_size +=
5014 strlen(second_dim_values[k]) + 1;
5021 block->block_contents_size += size * frame_step *
5022 n_particles * data->n_values_per_frame;
5025 if(block->block_contents)
5027 free(block->block_contents);
5029 block->block_contents = malloc(block->block_contents_size);
5030 if(!block->block_contents)
5032 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5033 block->block_contents_size, __FILE__, __LINE__);
5034 return(TNG_CRITICAL);
5038 memcpy(block->block_contents, &data->datatype, sizeof(char));
5039 offset += sizeof(char);
5041 memcpy(block->block_contents+offset, &dependency, sizeof(char));
5042 offset += sizeof(char);
5044 if(dependency & TNG_FRAME_DEPENDENT)
5046 if(stride_length > 1)
5054 memcpy(block->block_contents+offset, &temp, sizeof(char));
5055 offset += sizeof(char);
5058 memcpy(block->block_contents+offset, &data->n_values_per_frame,
5059 sizeof(data->n_values_per_frame));
5060 if(tng_data->output_endianness_swap_func_64)
5062 if(tng_data->output_endianness_swap_func_64(tng_data,
5063 (int64_t *)block->header_contents+offset)
5066 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5067 __FILE__, __LINE__);
5070 offset += sizeof(data->n_values_per_frame);
5072 memcpy(block->block_contents+offset, &data->codec_id,
5073 sizeof(data->codec_id));
5074 if(tng_data->output_endianness_swap_func_64)
5076 if(tng_data->output_endianness_swap_func_64(tng_data,
5077 (int64_t *)block->header_contents+offset)
5080 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5081 __FILE__, __LINE__);
5084 offset += sizeof(data->codec_id);
5086 if(data->codec_id != TNG_UNCOMPRESSED)
5088 memcpy(block->block_contents+offset, &data->compression_multiplier,
5089 sizeof(data->compression_multiplier));
5090 if(tng_data->output_endianness_swap_func_64)
5092 if(tng_data->output_endianness_swap_func_64(tng_data,
5093 (int64_t *)block->header_contents+offset)
5096 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5097 __FILE__, __LINE__);
5100 offset += sizeof(data->compression_multiplier);
5103 if(data->n_frames > 0 && stride_length > 1)
5105 /* FIXME: first_frame_with_data is not reliably set */
5106 if(data->first_frame_with_data == 0)
5108 data->first_frame_with_data = frame_set->first_frame;
5110 memcpy(block->block_contents+offset, &data->first_frame_with_data,
5111 sizeof(data->first_frame_with_data));
5112 if(tng_data->output_endianness_swap_func_64)
5114 if(tng_data->output_endianness_swap_func_64(tng_data,
5115 (int64_t *)block->header_contents+offset)
5118 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5119 __FILE__, __LINE__);
5122 offset += sizeof(data->first_frame_with_data);
5124 memcpy(block->block_contents+offset, &stride_length,
5125 sizeof(stride_length));
5126 if(tng_data->output_endianness_swap_func_64)
5128 if(tng_data->output_endianness_swap_func_64(tng_data,
5129 (int64_t *)block->header_contents+offset)
5132 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5133 __FILE__, __LINE__);
5136 offset += sizeof(stride_length);
5140 memcpy(block->block_contents+offset, &num_first_particle,
5141 sizeof(num_first_particle));
5142 if(tng_data->output_endianness_swap_func_64)
5144 if(tng_data->output_endianness_swap_func_64(tng_data,
5145 (int64_t *)block->header_contents+offset)
5148 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5149 __FILE__, __LINE__);
5152 offset += sizeof(num_first_particle);
5154 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
5155 if(tng_data->output_endianness_swap_func_64)
5157 if(tng_data->output_endianness_swap_func_64(tng_data,
5158 (int64_t *)block->header_contents+offset)
5161 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5162 __FILE__, __LINE__);
5165 offset += sizeof(n_particles);
5167 if(data->datatype == TNG_CHAR_DATA)
5171 for(i = 0; i < frame_step; i++)
5173 first_dim_values = data->strings[i];
5174 for(j = num_first_particle; j < num_first_particle + n_particles;
5177 second_dim_values = first_dim_values[j];
5178 for(k = 0; k < data->n_values_per_frame; k++)
5180 len = (unsigned int)strlen(second_dim_values[k]) + 1;
5181 strncpy(block->block_contents+offset,
5182 second_dim_values[k], len);
5189 else if(data->values)
5191 memcpy(block->block_contents + offset, data->values,
5192 block->block_contents_size - offset);
5194 switch(data->datatype)
5196 case TNG_FLOAT_DATA:
5197 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
5198 data->codec_id == TNG_TNG_COMPRESSION)
5200 if(tng_data->input_endianness_swap_func_32)
5202 for(i = offset; i < block->block_contents_size; i+=size)
5204 if(tng_data->input_endianness_swap_func_32(tng_data,
5205 (int32_t *)(block->block_contents + i))
5208 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5209 __FILE__, __LINE__);
5216 multiplier = data->compression_multiplier;
5217 if(fabs(multiplier - 1.0) > 0.00001 ||
5218 tng_data->input_endianness_swap_func_32)
5220 for(i = offset; i < block->block_contents_size; i+=size)
5222 *(float *)(block->block_contents + i) *= (float)multiplier;
5223 if(tng_data->input_endianness_swap_func_32 &&
5224 tng_data->input_endianness_swap_func_32(tng_data,
5225 (int32_t *)(block->block_contents + i))
5228 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5229 __FILE__, __LINE__);
5236 if(tng_data->input_endianness_swap_func_64)
5238 for(i = offset; i < block->block_contents_size; i+=size)
5240 if(tng_data->input_endianness_swap_func_64(tng_data,
5241 (int64_t *)(block->block_contents + i))
5244 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5245 __FILE__, __LINE__);
5250 case TNG_DOUBLE_DATA:
5251 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
5252 data->codec_id == TNG_TNG_COMPRESSION)
5254 if(tng_data->input_endianness_swap_func_64)
5256 for(i = offset; i < block->block_contents_size; i+=size)
5258 if(tng_data->input_endianness_swap_func_64(tng_data,
5259 (int64_t *)(block->block_contents + i))
5262 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5263 __FILE__, __LINE__);
5270 multiplier = data->compression_multiplier;
5271 if(fabs(multiplier - 1.0) > 0.00001 ||
5272 tng_data->input_endianness_swap_func_64)
5274 for(i = offset; i < block->block_contents_size; i+=size)
5276 *(double *)(block->block_contents + i) *= multiplier;
5277 if(tng_data->input_endianness_swap_func_64 &&
5278 tng_data->input_endianness_swap_func_64(tng_data,
5279 (int64_t *)(block->block_contents + i))
5282 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5283 __FILE__, __LINE__);
5295 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
5298 frame_set->n_written_frames += frame_set->n_unwritten_frames;
5299 frame_set->n_unwritten_frames = 0;
5301 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
5303 switch(data->codec_id)
5305 case TNG_XTC_COMPRESSION:
5306 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5307 data->codec_id = TNG_UNCOMPRESSED;
5309 case TNG_TNG_COMPRESSION:
5310 stat = tng_compress(tng_data, block, frame_step,
5311 n_particles, data->datatype,
5312 block->block_contents + data_start_pos);
5313 if(stat != TNG_SUCCESS)
5315 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
5316 __FILE__, __LINE__);
5317 if(stat == TNG_CRITICAL)
5319 return(TNG_CRITICAL);
5321 /* Set the data again, but with no compression (to write only
5322 * the relevant data) */
5323 data->codec_id = TNG_UNCOMPRESSED;
5324 stat = tng_particle_data_block_write(tng_data, block,
5325 block_index, mapping,
5331 case TNG_GZIP_COMPRESSION:
5332 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
5333 stat = tng_gzip_compress(tng_data, block,
5334 block->block_contents + data_start_pos,
5335 block->block_contents_size - data_start_pos);
5336 if(stat != TNG_SUCCESS)
5338 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
5340 if(stat == TNG_CRITICAL)
5342 return(TNG_CRITICAL);
5344 /* Set the data again, but with no compression (to write only
5345 * the relevant data) */
5346 data->codec_id = TNG_UNCOMPRESSED;
5347 stat = tng_particle_data_block_write(tng_data, block,
5348 block_index, mapping,
5352 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
5358 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
5360 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
5361 tng_data->output_file_path, __FILE__, __LINE__);
5362 return(TNG_CRITICAL);
5365 if(fwrite(block->block_contents, block->block_contents_size, 1,
5366 tng_data->output_file) != 1)
5368 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
5370 return(TNG_CRITICAL);
5373 return(TNG_SUCCESS);
5377 /** Create a non-particle data block
5378 * @param tng_data is a trajectory data container.
5379 * @param block_type_flag specifies if this is a trajectory block or a
5380 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
5381 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5382 * error has occured.
5384 static tng_function_status tng_data_block_create
5385 (tng_trajectory_t tng_data,
5386 const char block_type_flag)
5388 tng_trajectory_frame_set_t frame_set =
5389 &tng_data->current_trajectory_frame_set;
5391 tng_non_particle_data_t data;
5393 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5395 frame_set->n_data_blocks++;
5396 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
5397 frame_set->n_data_blocks);
5400 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5401 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
5402 __FILE__, __LINE__);
5403 free(frame_set->tr_data);
5404 frame_set->tr_data = 0;
5405 return(TNG_CRITICAL);
5407 frame_set->tr_data = data;
5411 tng_data->n_data_blocks++;
5412 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
5413 tng_data->n_data_blocks);
5416 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5417 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
5418 __FILE__, __LINE__);
5419 free(tng_data->non_tr_data);
5420 tng_data->non_tr_data = 0;
5421 return(TNG_CRITICAL);
5423 tng_data->non_tr_data = data;
5426 return(TNG_SUCCESS);
5430 /** Allocate memory for storing non-particle data.
5431 * The allocated block will be refered to by data->values.
5432 * @param tng_data is a trajectory data container.
5433 * @param data is the data struct, which will contain the allocated memory in
5435 * @param n_frames is the number of frames of data to store.
5436 * @param n_values_per_frame is the number of data values per frame.
5437 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5438 * error has occured.
5440 static tng_function_status tng_allocate_data_mem
5441 (tng_trajectory_t tng_data,
5442 tng_non_particle_data_t data,
5444 int64_t stride_length,
5445 const int64_t n_values_per_frame)
5448 int64_t i, j, size, frame_alloc;
5451 if(data->strings && data->datatype == TNG_CHAR_DATA)
5453 for(i = data->n_frames; i--;)
5455 for(j = data->n_values_per_frame; j--;)
5457 if(data->strings[i][j])
5459 free(data->strings[i][j]);
5460 data->strings[i][j] = 0;
5463 free(data->strings[i]);
5464 data->strings[i] = 0;
5466 free(data->strings);
5468 data->n_frames = n_frames;
5469 data->stride_length = tng_max_i64(1, stride_length);
5470 n_frames = tng_max_i64(1, n_frames);
5471 data->n_values_per_frame = n_values_per_frame;
5472 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5474 if(data->datatype == TNG_CHAR_DATA)
5476 data->strings = malloc(sizeof(char **) * frame_alloc);
5477 for(i = frame_alloc; i-- ;)
5479 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
5480 if(!data->strings[i])
5482 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5484 __FILE__, __LINE__);
5485 return(TNG_CRITICAL);
5487 for(j = n_values_per_frame; j--;)
5489 data->strings[i][j] = 0;
5495 switch(data->datatype)
5498 size = sizeof(int64_t);
5500 case TNG_FLOAT_DATA:
5501 size = sizeof(float);
5503 case TNG_DOUBLE_DATA:
5505 size = sizeof(double);
5508 values = realloc(data->values,
5509 size * frame_alloc *
5510 n_values_per_frame);
5513 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5514 size * frame_alloc *
5516 __FILE__, __LINE__);
5519 return(TNG_CRITICAL);
5521 data->values = values;
5524 return(TNG_SUCCESS);
5527 /** Read the values of a non-particle data block
5528 * @param tng_data is a trajectory data container.
5529 * @param block is the block to store the data (should already contain
5530 * the block headers and the block contents).
5531 * @param offset is the reading offset to point at the place where the actual
5532 * values are stored, starting from the beginning of the block_contents. The
5533 * offset is changed during the reading.
5534 * @param datatype is the type of data of the data block (char, int, float or
5536 * @param first_frame_with_data is the frame number of the first frame with data
5537 * in this data block.
5538 * @param stride_length is the number of frames between each data entry.
5539 * @param n_frames is the number of frames in this data block.
5540 * @param n_values is the number of values per frame stored in this data block.
5541 * @param codec_id is the ID of the codec to compress the data.
5542 * @param multiplier is the multiplication factor applied to each data value
5543 * before compression. This factor is applied since some compression algorithms
5544 * work only on integers.
5545 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5546 * error has occured.
5548 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
5549 tng_gen_block_t block,
5551 const char datatype,
5552 const int64_t first_frame_with_data,
5553 const int64_t stride_length,
5555 const int64_t n_values,
5556 const int64_t codec_id,
5557 const double multiplier)
5559 int64_t i, j, n_frames_div;
5562 unsigned long data_size;
5564 tng_non_particle_data_t data;
5565 tng_trajectory_frame_set_t frame_set =
5566 &tng_data->current_trajectory_frame_set;
5567 char block_type_flag;
5569 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5571 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
5579 size = sizeof(int64_t);
5581 case TNG_FLOAT_DATA:
5582 size = sizeof(float);
5584 case TNG_DOUBLE_DATA:
5586 size = sizeof(double);
5589 /* If the block does not exist, create it */
5590 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5592 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5594 block_type_flag = TNG_TRAJECTORY_BLOCK;
5598 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5601 if(tng_data_block_create(tng_data, block_type_flag) !=
5604 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5605 __FILE__, __LINE__);
5606 return(TNG_CRITICAL);
5608 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5610 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
5614 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
5616 data->block_id = block->id;
5618 data->block_name = malloc(strlen(block->name) + 1);
5619 if(!data->block_name)
5621 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5622 (int)strlen(block->name)+1, __FILE__, __LINE__);
5623 return(TNG_CRITICAL);
5625 strcpy(data->block_name, block->name);
5627 data->datatype = datatype;
5630 /* FIXME: Memory leak from strings. */
5633 data->codec_id = codec_id;
5634 data->compression_multiplier = multiplier;
5635 data->last_retrieved_frame = -1;
5638 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5640 if(codec_id != TNG_UNCOMPRESSED)
5645 case TNG_GZIP_COMPRESSION:
5646 data_size = n_frames_div * size * n_values;
5647 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
5648 if(tng_gzip_uncompress(tng_data, block,
5649 block->block_contents + *offset,
5650 data_size) != TNG_SUCCESS)
5652 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5654 return(TNG_CRITICAL);
5656 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
5662 /* Allocate memory */
5663 if(!data->values || data->n_frames != n_frames ||
5664 data->n_values_per_frame != n_values)
5666 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
5670 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
5671 __FILE__, __LINE__);
5672 return(TNG_CRITICAL);
5676 data->first_frame_with_data = first_frame_with_data;
5678 if(datatype == TNG_CHAR_DATA)
5680 for(i = 0; i < n_frames_div; i++)
5682 for(j = 0; j < n_values; j++)
5684 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5686 if(data->strings[i][j])
5688 free(data->strings[i][j]);
5690 data->strings[i][j] = malloc(len);
5691 if(!data->strings[i][j])
5693 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5694 len, __FILE__, __LINE__);
5695 return(TNG_CRITICAL);
5697 strncpy(data->strings[i][j], block->block_contents+*offset,
5705 memcpy(data->values, block->block_contents + *offset,
5706 block->block_contents_size - *offset);
5709 case TNG_FLOAT_DATA:
5710 if(tng_data->input_endianness_swap_func_32)
5712 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5714 if(tng_data->input_endianness_swap_func_32(tng_data,
5715 (int32_t *)((char *)data->values + i))
5718 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5719 __FILE__, __LINE__);
5725 case TNG_DOUBLE_DATA:
5726 if(tng_data->input_endianness_swap_func_64)
5728 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5730 if(tng_data->input_endianness_swap_func_64(tng_data,
5731 (int64_t *)((char *)data->values + i))
5734 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5735 __FILE__, __LINE__);
5744 return(TNG_SUCCESS);
5747 /** Write a non-particle data block
5748 * @param tng_data is a trajectory data container.
5749 * @param block is the block to store the data (should already contain
5750 * the block headers and the block contents).
5751 * @param block_index is the index number of the data block in the frame set.
5752 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5753 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5754 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5755 * error has occured.
5757 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
5758 tng_gen_block_t block,
5759 const int64_t block_index,
5760 const char hash_mode)
5762 int64_t n_frames, stride_length, frame_step;
5764 int offset = 0, size;
5768 tng_function_status stat;
5770 char temp, dependency, *temp_name;
5772 tng_trajectory_frame_set_t frame_set =
5773 &tng_data->current_trajectory_frame_set;
5775 tng_non_particle_data_t data;
5776 char block_type_flag;
5778 /* If we have already started writing frame sets it is too late to write
5779 * non-trajectory data blocks */
5780 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5782 block_type_flag = TNG_TRAJECTORY_BLOCK;
5786 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5789 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5791 return(TNG_CRITICAL);
5794 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5796 data = &frame_set->tr_data[block_index];
5798 /* If this data block has not had any data added in this frame set
5799 * do not write it. */
5800 if(data->first_frame_with_data < frame_set->first_frame)
5802 return(TNG_SUCCESS);
5805 stride_length = tng_max_i64(1, data->stride_length);
5809 data = &tng_data->non_tr_data[block_index];
5813 switch(data->datatype)
5819 size = sizeof(int64_t);
5821 case TNG_FLOAT_DATA:
5822 size = sizeof(float);
5824 case TNG_DOUBLE_DATA:
5826 size = sizeof(double);
5829 len = (unsigned int)strlen(data->block_name) + 1;
5831 if(!block->name || strlen(block->name) < len)
5833 temp_name = realloc(block->name, len);
5836 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
5837 __FILE__, __LINE__);
5840 return(TNG_CRITICAL);
5842 block->name = temp_name;
5844 strncpy(block->name, data->block_name, len);
5845 block->id = data->block_id;
5847 /* If writing frame independent data data->n_frames is 0, but n_frames
5848 is used for the loop writing the data (and reserving memory) and needs
5850 n_frames = tng_max_i64(1, data->n_frames);
5852 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5854 /* If the frame set is finished before writing the full number of frames
5855 make sure the data block is not longer than the frame set. */
5856 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5858 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5861 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5862 n_frames / stride_length;
5864 /* TNG compression will use compression precision to get integers from
5865 * floating point data. The compression multiplier stores that information
5866 * to be able to return the precision of the compressed data. */
5867 if(data->codec_id == TNG_TNG_COMPRESSION)
5869 data->compression_multiplier = tng_data->compression_precision;
5871 /* Uncompressed data blocks do not use compression multipliers at all.
5872 * GZip compression does not need it either. */
5873 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5875 data->compression_multiplier = 1.0;
5878 block->block_contents_size = sizeof(char) * 2 +
5879 sizeof(data->n_values_per_frame) +
5880 sizeof(data->codec_id);
5882 if(stride_length > 1)
5884 block->block_contents_size += sizeof(data->first_frame_with_data) +
5885 sizeof(data->stride_length);
5888 if(data->codec_id != TNG_UNCOMPRESSED)
5890 block->block_contents_size += sizeof(data->compression_multiplier);
5893 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
5895 dependency = TNG_FRAME_DEPENDENT;
5901 if(dependency & TNG_FRAME_DEPENDENT)
5903 block->block_contents_size += sizeof(char);
5907 data_start_pos = block->block_contents_size;
5910 if(data->datatype == TNG_CHAR_DATA)
5912 for(i = n_frames; i--;)
5914 for(j = data->n_values_per_frame; j--;)
5916 block->block_contents_size += strlen(data->strings[i][j]) + 1;
5922 block->block_contents_size += size * frame_step *
5923 data->n_values_per_frame;
5926 if(block->block_contents)
5928 free(block->block_contents);
5930 block->block_contents = malloc(block->block_contents_size);
5931 if(!block->block_contents)
5933 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5934 block->block_contents_size, __FILE__, __LINE__);
5935 return(TNG_CRITICAL);
5939 memcpy(block->block_contents, &data->datatype, sizeof(char));
5940 offset += sizeof(char);
5942 memcpy(block->block_contents+offset, &dependency, sizeof(char));
5943 offset += sizeof(char);
5945 if(dependency & TNG_FRAME_DEPENDENT)
5947 if(stride_length > 1)
5955 memcpy(block->block_contents+offset, &temp, sizeof(char));
5956 offset += sizeof(char);
5959 memcpy(block->block_contents+offset, &data->n_values_per_frame,
5960 sizeof(data->n_values_per_frame));
5961 if(tng_data->output_endianness_swap_func_64)
5963 if(tng_data->output_endianness_swap_func_64(tng_data,
5964 (int64_t *)block->header_contents+offset)
5967 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5968 __FILE__, __LINE__);
5971 offset += sizeof(data->n_values_per_frame);
5973 memcpy(block->block_contents+offset, &data->codec_id,
5974 sizeof(data->codec_id));
5975 if(tng_data->output_endianness_swap_func_64)
5977 if(tng_data->output_endianness_swap_func_64(tng_data,
5978 (int64_t *)block->header_contents+offset)
5981 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5982 __FILE__, __LINE__);
5985 offset += sizeof(data->codec_id);
5987 if(data->codec_id != TNG_UNCOMPRESSED)
5989 memcpy(block->block_contents+offset, &data->compression_multiplier,
5990 sizeof(data->compression_multiplier));
5991 if(tng_data->output_endianness_swap_func_64)
5993 if(tng_data->output_endianness_swap_func_64(tng_data,
5994 (int64_t *)block->header_contents+offset)
5997 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5998 __FILE__, __LINE__);
6001 offset += sizeof(data->compression_multiplier);
6004 if(data->n_frames > 0 && stride_length > 1)
6006 /* FIXME: first_frame_with_data is not reliably set */
6007 if(data->first_frame_with_data == 0)
6009 data->first_frame_with_data = frame_set->first_frame;
6011 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6012 sizeof(data->first_frame_with_data));
6013 if(tng_data->output_endianness_swap_func_64)
6015 if(tng_data->output_endianness_swap_func_64(tng_data,
6016 (int64_t *)block->header_contents+offset)
6019 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6020 __FILE__, __LINE__);
6023 offset += sizeof(data->first_frame_with_data);
6025 memcpy(block->block_contents+offset, &stride_length,
6026 sizeof(data->stride_length));
6027 if(tng_data->output_endianness_swap_func_64)
6029 if(tng_data->output_endianness_swap_func_64(tng_data,
6030 (int64_t *)block->header_contents+offset)
6033 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6034 __FILE__, __LINE__);
6037 offset += sizeof(data->stride_length);
6040 if(data->datatype == TNG_CHAR_DATA)
6044 for(i = 0; i < frame_step; i++)
6046 for(j = 0; j < data->n_values_per_frame; j++)
6048 len = (unsigned int)strlen(data->strings[i][j]) + 1;
6049 strncpy(block->block_contents+offset, data->strings[i][j],
6056 else if(data->values)
6058 memcpy(block->block_contents + offset, data->values,
6059 block->block_contents_size - offset);
6060 switch(data->datatype)
6062 case TNG_FLOAT_DATA:
6063 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6064 data->codec_id == TNG_TNG_COMPRESSION)
6066 if(tng_data->input_endianness_swap_func_32)
6068 for(i = offset; i < block->block_contents_size; i+=size)
6070 if(tng_data->input_endianness_swap_func_32(tng_data,
6071 (int32_t *)(block->block_contents + i))
6074 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6075 __FILE__, __LINE__);
6082 multiplier = data->compression_multiplier;
6083 if(fabs(multiplier - 1.0) > 0.00001 ||
6084 tng_data->input_endianness_swap_func_32)
6086 for(i = offset; block->block_contents_size; i+=size)
6088 *(float *)(block->block_contents + i) *= (float)multiplier;
6089 if(tng_data->input_endianness_swap_func_32 &&
6090 tng_data->input_endianness_swap_func_32(tng_data,
6091 (int32_t *)(block->block_contents + i))
6094 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6095 __FILE__, __LINE__);
6102 if(tng_data->input_endianness_swap_func_64)
6104 for(i = offset; i < block->block_contents_size; i+=size)
6106 if(tng_data->input_endianness_swap_func_64(tng_data,
6107 (int64_t *)(block->block_contents + i))
6110 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6111 __FILE__, __LINE__);
6116 case TNG_DOUBLE_DATA:
6117 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6118 data->codec_id == TNG_TNG_COMPRESSION)
6120 if(tng_data->input_endianness_swap_func_64)
6122 for(i = offset; i < block->block_contents_size; i+=size)
6124 if(tng_data->input_endianness_swap_func_64(tng_data,
6125 (int64_t *)(block->block_contents + i))
6128 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6129 __FILE__, __LINE__);
6136 multiplier = data->compression_multiplier;
6137 if(fabs(multiplier - 1.0) > 0.00001 ||
6138 tng_data->input_endianness_swap_func_64)
6140 for(i = offset; i < block->block_contents_size; i+=size)
6142 *(double *)(block->block_contents + i) *= multiplier;
6143 if(tng_data->input_endianness_swap_func_64 &&
6144 tng_data->input_endianness_swap_func_64(tng_data,
6145 (int64_t *)(block->block_contents + i))
6148 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6149 __FILE__, __LINE__);
6161 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6164 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6165 frame_set->n_unwritten_frames = 0;
6167 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6169 switch(data->codec_id)
6172 case TNG_GZIP_COMPRESSION:
6173 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6174 stat = tng_gzip_compress(tng_data, block,
6175 block->block_contents + data_start_pos,
6176 block->block_contents_size - data_start_pos);
6177 if(stat != TNG_SUCCESS)
6179 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6181 if(stat == TNG_CRITICAL)
6183 return(TNG_CRITICAL);
6185 data->codec_id = TNG_UNCOMPRESSED;
6187 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6193 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6195 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6196 tng_data->output_file_path, __FILE__, __LINE__);
6197 return(TNG_CRITICAL);
6200 if(fwrite(block->block_contents, block->block_contents_size, 1,
6201 tng_data->output_file) != 1)
6203 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
6204 __FILE__, __LINE__);
6205 return(TNG_CRITICAL);
6208 return(TNG_SUCCESS);
6211 /** Read the meta information of a data block (particle or non-particle data).
6212 * @param tng_data is a trajectory data container.
6213 * @param block is the block to store the data (should already contain
6214 * the block headers).
6215 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6216 * error has occured.
6218 static tng_function_status tng_data_block_meta_information_read
6219 (tng_trajectory_t tng_data,
6220 tng_gen_block_t block,
6227 int64_t *first_frame_with_data,
6228 int64_t *stride_length,
6230 int64_t *num_first_particle,
6231 int64_t *block_n_particles,
6237 if(block->block_contents)
6239 contents = block->block_contents;
6243 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
6244 contents = malloc(meta_size);
6248 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6249 meta_size, __FILE__, __LINE__);
6252 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
6254 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
6256 return(TNG_CRITICAL);
6260 memcpy(datatype, contents+*offset,
6262 *offset += sizeof(*datatype);
6264 memcpy(dependency, contents+*offset,
6265 sizeof(*dependency));
6266 *offset += sizeof(*dependency);
6268 if(*dependency & TNG_FRAME_DEPENDENT)
6270 memcpy(sparse_data, contents+*offset,
6271 sizeof(*sparse_data));
6272 *offset += sizeof(*sparse_data);
6275 memcpy(n_values, contents+*offset,
6277 if(tng_data->input_endianness_swap_func_64)
6279 if(tng_data->input_endianness_swap_func_64(tng_data,
6283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6284 __FILE__, __LINE__);
6287 *offset += sizeof(*n_values);
6289 memcpy(codec_id, contents+*offset,
6291 if(tng_data->input_endianness_swap_func_64)
6293 if(tng_data->input_endianness_swap_func_64(tng_data,
6297 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6298 __FILE__, __LINE__);
6301 *offset += sizeof(*codec_id);
6303 if(*codec_id != TNG_UNCOMPRESSED)
6305 memcpy(multiplier, contents+*offset,
6306 sizeof(*multiplier));
6307 if(tng_data->input_endianness_swap_func_64)
6309 if(tng_data->input_endianness_swap_func_64(tng_data,
6310 (int64_t *) multiplier)
6313 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6314 __FILE__, __LINE__);
6317 *offset += sizeof(*multiplier);
6324 if(*dependency & TNG_FRAME_DEPENDENT)
6328 memcpy(first_frame_with_data, contents+*offset,
6329 sizeof(*first_frame_with_data));
6330 if(tng_data->input_endianness_swap_func_64)
6332 if(tng_data->input_endianness_swap_func_64(tng_data,
6333 first_frame_with_data)
6336 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6337 __FILE__, __LINE__);
6340 *offset += sizeof(*first_frame_with_data);
6342 memcpy(stride_length, contents+*offset,
6343 sizeof(*stride_length));
6344 if(tng_data->input_endianness_swap_func_64)
6346 if(tng_data->input_endianness_swap_func_64(tng_data,
6350 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6351 __FILE__, __LINE__);
6354 *offset += sizeof(*stride_length);
6355 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
6356 (*first_frame_with_data -
6357 tng_data->current_trajectory_frame_set.first_frame);
6361 *first_frame_with_data = 0;
6363 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6368 *first_frame_with_data = 0;
6373 if (*dependency & TNG_PARTICLE_DEPENDENT)
6375 memcpy(num_first_particle, contents+*offset,
6376 sizeof(*num_first_particle));
6377 if(tng_data->input_endianness_swap_func_64)
6379 if(tng_data->input_endianness_swap_func_64(tng_data,
6383 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6384 __FILE__, __LINE__);
6387 *offset += sizeof(*num_first_particle);
6389 memcpy(block_n_particles, contents+*offset,
6390 sizeof(*block_n_particles));
6391 if(tng_data->input_endianness_swap_func_64)
6393 if(tng_data->input_endianness_swap_func_64(tng_data,
6397 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6398 __FILE__, __LINE__);
6401 *offset += sizeof(*block_n_particles);
6404 if(!block->block_contents)
6408 return(TNG_SUCCESS);
6411 /** Read the contents of a data block (particle or non-particle data).
6412 * @param tng_data is a trajectory data container.
6413 * @param block is the block to store the data (should already contain
6414 * the block headers).
6415 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6416 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6417 * compared to the md5 hash of the read contents to ensure valid data.
6418 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6419 * error has occured.
6421 static tng_function_status tng_data_block_contents_read
6422 (tng_trajectory_t tng_data,
6423 tng_gen_block_t block,
6424 const char hash_mode)
6426 int64_t n_values, codec_id, n_frames, first_frame_with_data;
6427 int64_t stride_length, block_n_particles, num_first_particle;
6429 char datatype, dependency, sparse_data;
6433 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
6435 return(TNG_CRITICAL);
6438 if(block->block_contents)
6440 free(block->block_contents);
6443 block->block_contents = malloc(block->block_contents_size);
6444 if(!block->block_contents)
6446 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6447 block->block_contents_size, __FILE__, __LINE__);
6448 return(TNG_CRITICAL);
6451 /* Read the whole block into block_contents to be able to write it to
6452 * disk even if it cannot be interpreted. */
6453 if(fread(block->block_contents, block->block_contents_size, 1,
6454 tng_data->input_file) == 0)
6456 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
6457 return(TNG_CRITICAL);
6460 /* FIXME: Does not check if the size of the contents matches the expected
6461 * size or if the contents can be read. */
6463 if(hash_mode == TNG_USE_HASH)
6465 tng_md5_hash_match_verify(block, &same_hash);
6466 if(same_hash != TNG_TRUE)
6468 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
6469 block->name, __FILE__, __LINE__);
6470 /* return(TNG_FAILURE); */
6474 if(tng_data_block_meta_information_read(tng_data, block,
6476 &dependency, &sparse_data,
6477 &n_values, &codec_id,
6478 &first_frame_with_data,
6479 &stride_length, &n_frames,
6480 &num_first_particle,
6482 &multiplier) == TNG_CRITICAL)
6484 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6485 block->name, __FILE__, __LINE__);
6486 return(TNG_CRITICAL);
6489 if (dependency & TNG_PARTICLE_DEPENDENT)
6491 return(tng_particle_data_read(tng_data, block,
6495 first_frame_with_data,
6498 codec_id, multiplier));
6502 return(tng_data_read(tng_data, block,
6504 first_frame_with_data,
6507 codec_id, multiplier));
6511 /** Update the md5 hash of a block already written to the file
6512 * @param tng_data is a trajectory data container.
6513 * @param block is the block, of which to update the md5 hash.
6514 * @param header_start_pos is the file position where the block header starts.
6515 * @param contents_start_pos is the file position where the block contents
6517 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6518 * error has occured.
6520 static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
6521 tng_gen_block_t block,
6522 const int64_t header_start_pos,
6523 const int64_t contents_start_pos)
6525 if(block->block_contents)
6527 free(block->block_contents);
6530 block->block_contents = malloc(block->block_contents_size);
6531 fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
6532 if(fread(block->block_contents, block->block_contents_size, 1,
6533 tng_data->output_file) == 0)
6535 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
6536 return(TNG_CRITICAL);
6539 tng_block_md5_hash_generate(block);
6541 fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
6543 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
6545 return(TNG_SUCCESS);
6548 /** Update the frame set pointers in the file header (general info block),
6549 * already written to disk
6550 * @param tng_data is a trajectory data container.
6551 * @param hash_mode specifies whether to update the block md5 hash when
6552 * updating the pointers.
6553 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6554 * error has occured.
6556 static tng_function_status tng_header_pointers_update
6557 (tng_trajectory_t tng_data, const char hash_mode)
6559 tng_gen_block_t block;
6560 FILE *temp = tng_data->input_file;
6561 int64_t output_file_pos, pos, contents_start_pos;
6563 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6565 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6566 __FILE__, __LINE__);
6567 return(TNG_CRITICAL);
6570 tng_data->input_file = tng_data->output_file;
6572 tng_block_init(&block);
6574 output_file_pos = ftell(tng_data->output_file);
6575 fseek(tng_data->output_file, 0, SEEK_SET);
6577 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6579 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
6580 __FILE__, __LINE__);
6581 tng_data->input_file = temp;
6582 tng_block_destroy(&block);
6583 return(TNG_CRITICAL);
6586 contents_start_pos = ftell(tng_data->output_file);
6588 fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
6589 sizeof(int64_t), SEEK_CUR);
6591 tng_data->input_file = temp;
6593 pos = tng_data->first_trajectory_frame_set_output_file_pos;
6595 if(tng_data->input_endianness_swap_func_64)
6597 if(tng_data->input_endianness_swap_func_64(tng_data,
6601 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6602 __FILE__, __LINE__);
6606 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6608 tng_block_destroy(&block);
6609 return(TNG_CRITICAL);
6612 pos = tng_data->last_trajectory_frame_set_output_file_pos;
6614 if(tng_data->input_endianness_swap_func_64)
6616 if(tng_data->input_endianness_swap_func_64(tng_data,
6620 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6621 __FILE__, __LINE__);
6626 sizeof(int64_t), 1, tng_data->output_file) != 1)
6628 tng_block_destroy(&block);
6629 return(TNG_CRITICAL);
6632 if(hash_mode == TNG_USE_HASH)
6634 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
6637 tng_block_destroy(&block);
6639 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
6641 return(TNG_SUCCESS);
6644 /** Update the frame set pointers in the current frame set block, already
6645 * written to disk. It also updates the pointers of the blocks pointing to
6646 * the current frame set block.
6647 * @param tng_data is a trajectory data container.
6648 * @param hash_mode specifies whether to update the block md5 hash when
6649 * updating the pointers.
6650 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6651 * error has occured.
6653 static tng_function_status tng_frame_set_pointers_update
6654 (tng_trajectory_t tng_data, const char hash_mode)
6656 tng_gen_block_t block;
6657 tng_trajectory_frame_set_t frame_set;
6658 FILE *temp = tng_data->input_file;
6659 int64_t pos, output_file_pos, header_start_pos, contents_start_pos;
6661 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6663 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6664 __FILE__, __LINE__);
6665 return(TNG_CRITICAL);
6668 tng_block_init(&block);
6669 output_file_pos = ftell(tng_data->output_file);
6671 tng_data->input_file = tng_data->output_file;
6673 frame_set = &tng_data->current_trajectory_frame_set;
6675 /* Update previous frame set */
6676 if(frame_set->prev_frame_set_file_pos != -1 &&
6677 frame_set->prev_frame_set_file_pos != 0)
6679 fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
6682 header_start_pos = frame_set->prev_frame_set_file_pos;
6684 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6686 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
6687 __FILE__, __LINE__);
6688 tng_data->input_file = temp;
6689 tng_block_destroy(&block);
6690 return(TNG_CRITICAL);
6693 contents_start_pos = ftell(tng_data->output_file);
6695 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
6696 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
6698 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6700 if(tng_data->input_endianness_swap_func_64)
6702 if(tng_data->input_endianness_swap_func_64(tng_data,
6706 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6707 __FILE__, __LINE__);
6711 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6713 tng_data->input_file = temp;
6714 tng_block_destroy(&block);
6715 return(TNG_CRITICAL);
6718 if(hash_mode == TNG_USE_HASH)
6720 tng_md5_hash_update(tng_data, block, header_start_pos,
6721 contents_start_pos);
6723 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
6726 /* Update the frame set one medium stride step before */
6727 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
6728 frame_set->medium_stride_prev_frame_set_file_pos != 0)
6730 fseek(tng_data->output_file,
6731 (long)frame_set->medium_stride_prev_frame_set_file_pos,
6734 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6736 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6737 __FILE__, __LINE__);
6738 tng_data->input_file = temp;
6739 tng_block_destroy(&block);
6740 return(TNG_CRITICAL);
6743 contents_start_pos = ftell(tng_data->output_file);
6745 fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
6746 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
6748 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6750 if(tng_data->input_endianness_swap_func_64)
6752 if(tng_data->input_endianness_swap_func_64(tng_data,
6756 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6757 __FILE__, __LINE__);
6761 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6763 tng_data->input_file = temp;
6764 tng_block_destroy(&block);
6765 return(TNG_CRITICAL);
6768 if(hash_mode == TNG_USE_HASH)
6770 tng_md5_hash_update(tng_data, block,
6771 frame_set->medium_stride_prev_frame_set_file_pos,
6772 contents_start_pos);
6776 /* Update the frame set one long stride step before */
6777 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
6778 frame_set->long_stride_prev_frame_set_file_pos != 0)
6780 fseek(tng_data->output_file,
6781 (long)frame_set->long_stride_prev_frame_set_file_pos,
6784 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6786 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6787 __FILE__, __LINE__);
6788 tng_data->input_file = temp;
6789 tng_block_destroy(&block);
6790 return(TNG_CRITICAL);
6793 contents_start_pos = ftell(tng_data->output_file);
6795 fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
6796 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
6798 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6800 if(tng_data->input_endianness_swap_func_64)
6802 if(tng_data->input_endianness_swap_func_64(tng_data,
6806 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6807 __FILE__, __LINE__);
6811 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
6813 tng_data->input_file = temp;
6814 tng_block_destroy(&block);
6815 return(TNG_CRITICAL);
6818 if(hash_mode == TNG_USE_HASH)
6820 tng_md5_hash_update(tng_data, block,
6821 frame_set->long_stride_prev_frame_set_file_pos,
6822 contents_start_pos);
6826 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
6828 tng_data->input_file = temp;
6830 tng_block_destroy(&block);
6832 return(TNG_SUCCESS);
6835 // ** Move the blocks in a frame set so that there is no unused space between
6836 // * them. This can only be done on the last frame set in the file and should
6837 // * be done e.g. if the last frame set in the file has fewer frames than
6838 // * default or after compressing data blocks in a frame set.
6839 // * @param tng_data is a trajectory data container.
6840 // * @details the current_trajectory_frame_set is the one that will be modified.
6841 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6842 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6843 // * FIXME: This function is not finished!!!
6845 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6847 // tng_gen_block_t block;
6848 // tng_trajectory_frame_set_t frame_set;
6849 // FILE *temp = tng_data->input_file;
6850 // int64_t pos, contents_start_pos, output_file_len;
6852 // frame_set = &tng_data->current_trajectory_frame_set;
6854 // if(frame_set->n_written_frames == frame_set->n_frames)
6856 // return(TNG_SUCCESS);
6859 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6860 // tng_data->last_trajectory_frame_set_output_file_pos)
6864 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6866 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6867 // __FILE__, __LINE__);
6868 // return(TNG_CRITICAL);
6871 // tng_block_init(&block);
6872 // // output_file_pos = ftell(tng_data->output_file);
6874 // tng_data->input_file = tng_data->output_file;
6876 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6878 // fseek(tng_data->output_file, pos, SEEK_SET);
6879 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6881 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6882 // __FILE__, __LINE__);
6883 // tng_data->input_file = temp;
6884 // tng_block_destroy(&block);
6885 // return(TNG_CRITICAL);
6888 // contents_start_pos = ftell(tng_data->output_file);
6890 // fseek(tng_data->output_file, 0, SEEK_END);
6891 // output_file_len = ftell(tng_data->output_file);
6892 // pos = contents_start_pos + block->block_contents_size;
6893 // fseek(tng_data->output_file, pos,
6896 // while(pos < output_file_len)
6898 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6900 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
6901 // __FILE__, __LINE__);
6902 // tng_data->input_file = temp;
6903 // tng_block_destroy(&block);
6904 // return(TNG_CRITICAL);
6906 // pos += block->header_contents_size + block->block_contents_size;
6907 // fseek(tng_data->output_file, pos, SEEK_SET);
6910 // return(TNG_SUCCESS);
6913 /** Finish writing the current frame set. Update the number of frames
6914 * and the hashes of the frame set and all its data blocks (if hash_mode
6916 * @param tng_data is a trajectory data container.
6917 * @param hash_mode specifies whether to update the block md5 hash when
6918 * updating the pointers.
6919 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6920 * error has occured.
6922 static tng_function_status tng_frame_set_finalize
6923 (tng_trajectory_t tng_data, const char hash_mode)
6925 tng_gen_block_t block;
6926 tng_trajectory_frame_set_t frame_set;
6927 FILE *temp = tng_data->input_file;
6928 int64_t pos, contents_start_pos, output_file_len;
6930 frame_set = &tng_data->current_trajectory_frame_set;
6932 if(frame_set->n_written_frames == frame_set->n_frames)
6934 return(TNG_SUCCESS);
6937 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6939 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6940 __FILE__, __LINE__);
6941 return(TNG_CRITICAL);
6944 tng_block_init(&block);
6945 /* output_file_pos = ftell(tng_data->output_file); */
6947 tng_data->input_file = tng_data->output_file;
6949 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6951 fseek(tng_data->output_file, (long)pos, SEEK_SET);
6953 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6955 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6956 __FILE__, __LINE__);
6957 tng_data->input_file = temp;
6958 tng_block_destroy(&block);
6959 return(TNG_CRITICAL);
6962 contents_start_pos = ftell(tng_data->output_file);
6964 fseek(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
6965 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
6966 1, tng_data->output_file) != 1)
6968 tng_data->input_file = temp;
6969 tng_block_destroy(&block);
6970 return(TNG_CRITICAL);
6974 if(hash_mode == TNG_USE_HASH)
6976 tng_md5_hash_update(tng_data, block, pos,
6977 pos + block->header_contents_size);
6980 fseek(tng_data->output_file, 0, SEEK_END);
6981 output_file_len = ftell(tng_data->output_file);
6982 pos = contents_start_pos + block->block_contents_size;
6983 fseek(tng_data->output_file, (long)pos, SEEK_SET);
6985 while(pos < output_file_len)
6987 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6989 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
6990 __FILE__, __LINE__);
6991 tng_data->input_file = temp;
6992 tng_block_destroy(&block);
6993 return(TNG_CRITICAL);
6996 if(hash_mode == TNG_USE_HASH)
6998 tng_md5_hash_update(tng_data, block, pos,
6999 pos + block->header_contents_size);
7001 pos += block->header_contents_size + block->block_contents_size;
7002 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7005 tng_data->input_file = temp;
7006 tng_block_destroy(&block);
7007 return(TNG_SUCCESS);
7011 // ** Sets the name of a file contents block
7012 // * @param tng_data is a trajectory data container.
7013 // * @param block is the block, of which to change names.
7014 // * @param new_name is the new name of the block.
7015 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7016 // * error has occured.
7018 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7019 // tng_gen_block_t block,
7020 // const char *new_name)
7024 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7026 // * If the currently stored string length is not enough to store the new
7027 // * string it is freed and reallocated. *
7028 // if(block->name && strlen(block->name) < len)
7030 // free(block->name);
7035 // block->name = malloc(len);
7038 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7039 // __FILE__, __LINE__);
7040 // return(TNG_CRITICAL);
7044 // strncpy(block->name, new_name, len);
7046 // return(TNG_SUCCESS);
7050 tng_function_status tng_atom_residue_get(tng_trajectory_t tng_data,
7051 const tng_atom_t atom,
7052 tng_residue_t *residue)
7056 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7058 *residue = atom->residue;
7060 return(TNG_SUCCESS);
7063 tng_function_status tng_atom_name_get(tng_trajectory_t tng_data,
7064 const tng_atom_t atom,
7069 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7070 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7072 strncpy(name, atom->name, max_len - 1);
7073 name[max_len - 1] = 0;
7075 if(strlen(atom->name) > (unsigned int)max_len - 1)
7077 return(TNG_FAILURE);
7079 return(TNG_SUCCESS);
7082 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7084 const char *new_name)
7089 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7090 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7092 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7094 /* If the currently stored string length is not enough to store the new
7095 * string it is freed and reallocated. */
7096 if(atom->name && strlen(atom->name) < len)
7103 atom->name = malloc(len);
7106 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7107 __FILE__, __LINE__);
7108 return(TNG_CRITICAL);
7112 strncpy(atom->name, new_name, len);
7114 return(TNG_SUCCESS);
7117 tng_function_status tng_atom_type_get(tng_trajectory_t tng_data,
7118 const tng_atom_t atom,
7123 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7124 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7126 strncpy(type, atom->atom_type, max_len - 1);
7127 type[max_len - 1] = 0;
7129 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7131 return(TNG_FAILURE);
7133 return(TNG_SUCCESS);
7136 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7138 const char *new_type)
7143 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7144 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7146 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7148 /* If the currently stored string length is not enough to store the new
7149 * string it is freed and reallocated. */
7150 if(atom->atom_type && strlen(atom->atom_type) < len)
7152 free(atom->atom_type);
7153 atom->atom_type = 0;
7155 if(!atom->atom_type)
7157 atom->atom_type = malloc(len);
7158 if(!atom->atom_type)
7160 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7161 __FILE__, __LINE__);
7162 return(TNG_CRITICAL);
7166 strncpy(atom->atom_type, new_type, len);
7168 return(TNG_SUCCESS);
7171 /** Initialise an atom struct
7172 * @param atom is the atom to initialise.
7173 * @return TNG_SUCCESS (0) if successful.
7175 static tng_function_status tng_atom_init(tng_atom_t atom)
7178 atom->atom_type = 0;
7180 return(TNG_SUCCESS);
7183 /** Free the memory in an atom struct
7184 * @param atom is the atom to destroy.
7185 * @return TNG_SUCCESS (0) if successful.
7187 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7196 free(atom->atom_type);
7197 atom->atom_type = 0;
7200 return(TNG_SUCCESS);
7203 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7204 (tng_trajectory_t tng_data,
7206 tng_molecule_t *molecule)
7209 tng_bool found_id = TNG_TRUE;
7211 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7212 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7214 /* Find an unused ID */
7218 found_id = TNG_FALSE;
7219 for(i = tng_data->n_molecules; i--;)
7221 if(tng_data->molecules[i].id == id)
7223 found_id = TNG_TRUE;
7233 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7236 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7237 (tng_trajectory_t tng_data,
7240 tng_molecule_t *molecule)
7242 tng_molecule_t new_molecules;
7243 int64_t *new_molecule_cnt_list, i;
7244 tng_function_status stat = TNG_SUCCESS;
7246 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7247 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7249 new_molecules = realloc(tng_data->molecules,
7250 sizeof(struct tng_molecule) *
7251 (tng_data->n_molecules + 1));
7255 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7256 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7257 __FILE__, __LINE__);
7258 free(tng_data->molecules);
7259 tng_data->molecules = 0;
7260 return(TNG_CRITICAL);
7263 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7265 (tng_data->n_molecules + 1));
7267 if(!new_molecule_cnt_list)
7269 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7270 sizeof(int64_t) * (tng_data->n_molecules + 1),
7271 __FILE__, __LINE__);
7272 free(tng_data->molecule_cnt_list);
7273 tng_data->molecule_cnt_list = 0;
7274 free(new_molecules);
7275 return(TNG_CRITICAL);
7278 tng_data->molecules = new_molecules;
7279 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7281 *molecule = &new_molecules[tng_data->n_molecules];
7283 tng_molecule_init(tng_data, *molecule);
7284 tng_molecule_name_set(tng_data, *molecule, name);
7286 /* FIXME: Should this be a function argument instead? */
7287 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7289 for(i = tng_data->n_molecules; i--;)
7291 if(tng_data->molecules[i].id == id)
7294 fprintf(stderr, "TNG library: Molecule ID %"PRId64" already in use. %s: %d\n", id,
7295 __FILE__, __LINE__);
7300 (*molecule)->id = id;
7302 tng_data->n_molecules++;
7307 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
7308 (tng_trajectory_t tng_data,
7309 tng_molecule_t *molecule_p)
7311 tng_bool found_id = TNG_TRUE;
7312 tng_molecule_t new_molecules, molecule;
7313 int64_t *new_molecule_cnt_list, i, id;
7315 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7317 /* Find an unused ID */
7321 found_id = TNG_FALSE;
7322 for(i = tng_data->n_molecules; i--;)
7324 if(tng_data->molecules[i].id == id)
7326 found_id = TNG_TRUE;
7336 new_molecules = realloc(tng_data->molecules,
7337 sizeof(struct tng_molecule) *
7338 (tng_data->n_molecules + 1));
7342 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7343 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7344 __FILE__, __LINE__);
7345 free(tng_data->molecules);
7346 tng_data->molecules = 0;
7347 return(TNG_CRITICAL);
7350 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7352 (tng_data->n_molecules + 1));
7354 if(!new_molecule_cnt_list)
7356 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7357 sizeof(int64_t) * (tng_data->n_molecules + 1),
7358 __FILE__, __LINE__);
7359 free(tng_data->molecule_cnt_list);
7360 tng_data->molecule_cnt_list = 0;
7361 free(new_molecules);
7362 return(TNG_CRITICAL);
7365 molecule = *molecule_p;
7367 tng_data->molecules = new_molecules;
7368 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7370 new_molecules[tng_data->n_molecules] = *molecule;
7372 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7376 molecule = &new_molecules[tng_data->n_molecules];
7378 *molecule_p = molecule;
7382 tng_data->n_molecules++;
7384 return(TNG_SUCCESS);
7387 tng_function_status tng_molecule_name_get(tng_trajectory_t tng_data,
7388 const tng_molecule_t molecule,
7393 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7394 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7396 strncpy(name, molecule->name, max_len - 1);
7397 name[max_len - 1] = 0;
7399 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7401 return(TNG_FAILURE);
7403 return(TNG_SUCCESS);
7406 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7407 (tng_trajectory_t tng_data,
7408 tng_molecule_t molecule,
7409 const char *new_name)
7414 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7415 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7417 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7419 /* If the currently stored string length is not enough to store the new
7420 * string it is freed and reallocated. */
7421 if(molecule->name && strlen(molecule->name) < len)
7423 free(molecule->name);
7428 molecule->name = malloc(len);
7431 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7432 __FILE__, __LINE__);
7433 return(TNG_CRITICAL);
7437 strncpy(molecule->name, new_name, len);
7439 return(TNG_SUCCESS);
7442 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7443 (tng_trajectory_t tng_data,
7444 tng_molecule_t molecule,
7447 int64_t i, index = -1;
7449 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7450 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7452 for(i = tng_data->n_molecules; i--;)
7454 if(&tng_data->molecules[i] == molecule)
7462 return(TNG_FAILURE);
7464 *cnt = tng_data->molecule_cnt_list[index];
7466 return(TNG_SUCCESS);
7469 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7470 (tng_trajectory_t tng_data,
7471 tng_molecule_t molecule,
7474 int64_t i, old_cnt, index = -1;
7476 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7478 for(i = tng_data->n_molecules; i--;)
7480 if(&tng_data->molecules[i] == molecule)
7488 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7489 __FILE__, __LINE__);
7490 return(TNG_FAILURE);
7492 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7494 old_cnt = tng_data->molecule_cnt_list[index];
7495 tng_data->molecule_cnt_list[index] = cnt;
7497 tng_data->n_particles += (cnt-old_cnt) *
7498 tng_data->molecules[index].n_atoms;
7502 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7503 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7505 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7506 tng_data->molecules[index].n_atoms;
7509 return(TNG_SUCCESS);
7512 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7513 (tng_trajectory_t tng_data,
7516 tng_molecule_t *molecule)
7518 int64_t i, n_molecules;
7520 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7521 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7522 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7524 n_molecules = tng_data->n_molecules;
7526 for(i = 0; i < n_molecules; i++)
7528 *molecule = &tng_data->molecules[i];
7529 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7531 if(nr == -1 || nr == (*molecule)->id)
7533 return(TNG_SUCCESS);
7540 return(TNG_FAILURE);
7543 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7544 (tng_trajectory_t tng_data,
7546 tng_molecule_t *molecule)
7548 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7549 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7551 if(index >= tng_data->n_molecules)
7554 return(TNG_FAILURE);
7556 *molecule = &tng_data->molecules[index];
7557 return(TNG_SUCCESS);
7560 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
7561 tng_trajectory_t tng_data_dest)
7563 tng_molecule_t molecule, molecule_temp;
7564 tng_chain_t chain, chain_temp;
7565 tng_residue_t residue, residue_temp;
7566 tng_atom_t atom, atom_temp;
7567 tng_bond_t bond_temp;
7568 tng_function_status stat;
7569 int64_t i, j, k, l, *list_temp;
7571 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7572 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7574 for(i = 0; i < tng_data_dest->n_molecules; i++)
7576 molecule = &tng_data_dest->molecules[i];
7577 tng_molecule_destroy(tng_data_dest, molecule);
7580 tng_data_dest->n_molecules = 0;
7581 tng_data_dest->n_particles = 0;
7583 molecule_temp = realloc(tng_data_dest->molecules,
7584 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7587 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7588 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
7589 __FILE__, __LINE__);
7590 free(tng_data_dest->molecules);
7591 tng_data_dest->molecules = 0;
7592 return(TNG_CRITICAL);
7594 list_temp = realloc(tng_data_dest->molecule_cnt_list,
7595 sizeof(int64_t) * tng_data_src->n_molecules);
7598 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7599 sizeof(int64_t) * tng_data_src->n_molecules,
7600 __FILE__, __LINE__);
7601 free(tng_data_dest->molecule_cnt_list);
7602 tng_data_dest->molecule_cnt_list = 0;
7603 free(molecule_temp);
7604 return(TNG_CRITICAL);
7607 tng_data_dest->molecules = molecule_temp;
7608 tng_data_dest->molecule_cnt_list = list_temp;
7610 for(i = 0; i < tng_data_src->n_molecules; i++)
7612 molecule = &tng_data_src->molecules[i];
7613 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7615 if(stat != TNG_SUCCESS)
7617 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7618 __FILE__, __LINE__);
7621 molecule_temp->quaternary_str = molecule->quaternary_str;
7622 for(j = 0; j < molecule->n_chains; j++)
7624 chain = &molecule->chains[j];
7625 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7626 chain->name, chain->id,
7628 if(stat != TNG_SUCCESS)
7630 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7631 __FILE__, __LINE__);
7634 for(k = 0; k < chain->n_residues; k++)
7636 residue = &chain->residues[k];
7637 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7638 residue->name, residue->id,
7640 if(stat != TNG_SUCCESS)
7642 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7643 __FILE__, __LINE__);
7646 for(l = 0; l < residue->n_atoms; l++)
7648 atom = &molecule->atoms[residue->atoms_offset + l];
7649 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7650 atom->name, atom->atom_type,
7651 atom->id, &atom_temp);
7652 if(stat != TNG_SUCCESS)
7654 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7655 __FILE__, __LINE__);
7661 molecule_temp->n_bonds = molecule->n_bonds;
7662 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7666 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7667 sizeof(struct tng_bond) * molecule->n_bonds,
7668 __FILE__, __LINE__);
7669 free(molecule_temp->bonds);
7670 molecule_temp->n_bonds = 0;
7671 return(TNG_CRITICAL);
7673 molecule_temp->bonds = bond_temp;
7674 for(j = 0; j < molecule->n_bonds; j++)
7676 molecule_temp->bonds[j] = molecule->bonds[j];
7678 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7679 tng_data_src->molecule_cnt_list[i]);
7680 if(stat != TNG_SUCCESS)
7682 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7683 __FILE__, __LINE__);
7687 return(TNG_SUCCESS);
7690 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7691 (const tng_trajectory_t tng_data,
7692 const tng_molecule_t molecule,
7696 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7697 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7699 *n = molecule->n_chains;
7701 return(TNG_SUCCESS);
7704 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7705 (tng_trajectory_t tng_data,
7706 tng_molecule_t molecule,
7711 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7712 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7714 if(index >= molecule->n_chains)
7717 return(TNG_FAILURE);
7719 *chain = &molecule->chains[index];
7720 return(TNG_SUCCESS);
7723 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7724 (const tng_trajectory_t tng_data,
7725 const tng_molecule_t molecule,
7729 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7730 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7732 *n = molecule->n_residues;
7734 return(TNG_SUCCESS);
7737 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7738 (tng_trajectory_t tng_data,
7739 tng_molecule_t molecule,
7741 tng_residue_t *residue)
7744 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7745 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7747 if(index >= molecule->n_residues)
7750 return(TNG_FAILURE);
7752 *residue = &molecule->residues[index];
7753 return(TNG_SUCCESS);
7756 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7757 (const tng_trajectory_t tng_data,
7758 const tng_molecule_t molecule,
7762 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7763 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7765 *n = molecule->n_atoms;
7767 return(TNG_SUCCESS);
7770 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7771 (tng_trajectory_t tng_data,
7772 tng_molecule_t molecule,
7777 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7778 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7780 if(index >= molecule->n_atoms)
7783 return(TNG_FAILURE);
7785 *atom = &molecule->atoms[index];
7786 return(TNG_SUCCESS);
7789 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7790 (tng_trajectory_t tng_data,
7791 tng_molecule_t molecule,
7796 int64_t i, n_chains;
7799 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7800 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7802 n_chains = molecule->n_chains;
7804 for(i = 0; i < n_chains; i++)
7806 *chain = &molecule->chains[i];
7807 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7809 if(nr == -1 || nr == (*chain)->id)
7811 return(TNG_SUCCESS);
7818 return(TNG_FAILURE);
7821 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7822 (tng_trajectory_t tng_data,
7823 tng_molecule_t molecule,
7827 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7828 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7830 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7831 molecule->n_chains + 1, chain));
7834 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7835 (tng_trajectory_t tng_data,
7836 tng_molecule_t molecule,
7842 tng_chain_t new_chains;
7843 tng_function_status stat = TNG_SUCCESS;
7845 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7846 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7848 new_chains = realloc(molecule->chains,
7849 sizeof(struct tng_chain) *
7850 (molecule->n_chains + 1));
7854 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7855 sizeof(struct tng_chain) * (molecule->n_chains + 1),
7856 __FILE__, __LINE__);
7857 free(molecule->chains);
7858 molecule->chains = 0;
7859 return(TNG_CRITICAL);
7862 molecule->chains = new_chains;
7864 *chain = &new_chains[molecule->n_chains];
7867 tng_chain_name_set(tng_data, *chain, name);
7869 (*chain)->molecule = molecule;
7870 (*chain)->n_residues = 0;
7872 for(i = molecule->n_chains; i--;)
7874 if(molecule->chains[i].id == id)
7877 fprintf(stderr, "TNG library: Chain ID already in use. %s: %d\n", __FILE__, __LINE__);
7882 molecule->n_chains++;
7889 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7890 (const tng_trajectory_t tng_data,
7891 tng_molecule_t molecule,
7892 const int64_t from_atom_id,
7893 const int64_t to_atom_id,
7897 tng_bond_t new_bonds;
7900 for(i = 0; i < molecule->n_bonds; i++)
7902 *bond = &molecule->bonds[i];
7903 /* Check if the bond already exists */
7904 if(((*bond)->from_atom_id == from_atom_id && (*bond)->to_atom_id == to_atom_id) ||
7905 ((*bond)->to_atom_id == from_atom_id && (*bond)->from_atom_id == to_atom_id))
7907 return(TNG_SUCCESS);
7911 new_bonds = realloc(molecule->bonds,
7912 sizeof(struct tng_bond) *
7913 (molecule->n_bonds + 1));
7917 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7918 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
7919 __FILE__, __LINE__);
7921 free(molecule->bonds);
7922 molecule->bonds = 0;
7923 return(TNG_CRITICAL);
7926 molecule->bonds = new_bonds;
7928 *bond = &new_bonds[molecule->n_bonds];
7930 (*bond)->from_atom_id = from_atom_id;
7931 (*bond)->to_atom_id = to_atom_id;
7933 molecule->n_bonds++;
7935 return(TNG_SUCCESS);
7938 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7939 (tng_trajectory_t tng_data,
7940 tng_molecule_t molecule,
7948 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7950 n_atoms = molecule->n_atoms;
7952 for(i = 0; i < n_atoms; i++)
7954 *atom = &molecule->atoms[i];
7955 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
7957 if(id == -1 || id == (*atom)->id)
7959 return(TNG_SUCCESS);
7966 return(TNG_FAILURE);
7969 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
7970 const tng_chain_t chain,
7975 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7976 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7978 strncpy(name, chain->name, max_len - 1);
7979 name[max_len - 1] = 0;
7981 if(strlen(chain->name) > (unsigned int)max_len - 1)
7983 return(TNG_FAILURE);
7985 return(TNG_SUCCESS);
7988 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7989 (tng_trajectory_t tng_data,
7991 const char *new_name)
7996 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7998 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8000 /* If the currently stored string length is not enough to store the new
8001 * string it is freed and reallocated. */
8002 if(chain->name && strlen(chain->name) < len)
8009 chain->name = malloc(len);
8012 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8013 __FILE__, __LINE__);
8014 return(TNG_CRITICAL);
8018 strncpy(chain->name, new_name, len);
8020 return(TNG_SUCCESS);
8023 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8024 (const tng_trajectory_t tng_data,
8025 const tng_chain_t chain,
8029 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8030 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8032 *n = chain->n_residues;
8034 return(TNG_SUCCESS);
8037 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8038 (tng_trajectory_t tng_data,
8041 tng_residue_t *residue)
8044 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8045 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8047 if(index >= chain->n_residues)
8050 return(TNG_FAILURE);
8052 *residue = &chain->residues[index];
8053 return(TNG_SUCCESS);
8056 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8057 (tng_trajectory_t tng_data,
8061 tng_residue_t *residue)
8063 int64_t i, n_residues;
8066 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8068 n_residues = chain->n_residues;
8070 for(i = 0; i < n_residues; i++)
8072 *residue = &chain->residues[i];
8073 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8075 if(id == -1 || id == (*residue)->id)
8077 return(TNG_SUCCESS);
8084 return(TNG_FAILURE);
8087 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8088 (tng_trajectory_t tng_data,
8091 tng_residue_t *residue)
8093 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8094 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8096 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8097 chain->n_residues + 1, residue));
8100 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8101 (tng_trajectory_t tng_data,
8105 tng_residue_t *residue)
8107 int64_t i, curr_index;
8108 tng_residue_t new_residues, temp_residue, last_residue;
8109 tng_molecule_t molecule = chain->molecule;
8110 tng_function_status stat = TNG_SUCCESS;
8112 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8113 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8115 if(chain->n_residues)
8117 curr_index = chain->residues - molecule->residues;
8124 new_residues = realloc(molecule->residues,
8125 sizeof(struct tng_residue) *
8126 (molecule->n_residues + 1));
8130 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8131 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8132 __FILE__, __LINE__);
8133 free(molecule->residues);
8134 molecule->residues = 0;
8135 return(TNG_CRITICAL);
8138 molecule->residues = new_residues;
8140 if(curr_index != -1)
8142 chain->residues = new_residues + curr_index;
8143 if(molecule->n_residues)
8145 last_residue = &new_residues[molecule->n_residues - 1];
8147 temp_residue = chain->residues + (chain->n_residues - 1);
8148 /* Make space in list of residues to add the new residues together with the other
8149 * residues of this chain */
8150 if(temp_residue != last_residue)
8153 memmove(temp_residue + 1, temp_residue,
8154 last_residue - temp_residue);
8160 curr_index = molecule->n_residues;
8163 *residue = &molecule->residues[curr_index + chain->n_residues];
8165 if(!chain->n_residues)
8167 chain->residues = *residue;
8170 (*residue)->name = 0;
8171 tng_residue_name_set(tng_data, *residue, name);
8173 (*residue)->chain = chain;
8174 (*residue)->n_atoms = 0;
8175 (*residue)->atoms_offset = 0;
8177 for(i = chain->n_residues; i--;)
8179 if(chain->residues[i].id == id)
8182 fprintf(stderr, "TNG library: Residue ID already in use. %s: %d\n", __FILE__, __LINE__);
8187 chain->n_residues++;
8188 molecule->n_residues++;
8190 (*residue)->id = id;
8195 tng_function_status tng_residue_name_get(tng_trajectory_t tng_data,
8196 const tng_residue_t residue,
8201 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8202 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8204 strncpy(name, residue->name, max_len - 1);
8205 name[max_len - 1] = 0;
8207 if(strlen(residue->name) > (unsigned int)max_len - 1)
8209 return(TNG_FAILURE);
8211 return(TNG_SUCCESS);
8214 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8215 tng_residue_t residue,
8216 const char *new_name)
8221 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8222 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8224 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8226 /* If the currently stored string length is not enough to store the new
8227 * string it is freed and reallocated. */
8228 if(residue->name && strlen(residue->name) < len)
8230 free(residue->name);
8235 residue->name = malloc(len);
8238 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8239 __FILE__, __LINE__);
8240 return(TNG_CRITICAL);
8244 strncpy(residue->name, new_name, len);
8246 return(TNG_SUCCESS);
8249 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8250 (const tng_trajectory_t tng_data,
8251 const tng_residue_t residue,
8255 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8256 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8258 *n = residue->n_atoms;
8260 return(TNG_SUCCESS);
8263 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8264 (tng_trajectory_t tng_data,
8265 tng_residue_t residue,
8270 tng_molecule_t molecule;
8273 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8274 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8276 if(index >= residue->n_atoms)
8279 return(TNG_FAILURE);
8281 chain = residue->chain;
8282 molecule = chain->molecule;
8284 if(index + residue->atoms_offset >= molecule->n_atoms)
8287 return(TNG_FAILURE);
8290 *atom = &molecule->atoms[residue->atoms_offset + index];
8291 return(TNG_SUCCESS);
8294 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8295 (tng_trajectory_t tng_data,
8296 tng_residue_t residue,
8297 const char *atom_name,
8298 const char *atom_type,
8301 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8302 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8303 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8305 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
8306 residue->chain->molecule->n_atoms + 1,
8310 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
8311 (tng_trajectory_t tng_data,
8312 tng_residue_t residue,
8313 const char *atom_name,
8314 const char *atom_type,
8319 tng_atom_t new_atoms;
8320 tng_molecule_t molecule = residue->chain->molecule;
8321 tng_function_status stat = TNG_SUCCESS;
8323 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8324 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8325 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8327 if(!residue->n_atoms)
8329 residue->atoms_offset = molecule->n_atoms;
8332 new_atoms = realloc(molecule->atoms,
8333 sizeof(struct tng_atom) *
8334 (molecule->n_atoms + 1));
8338 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8339 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
8340 __FILE__, __LINE__);
8341 free(molecule->atoms);
8342 molecule->atoms = 0;
8343 return(TNG_CRITICAL);
8346 molecule->atoms = new_atoms;
8348 *atom = &new_atoms[molecule->n_atoms];
8350 tng_atom_init(*atom);
8351 tng_atom_name_set(tng_data, *atom, atom_name);
8352 tng_atom_type_set(tng_data, *atom, atom_type);
8354 (*atom)->residue = residue;
8356 for(i = molecule->n_atoms; i--;)
8358 if(molecule->atoms[i].id == id)
8361 fprintf(stderr, "TNG library: Atom ID %"PRId64" already in use. %s: %d\n", id, __FILE__, __LINE__);
8367 molecule->n_atoms++;
8374 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8375 tng_molecule_t *molecule_p)
8377 *molecule_p = malloc(sizeof(struct tng_molecule));
8380 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
8381 sizeof(struct tng_molecule), __FILE__, __LINE__);
8382 return(TNG_CRITICAL);
8385 tng_molecule_init(tng_data, *molecule_p);
8387 return(TNG_SUCCESS);
8390 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8391 tng_molecule_t *molecule_p)
8395 return(TNG_SUCCESS);
8398 tng_molecule_destroy(tng_data, *molecule_p);
8403 return(TNG_SUCCESS);
8406 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8407 tng_molecule_t molecule)
8410 molecule->quaternary_str = 1;
8412 molecule->n_chains = 0;
8413 molecule->chains = 0;
8414 molecule->n_residues = 0;
8415 molecule->residues = 0;
8416 molecule->n_atoms = 0;
8417 molecule->atoms = 0;
8418 molecule->n_bonds = 0;
8419 molecule->bonds = 0;
8421 return(TNG_SUCCESS);
8424 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8425 tng_molecule_t molecule)
8432 free(molecule->name);
8436 if(molecule->chains)
8438 for(i = molecule->n_chains; i--;)
8440 if(molecule->chains[i].name)
8442 free(molecule->chains[i].name);
8443 molecule->chains[i].name = 0;
8446 free(molecule->chains);
8447 molecule->chains = 0;
8449 molecule->n_chains = 0;
8451 if(molecule->residues)
8453 for(i = molecule->n_residues; i--;)
8455 if(molecule->residues[i].name)
8457 free(molecule->residues[i].name);
8458 molecule->residues[i].name = 0;
8461 free(molecule->residues);
8462 molecule->residues = 0;
8464 molecule->n_residues = 0;
8468 for(i = molecule->n_atoms; i--;)
8470 tng_atom_destroy(&molecule->atoms[i]);
8472 free(molecule->atoms);
8473 molecule->atoms = 0;
8475 molecule->n_atoms = 0;
8479 free(molecule->bonds);
8480 molecule->bonds = 0;
8482 molecule->n_bonds = 0;
8484 return(TNG_SUCCESS);
8487 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8488 (const tng_trajectory_t tng_data,
8493 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8495 tng_bool found = TNG_FALSE;
8497 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8498 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8500 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8502 if(!molecule_cnt_list)
8504 return(TNG_FAILURE);
8507 for(i = 0; i < tng_data->n_molecules; i++)
8509 mol = &tng_data->molecules[i];
8510 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8512 cnt += mol->n_atoms * molecule_cnt_list[i];
8520 return(TNG_FAILURE);
8523 strncpy(name, mol->name, max_len - 1);
8524 name[max_len - 1] = 0;
8526 if(strlen(mol->name) > (unsigned int)max_len - 1)
8528 return(TNG_FAILURE);
8530 return(TNG_SUCCESS);
8533 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8534 (const tng_trajectory_t tng_data,
8538 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8540 tng_bool found = TNG_FALSE;
8542 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8543 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8545 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8547 if(!molecule_cnt_list)
8549 return(TNG_FAILURE);
8552 for(i = 0; i < tng_data->n_molecules; i++)
8554 mol = &tng_data->molecules[i];
8555 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8557 cnt += mol->n_atoms * molecule_cnt_list[i];
8565 return(TNG_FAILURE);
8570 return(TNG_SUCCESS);
8573 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8574 (const tng_trajectory_t tng_data,
8576 int64_t **from_atoms,
8579 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8580 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8584 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8585 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8586 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8587 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8589 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8591 if(!molecule_cnt_list)
8593 return(TNG_FAILURE);
8597 /* First count the total number of bonds to allocate memory */
8598 for(i = 0; i < tng_data->n_molecules; i++)
8600 mol = &tng_data->molecules[i];
8601 mol_cnt = molecule_cnt_list[i];
8602 *n_bonds += mol_cnt * mol->n_bonds;
8606 return(TNG_SUCCESS);
8609 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8612 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8613 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8614 return(TNG_CRITICAL);
8616 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8619 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8620 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8623 return(TNG_CRITICAL);
8627 for(i = 0; i < tng_data->n_molecules; i++)
8629 mol = &tng_data->molecules[i];
8630 mol_cnt = molecule_cnt_list[i];
8631 for(j = 0; j < mol_cnt; j++)
8633 for(k = 0; k < mol->n_bonds; k++)
8635 bond = &mol->bonds[k];
8636 from_atom = atom_cnt + bond->from_atom_id;
8637 to_atom = atom_cnt + bond->to_atom_id;
8638 (*from_atoms)[cnt] = from_atom;
8639 (*to_atoms)[cnt++] = to_atom;
8641 atom_cnt += mol->n_atoms;
8645 return(TNG_SUCCESS);
8648 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8649 (const tng_trajectory_t tng_data,
8654 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8657 tng_bool found = TNG_FALSE;
8659 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8660 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8662 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8664 if(!molecule_cnt_list)
8666 return(TNG_FAILURE);
8669 for(i = 0; i < tng_data->n_molecules; i++)
8671 mol = &tng_data->molecules[i];
8672 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8674 cnt += mol->n_atoms * molecule_cnt_list[i];
8677 atom = &mol->atoms[nr % mol->n_atoms];
8683 return(TNG_FAILURE);
8685 if(!atom->residue || !atom->residue->chain)
8687 return(TNG_FAILURE);
8690 strncpy(name, atom->residue->chain->name, max_len - 1);
8691 name[max_len - 1] = 0;
8693 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8695 return(TNG_FAILURE);
8697 return(TNG_SUCCESS);
8700 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8701 (const tng_trajectory_t tng_data,
8706 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8709 tng_bool found = TNG_FALSE;
8711 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8712 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8714 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8716 if(!molecule_cnt_list)
8718 return(TNG_FAILURE);
8721 for(i = 0; i < tng_data->n_molecules; i++)
8723 mol = &tng_data->molecules[i];
8724 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8726 cnt += mol->n_atoms * molecule_cnt_list[i];
8729 atom = &mol->atoms[nr % mol->n_atoms];
8735 return(TNG_FAILURE);
8739 return(TNG_FAILURE);
8742 strncpy(name, atom->residue->name, max_len - 1);
8743 name[max_len - 1] = 0;
8745 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8747 return(TNG_FAILURE);
8749 return(TNG_SUCCESS);
8752 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8753 (const tng_trajectory_t tng_data,
8757 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8760 tng_bool found = TNG_FALSE;
8762 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8763 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8765 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8767 if(!molecule_cnt_list)
8769 return(TNG_FAILURE);
8772 for(i = 0; i < tng_data->n_molecules; i++)
8774 mol = &tng_data->molecules[i];
8775 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8777 cnt += mol->n_atoms * molecule_cnt_list[i];
8780 atom = &mol->atoms[nr % mol->n_atoms];
8786 return(TNG_FAILURE);
8790 return(TNG_FAILURE);
8793 *id = atom->residue->id;
8795 return(TNG_SUCCESS);
8798 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8799 (const tng_trajectory_t tng_data,
8803 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8806 tng_bool found = TNG_FALSE;
8808 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8809 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8811 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8813 if(!molecule_cnt_list)
8815 return(TNG_FAILURE);
8818 for(i = 0; i < tng_data->n_molecules; i++)
8820 mol = &tng_data->molecules[i];
8821 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8823 cnt += mol->n_atoms * molecule_cnt_list[i];
8824 offset += mol->n_residues * molecule_cnt_list[i];
8827 atom = &mol->atoms[nr % mol->n_atoms];
8833 return(TNG_FAILURE);
8837 return(TNG_FAILURE);
8840 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8842 *id = atom->residue->id + offset;
8844 return(TNG_SUCCESS);
8847 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8848 (const tng_trajectory_t tng_data,
8853 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8856 tng_bool found = TNG_FALSE;
8858 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8859 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8861 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8863 if(!molecule_cnt_list)
8865 return(TNG_FAILURE);
8868 for(i = 0; i < tng_data->n_molecules; i++)
8870 mol = &tng_data->molecules[i];
8871 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8873 cnt += mol->n_atoms * molecule_cnt_list[i];
8876 atom = &mol->atoms[nr % mol->n_atoms];
8882 return(TNG_FAILURE);
8885 strncpy(name, atom->name, max_len - 1);
8886 name[max_len - 1] = 0;
8888 if(strlen(atom->name) > (unsigned int)max_len - 1)
8890 return(TNG_FAILURE);
8892 return(TNG_SUCCESS);
8895 tng_function_status tng_atom_type_of_particle_nr_get
8896 (const tng_trajectory_t tng_data,
8901 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8904 tng_bool found = TNG_FALSE;
8906 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8907 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8909 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8911 if(!molecule_cnt_list)
8913 return(TNG_FAILURE);
8916 for(i = 0; i < tng_data->n_molecules; i++)
8918 mol = &tng_data->molecules[i];
8919 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8921 cnt += mol->n_atoms * molecule_cnt_list[i];
8924 atom = &mol->atoms[nr % mol->n_atoms];
8930 return(TNG_FAILURE);
8933 strncpy(type, atom->atom_type, max_len - 1);
8934 type[max_len - 1] = 0;
8936 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8938 return(TNG_FAILURE);
8940 return(TNG_SUCCESS);
8943 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8944 (tng_trajectory_t tng_data,
8945 const int64_t num_first_particle,
8946 const int64_t n_particles,
8947 const int64_t *mapping_table)
8950 tng_particle_mapping_t mapping;
8951 tng_trajectory_frame_set_t frame_set;
8953 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8955 frame_set = &tng_data->current_trajectory_frame_set;
8957 /* Sanity check of the particle ranges. Split into multiple if
8958 * statements for improved readability */
8959 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8961 mapping = &frame_set->mappings[i];
8962 if(num_first_particle >= mapping->num_first_particle &&
8963 num_first_particle < mapping->num_first_particle +
8964 mapping->n_particles)
8966 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8967 return(TNG_FAILURE);
8969 if(num_first_particle + n_particles >=
8970 mapping->num_first_particle &&
8971 num_first_particle + n_particles <
8972 mapping->num_first_particle + mapping->n_particles)
8974 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8975 return(TNG_FAILURE);
8977 if(mapping->num_first_particle >= num_first_particle &&
8978 mapping->num_first_particle < num_first_particle +
8981 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8982 return(TNG_FAILURE);
8984 if(mapping->num_first_particle + mapping->n_particles >
8985 num_first_particle &&
8986 mapping->num_first_particle + mapping->n_particles <
8987 num_first_particle + n_particles)
8989 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8990 return(TNG_FAILURE);
8994 frame_set->n_mapping_blocks++;
8996 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
8997 frame_set->n_mapping_blocks);
9001 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9002 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9003 __FILE__, __LINE__);
9004 free(frame_set->mappings);
9005 frame_set->mappings = 0;
9006 return(TNG_CRITICAL);
9008 frame_set->mappings = mapping;
9010 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9011 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9013 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9014 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9016 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9017 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9018 return(TNG_CRITICAL);
9021 for(i=0; i<n_particles; i++)
9023 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9026 return(TNG_SUCCESS);
9029 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9031 tng_trajectory_frame_set_t frame_set;
9032 tng_particle_mapping_t mapping;
9035 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9037 frame_set = &tng_data->current_trajectory_frame_set;
9039 if(frame_set->n_mapping_blocks && frame_set->mappings)
9041 for(i = frame_set->n_mapping_blocks; i--;)
9043 mapping = &frame_set->mappings[i];
9044 if(mapping->real_particle_numbers)
9046 free(mapping->real_particle_numbers);
9047 mapping->real_particle_numbers = 0;
9050 free(frame_set->mappings);
9051 frame_set->mappings = 0;
9052 frame_set->n_mapping_blocks = 0;
9055 return(TNG_SUCCESS);
9058 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9061 tng_trajectory_frame_set_t frame_set;
9062 tng_trajectory_t tng_data;
9064 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9067 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9068 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9069 return(TNG_CRITICAL);
9072 tng_data = *tng_data_p;
9074 frame_set = &tng_data->current_trajectory_frame_set;
9076 tng_data->input_file_path = 0;
9077 tng_data->input_file = 0;
9078 tng_data->input_file_len = 0;
9079 tng_data->output_file_path = 0;
9080 tng_data->output_file = 0;
9082 tng_data->first_program_name = 0;
9083 tng_data->first_user_name = 0;
9084 tng_data->first_computer_name = 0;
9085 tng_data->first_pgp_signature = 0;
9086 tng_data->last_program_name = 0;
9087 tng_data->last_user_name = 0;
9088 tng_data->last_computer_name = 0;
9089 tng_data->last_pgp_signature = 0;
9090 tng_data->forcefield_name = 0;
9095 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9099 tng_data->time = seconds;
9102 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9103 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9104 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9105 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9106 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9107 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9108 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9109 tng_data->frame_set_n_frames = 100;
9110 tng_data->n_trajectory_frame_sets = 0;
9111 tng_data->n_trajectory_blocks = 0;
9112 tng_data->medium_stride_length = 100;
9113 tng_data->long_stride_length = 10000;
9115 tng_data->time_per_frame = -1;
9117 tng_data->n_particle_data_blocks = 0;
9118 tng_data->n_data_blocks = 0;
9120 tng_data->non_tr_particle_data = 0;
9121 tng_data->non_tr_data = 0;
9123 tng_data->compress_algo_pos = 0;
9124 tng_data->compress_algo_vel = 0;
9125 tng_data->compression_precision = 1000;
9126 tng_data->distance_unit_exponential = -9;
9128 frame_set->first_frame = -1;
9129 frame_set->n_mapping_blocks = 0;
9130 frame_set->mappings = 0;
9131 frame_set->molecule_cnt_list = 0;
9133 frame_set->n_particle_data_blocks = 0;
9134 frame_set->n_data_blocks = 0;
9136 frame_set->tr_particle_data = 0;
9137 frame_set->tr_data = 0;
9139 frame_set->n_written_frames = 0;
9140 frame_set->n_unwritten_frames = 0;
9142 frame_set->next_frame_set_file_pos = -1;
9143 frame_set->prev_frame_set_file_pos = -1;
9144 frame_set->medium_stride_next_frame_set_file_pos = -1;
9145 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9146 frame_set->long_stride_next_frame_set_file_pos = -1;
9147 frame_set->long_stride_prev_frame_set_file_pos = -1;
9149 frame_set->first_frame_time = -1;
9151 tng_data->n_molecules = 0;
9152 tng_data->molecules = 0;
9153 tng_data->molecule_cnt_list = 0;
9154 tng_data->n_particles = 0;
9157 /* Check the endianness of the computer */
9158 static int32_t endianness_32 = 0x01234567;
9160 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9162 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9166 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9168 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9173 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9175 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9179 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9180 /* 0x0123456789ABCDEF */
9181 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9183 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9186 /* 0xEFCDAB8967452301 */
9187 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9189 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9192 /* 0x89ABCDEF01234567 */
9193 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9195 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9198 /* 0x45670123CDEF89AB */
9199 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9201 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9204 /* 0x23016745AB89EFCD */
9205 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9207 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9211 /* By default do not swap the byte order, i.e. keep the byte order of the
9212 * architecture. The input file endianness will be set when reading the
9213 * header. The output endianness can be changed - before the file is
9215 tng_data->input_endianness_swap_func_32 = 0;
9216 tng_data->input_endianness_swap_func_64 = 0;
9217 tng_data->output_endianness_swap_func_32 = 0;
9218 tng_data->output_endianness_swap_func_64 = 0;
9220 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9221 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9222 tng_data->current_trajectory_frame_set.n_frames = 0;
9224 return(TNG_SUCCESS);
9227 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9230 int64_t n_particles, n_values_per_frame;
9231 tng_trajectory_t tng_data = *tng_data_p;
9232 tng_trajectory_frame_set_t frame_set;
9236 return(TNG_SUCCESS);
9239 frame_set = &tng_data->current_trajectory_frame_set;
9241 if(tng_data->input_file_path)
9243 free(tng_data->input_file_path);
9244 tng_data->input_file_path = 0;
9247 if(tng_data->input_file)
9249 fclose(tng_data->input_file);
9250 tng_data->input_file = 0;
9253 if(tng_data->output_file_path)
9255 free(tng_data->output_file_path);
9256 tng_data->output_file_path = 0;
9259 if(tng_data->output_file)
9261 /* FIXME: Do not always write the hash */
9262 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9263 fclose(tng_data->output_file);
9264 tng_data->output_file = 0;
9267 if(tng_data->first_program_name)
9269 free(tng_data->first_program_name);
9270 tng_data->first_program_name = 0;
9273 if(tng_data->last_program_name)
9275 free(tng_data->last_program_name);
9276 tng_data->last_program_name = 0;
9279 if(tng_data->first_user_name)
9281 free(tng_data->first_user_name);
9282 tng_data->first_user_name = 0;
9285 if(tng_data->last_user_name)
9287 free(tng_data->last_user_name);
9288 tng_data->last_user_name = 0;
9291 if(tng_data->first_computer_name)
9293 free(tng_data->first_computer_name);
9294 tng_data->first_computer_name = 0;
9297 if(tng_data->last_computer_name)
9299 free(tng_data->last_computer_name);
9300 tng_data->last_computer_name = 0;
9303 if(tng_data->first_pgp_signature)
9305 free(tng_data->first_pgp_signature);
9306 tng_data->first_pgp_signature = 0;
9309 if(tng_data->last_pgp_signature)
9311 free(tng_data->last_pgp_signature);
9312 tng_data->last_pgp_signature = 0;
9315 if(tng_data->forcefield_name)
9317 free(tng_data->forcefield_name);
9318 tng_data->forcefield_name = 0;
9321 tng_frame_set_particle_mapping_free(tng_data);
9323 if(frame_set->molecule_cnt_list)
9325 free(frame_set->molecule_cnt_list);
9326 frame_set->molecule_cnt_list = 0;
9329 if(tng_data->var_num_atoms_flag)
9331 n_particles = frame_set->n_particles;
9335 n_particles = tng_data->n_particles;
9338 if(tng_data->non_tr_particle_data)
9340 for(i = tng_data->n_particle_data_blocks; i--; )
9342 if(tng_data->non_tr_particle_data[i].values)
9344 free(tng_data->non_tr_particle_data[i].values);
9345 tng_data->non_tr_particle_data[i].values = 0;
9348 if(tng_data->non_tr_particle_data[i].strings)
9350 n_values_per_frame = tng_data->non_tr_particle_data[i].
9352 if(tng_data->non_tr_particle_data[i].strings[0])
9354 for(j = n_particles; j--;)
9356 if(tng_data->non_tr_particle_data[i].strings[0][j])
9358 for(k = n_values_per_frame; k--;)
9360 if(tng_data->non_tr_particle_data[i].
9363 free(tng_data->non_tr_particle_data[i].
9365 tng_data->non_tr_particle_data[i].
9366 strings[0][j][k] = 0;
9369 free(tng_data->non_tr_particle_data[i].
9371 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9374 free(tng_data->non_tr_particle_data[i].strings[0]);
9375 tng_data->non_tr_particle_data[i].strings[0] = 0;
9377 free(tng_data->non_tr_particle_data[i].strings);
9378 tng_data->non_tr_particle_data[i].strings = 0;
9381 if(tng_data->non_tr_particle_data[i].block_name)
9383 free(tng_data->non_tr_particle_data[i].block_name);
9384 tng_data->non_tr_particle_data[i].block_name = 0;
9387 free(tng_data->non_tr_particle_data);
9388 tng_data->non_tr_particle_data = 0;
9391 if(tng_data->non_tr_data)
9393 for(i = tng_data->n_data_blocks; i--;)
9395 if(tng_data->non_tr_data[i].values)
9397 free(tng_data->non_tr_data[i].values);
9398 tng_data->non_tr_data[i].values = 0;
9401 if(tng_data->non_tr_data[i].strings)
9403 n_values_per_frame = tng_data->non_tr_data[i].
9405 if(tng_data->non_tr_data[i].strings[0])
9407 for(j = n_values_per_frame; j--;)
9409 if(tng_data->non_tr_data[i].strings[0][j])
9411 free(tng_data->non_tr_data[i].strings[0][j]);
9412 tng_data->non_tr_data[i].strings[0][j] = 0;
9415 free(tng_data->non_tr_data[i].strings[0]);
9416 tng_data->non_tr_data[i].strings[0] = 0;
9418 free(tng_data->non_tr_data[i].strings);
9419 tng_data->non_tr_data[i].strings = 0;
9422 if(tng_data->non_tr_data[i].block_name)
9424 free(tng_data->non_tr_data[i].block_name);
9425 tng_data->non_tr_data[i].block_name = 0;
9428 free(tng_data->non_tr_data);
9429 tng_data->non_tr_data = 0;
9432 tng_data->n_particle_data_blocks = 0;
9433 tng_data->n_data_blocks = 0;
9435 if(tng_data->compress_algo_pos)
9437 free(tng_data->compress_algo_pos);
9438 tng_data->compress_algo_pos = 0;
9440 if(tng_data->compress_algo_vel)
9442 free(tng_data->compress_algo_vel);
9443 tng_data->compress_algo_vel = 0;
9446 if(frame_set->tr_particle_data)
9448 for(i = frame_set->n_particle_data_blocks; i--; )
9450 if(frame_set->tr_particle_data[i].values)
9452 free(frame_set->tr_particle_data[i].values);
9453 frame_set->tr_particle_data[i].values = 0;
9456 if(frame_set->tr_particle_data[i].strings)
9458 n_values_per_frame = frame_set->tr_particle_data[i].
9460 for(j = frame_set->tr_particle_data[i].n_frames; j--;)
9462 if(frame_set->tr_particle_data[i].strings[j])
9464 for(k = n_particles; k--;)
9466 if(frame_set->tr_particle_data[i].
9469 for(l = n_values_per_frame; l--;)
9471 if(frame_set->tr_particle_data[i].
9474 free(frame_set->tr_particle_data[i].
9476 frame_set->tr_particle_data[i].
9477 strings[j][k][l] = 0;
9480 free(frame_set->tr_particle_data[i].
9482 frame_set->tr_particle_data[i].
9486 free(frame_set->tr_particle_data[i].strings[j]);
9487 frame_set->tr_particle_data[i].strings[j] = 0;
9490 free(frame_set->tr_particle_data[i].strings);
9491 frame_set->tr_particle_data[i].strings = 0;
9494 if(frame_set->tr_particle_data[i].block_name)
9496 free(frame_set->tr_particle_data[i].block_name);
9497 frame_set->tr_particle_data[i].block_name = 0;
9500 free(frame_set->tr_particle_data);
9501 frame_set->tr_particle_data = 0;
9504 if(frame_set->tr_data)
9506 for(i = frame_set->n_data_blocks; i--;)
9508 if(frame_set->tr_data[i].values)
9510 free(frame_set->tr_data[i].values);
9511 frame_set->tr_data[i].values = 0;
9514 if(frame_set->tr_data[i].strings)
9516 n_values_per_frame = frame_set->tr_data[i].
9518 for(j = frame_set->tr_data[i].n_frames; j--;)
9520 if(frame_set->tr_data[i].strings[j])
9522 for(k = n_values_per_frame; k--;)
9524 if(frame_set->tr_data[i].strings[j][k])
9526 free(frame_set->tr_data[i].strings[j][k]);
9527 frame_set->tr_data[i].strings[j][k] = 0;
9530 free(frame_set->tr_data[i].strings[j]);
9531 frame_set->tr_data[i].strings[j] = 0;
9534 free(frame_set->tr_data[i].strings);
9535 frame_set->tr_data[i].strings = 0;
9538 if(frame_set->tr_data[i].block_name)
9540 free(frame_set->tr_data[i].block_name);
9541 frame_set->tr_data[i].block_name = 0;
9544 free(frame_set->tr_data);
9545 frame_set->tr_data = 0;
9548 frame_set->n_particle_data_blocks = 0;
9549 frame_set->n_data_blocks = 0;
9551 if(tng_data->molecules)
9553 for(i=tng_data->n_molecules; i--;)
9555 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9557 free(tng_data->molecules);
9558 tng_data->molecules = 0;
9559 tng_data->n_molecules = 0;
9561 if(tng_data->molecule_cnt_list)
9563 free(tng_data->molecule_cnt_list);
9564 tng_data->molecule_cnt_list = 0;
9570 return(TNG_SUCCESS);
9573 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
9574 tng_trajectory_t *dest_p)
9576 tng_trajectory_frame_set_t frame_set;
9577 tng_trajectory_t dest;
9579 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9581 *dest_p = malloc(sizeof(struct tng_trajectory));
9584 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9585 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9586 return(TNG_CRITICAL);
9591 frame_set = &dest->current_trajectory_frame_set;
9593 strcpy(dest->input_file_path, src->input_file_path);
9594 dest->input_file = 0;
9595 dest->input_file_len = src->input_file_len;
9596 strcpy(dest->output_file_path, src->output_file_path);
9597 dest->output_file = 0;
9599 dest->first_program_name = 0;
9600 dest->first_user_name = 0;
9601 dest->first_computer_name = 0;
9602 dest->first_pgp_signature = 0;
9603 dest->last_program_name = 0;
9604 dest->last_user_name = 0;
9605 dest->last_computer_name = 0;
9606 dest->last_pgp_signature = 0;
9607 dest->forcefield_name = 0;
9609 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9610 dest->first_trajectory_frame_set_input_file_pos =
9611 src->first_trajectory_frame_set_input_file_pos;
9612 dest->last_trajectory_frame_set_input_file_pos =
9613 src->last_trajectory_frame_set_input_file_pos;
9614 dest->current_trajectory_frame_set_input_file_pos =
9615 src->current_trajectory_frame_set_input_file_pos;
9616 dest->first_trajectory_frame_set_output_file_pos =
9617 src->first_trajectory_frame_set_output_file_pos;
9618 dest->last_trajectory_frame_set_output_file_pos =
9619 src->last_trajectory_frame_set_output_file_pos;
9620 dest->current_trajectory_frame_set_output_file_pos =
9621 src->current_trajectory_frame_set_output_file_pos;
9622 dest->frame_set_n_frames = src->frame_set_n_frames;
9623 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9624 dest->n_trajectory_blocks = src->n_trajectory_blocks;
9625 dest->medium_stride_length = src->medium_stride_length;
9626 dest->long_stride_length = src->long_stride_length;
9628 dest->time_per_frame = src->time_per_frame;
9630 /* Currently the non trajectory data blocks are not copied since it
9631 * can lead to problems when freeing memory in a parallel block. */
9632 dest->n_particle_data_blocks = 0;
9633 dest->n_data_blocks = 0;
9634 dest->non_tr_particle_data = 0;
9635 dest->non_tr_data = 0;
9637 dest->compress_algo_pos = 0;
9638 dest->compress_algo_vel = 0;
9639 dest->distance_unit_exponential = -9;
9640 dest->compression_precision = 1000;
9642 frame_set->n_mapping_blocks = 0;
9643 frame_set->mappings = 0;
9644 frame_set->molecule_cnt_list = 0;
9646 frame_set->n_particle_data_blocks = 0;
9647 frame_set->n_data_blocks = 0;
9649 frame_set->tr_particle_data = 0;
9650 frame_set->tr_data = 0;
9652 frame_set->next_frame_set_file_pos = -1;
9653 frame_set->prev_frame_set_file_pos = -1;
9654 frame_set->medium_stride_next_frame_set_file_pos = -1;
9655 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9656 frame_set->long_stride_next_frame_set_file_pos = -1;
9657 frame_set->long_stride_prev_frame_set_file_pos = -1;
9658 frame_set->first_frame = -1;
9660 dest->n_molecules = 0;
9661 dest->molecules = 0;
9662 dest->molecule_cnt_list = 0;
9663 dest->n_particles = src->n_particles;
9665 dest->endianness_32 = src->endianness_32;
9666 dest->endianness_64 = src->endianness_64;
9667 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9668 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9669 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9670 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9672 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9673 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9674 dest->current_trajectory_frame_set.n_frames = 0;
9676 return(TNG_SUCCESS);
9679 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
9680 char *file_name, const int max_len)
9682 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9683 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9685 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9686 file_name[max_len - 1] = 0;
9688 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9690 return(TNG_FAILURE);
9692 return(TNG_SUCCESS);
9695 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
9696 const char *file_name)
9701 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9702 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9705 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9708 return(TNG_SUCCESS);
9711 if(tng_data->input_file)
9713 fclose(tng_data->input_file);
9716 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
9717 temp = realloc(tng_data->input_file_path, len);
9720 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9721 __FILE__, __LINE__);
9722 free(tng_data->input_file_path);
9723 tng_data->input_file_path = 0;
9724 return(TNG_CRITICAL);
9726 tng_data->input_file_path = temp;
9728 strncpy(tng_data->input_file_path, file_name, len);
9730 return(tng_input_file_init(tng_data));
9733 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
9734 char *file_name, const int max_len)
9736 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9737 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9739 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9740 file_name[max_len - 1] = 0;
9742 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9744 return(TNG_FAILURE);
9746 return(TNG_SUCCESS);
9749 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
9750 const char *file_name)
9755 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9756 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9758 if(tng_data->output_file_path &&
9759 strcmp(tng_data->output_file_path, file_name) == 0)
9761 return(TNG_SUCCESS);
9764 if(tng_data->output_file)
9766 fclose(tng_data->output_file);
9769 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
9770 temp = realloc(tng_data->output_file_path, len);
9773 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9774 __FILE__, __LINE__);
9775 free(tng_data->output_file_path);
9776 tng_data->output_file_path = 0;
9777 return(TNG_CRITICAL);
9779 tng_data->output_file_path = temp;
9781 strncpy(tng_data->output_file_path, file_name, len);
9783 return(tng_output_file_init(tng_data));
9786 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9787 (tng_trajectory_t tng_data,
9788 const char *file_name)
9793 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9794 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9796 if(tng_data->output_file_path &&
9797 strcmp(tng_data->output_file_path, file_name) == 0)
9799 return(TNG_SUCCESS);
9802 if(tng_data->output_file)
9804 fclose(tng_data->output_file);
9807 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
9808 temp = realloc(tng_data->output_file_path, len);
9811 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9812 __FILE__, __LINE__);
9813 free(tng_data->output_file_path);
9814 tng_data->output_file_path = 0;
9815 return(TNG_CRITICAL);
9817 tng_data->output_file_path = temp;
9819 strncpy(tng_data->output_file_path, file_name, len);
9821 tng_data->output_file = fopen(tng_data->output_file_path, "r+");
9822 if(!tng_data->output_file)
9824 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9825 tng_data->output_file_path, __FILE__, __LINE__);
9826 return(TNG_CRITICAL);
9829 return(TNG_SUCCESS);
9832 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9833 (tng_trajectory_t tng_data, tng_file_endianness *endianness)
9835 tng_endianness_32 end_32;
9836 tng_endianness_64 end_64;
9838 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9839 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9841 if(tng_data->output_endianness_swap_func_32)
9843 /* If other endianness variants are added they must be added here as well */
9844 if(tng_data->output_endianness_swap_func_32 ==
9845 &tng_swap_byte_order_big_endian_32)
9847 end_32 = TNG_BIG_ENDIAN_32;
9849 else if(tng_data->output_endianness_swap_func_32 ==
9850 &tng_swap_byte_order_little_endian_32)
9852 end_32 = TNG_LITTLE_ENDIAN_32;
9856 return(TNG_FAILURE);
9861 end_32 = (tng_endianness_32)tng_data->endianness_32;
9864 if(tng_data->output_endianness_swap_func_64)
9866 /* If other endianness variants are added they must be added here as well */
9867 if(tng_data->output_endianness_swap_func_64 ==
9868 &tng_swap_byte_order_big_endian_64)
9870 end_64 = TNG_BIG_ENDIAN_64;
9872 else if(tng_data->output_endianness_swap_func_64 ==
9873 &tng_swap_byte_order_little_endian_64)
9875 end_64 = TNG_LITTLE_ENDIAN_64;
9879 return(TNG_FAILURE);
9884 end_64 = (tng_endianness_64)tng_data->endianness_64;
9887 if((int)end_32 != (int)end_64)
9889 return(TNG_FAILURE);
9892 if(end_32 == TNG_LITTLE_ENDIAN_32)
9894 *endianness = TNG_LITTLE_ENDIAN;
9897 else if(end_32 == TNG_BIG_ENDIAN_32)
9899 *endianness = TNG_BIG_ENDIAN;
9903 return(TNG_FAILURE);
9906 return(TNG_SUCCESS);
9909 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9910 (tng_trajectory_t tng_data,
9911 const tng_file_endianness endianness)
9913 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9915 /* Tne endianness cannot be changed if the data has already been written
9916 * to the output file. */
9917 if(ftell(tng_data->output_file) > 0)
9919 return(TNG_FAILURE);
9922 if(endianness == TNG_BIG_ENDIAN)
9924 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9926 tng_data->output_endianness_swap_func_32 = 0;
9930 tng_data->output_endianness_swap_func_32 =
9931 &tng_swap_byte_order_big_endian_32;
9933 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
9935 tng_data->output_endianness_swap_func_64 = 0;
9939 tng_data->output_endianness_swap_func_64 =
9940 &tng_swap_byte_order_big_endian_64;
9942 return(TNG_SUCCESS);
9944 else if(endianness == TNG_LITTLE_ENDIAN)
9946 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
9948 tng_data->output_endianness_swap_func_32 = 0;
9952 tng_data->output_endianness_swap_func_32 =
9953 &tng_swap_byte_order_little_endian_32;
9955 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
9957 tng_data->output_endianness_swap_func_64 = 0;
9961 tng_data->output_endianness_swap_func_64 =
9962 &tng_swap_byte_order_little_endian_64;
9964 return(TNG_SUCCESS);
9967 /* If the specified endianness is neither big nor little endian return a
9969 return(TNG_FAILURE);
9972 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9973 (const tng_trajectory_t tng_data,
9974 char *name, const int max_len)
9976 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9977 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9979 strncpy(name, tng_data->first_program_name, max_len - 1);
9980 name[max_len - 1] = 0;
9982 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
9984 return(TNG_FAILURE);
9986 return(TNG_SUCCESS);
9989 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
9990 const char *new_name)
9994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9995 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9997 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
9999 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10001 free(tng_data->first_program_name);
10002 tng_data->first_program_name = 0;
10004 if(!tng_data->first_program_name)
10006 tng_data->first_program_name = malloc(len);
10007 if(!tng_data->first_program_name)
10009 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10010 __FILE__, __LINE__);
10011 return(TNG_CRITICAL);
10015 strncpy(tng_data->first_program_name, new_name, len);
10017 return(TNG_SUCCESS);
10020 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10021 (const tng_trajectory_t tng_data,
10022 char *name, const int max_len)
10024 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10025 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10027 strncpy(name, tng_data->last_program_name, max_len - 1);
10028 name[max_len - 1] = 0;
10030 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10032 return(TNG_FAILURE);
10034 return(TNG_SUCCESS);
10037 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10038 (tng_trajectory_t tng_data,
10039 const char *new_name)
10043 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10044 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10046 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10048 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10050 free(tng_data->last_program_name);
10051 tng_data->last_program_name = 0;
10053 if(!tng_data->last_program_name)
10055 tng_data->last_program_name = malloc(len);
10056 if(!tng_data->last_program_name)
10058 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10059 __FILE__, __LINE__);
10060 return(TNG_CRITICAL);
10064 strncpy(tng_data->last_program_name, new_name, len);
10066 return(TNG_SUCCESS);
10069 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10070 (const tng_trajectory_t tng_data,
10071 char *name, const int max_len)
10073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10074 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10076 strncpy(name, tng_data->first_user_name, max_len - 1);
10077 name[max_len - 1] = 0;
10079 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10081 return(TNG_FAILURE);
10083 return(TNG_SUCCESS);
10086 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10087 (tng_trajectory_t tng_data,
10088 const char *new_name)
10092 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10093 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10095 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10097 /* If the currently stored string length is not enough to store the new
10098 * string it is freed and reallocated. */
10099 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10101 free(tng_data->first_user_name);
10102 tng_data->first_user_name = 0;
10104 if(!tng_data->first_user_name)
10106 tng_data->first_user_name = malloc(len);
10107 if(!tng_data->first_user_name)
10109 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10110 __FILE__, __LINE__);
10111 return(TNG_CRITICAL);
10115 strncpy(tng_data->first_user_name, new_name, len);
10117 return(TNG_SUCCESS);
10120 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10121 (const tng_trajectory_t tng_data,
10122 char *name, const int max_len)
10124 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10125 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10127 strncpy(name, tng_data->last_user_name, max_len - 1);
10128 name[max_len - 1] = 0;
10130 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10132 return(TNG_FAILURE);
10134 return(TNG_SUCCESS);
10137 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10138 (tng_trajectory_t tng_data,
10139 const char *new_name)
10143 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10144 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10146 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10148 /* If the currently stored string length is not enough to store the new
10149 * string it is freed and reallocated. */
10150 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10152 free(tng_data->last_user_name);
10153 tng_data->last_user_name = 0;
10155 if(!tng_data->last_user_name)
10157 tng_data->last_user_name = malloc(len);
10158 if(!tng_data->last_user_name)
10160 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10161 __FILE__, __LINE__);
10162 return(TNG_CRITICAL);
10166 strncpy(tng_data->last_user_name, new_name, len);
10168 return(TNG_SUCCESS);
10171 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10172 (const tng_trajectory_t tng_data,
10173 char *name, const int max_len)
10175 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10176 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10178 strncpy(name, tng_data->first_computer_name, max_len - 1);
10179 name[max_len - 1] = 0;
10181 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10183 return(TNG_FAILURE);
10185 return(TNG_SUCCESS);
10188 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10189 (tng_trajectory_t tng_data,
10190 const char *new_name)
10194 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10195 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10197 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10199 /* If the currently stored string length is not enough to store the new
10200 * string it is freed and reallocated. */
10201 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10203 free(tng_data->first_computer_name);
10204 tng_data->first_computer_name = 0;
10206 if(!tng_data->first_computer_name)
10208 tng_data->first_computer_name = malloc(len);
10209 if(!tng_data->first_computer_name)
10211 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10212 __FILE__, __LINE__);
10213 return(TNG_CRITICAL);
10217 strncpy(tng_data->first_computer_name, new_name, len);
10219 return(TNG_SUCCESS);
10222 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10223 (const tng_trajectory_t tng_data,
10224 char *name, const int max_len)
10226 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10227 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10229 strncpy(name, tng_data->last_computer_name, max_len - 1);
10230 name[max_len - 1] = 0;
10232 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10234 return(TNG_FAILURE);
10236 return(TNG_SUCCESS);
10239 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10240 (tng_trajectory_t tng_data,
10241 const char *new_name)
10245 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10246 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10248 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10250 /* If the currently stored string length is not enough to store the new
10251 * string it is freed and reallocated. */
10252 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10255 free(tng_data->last_computer_name);
10256 tng_data->last_computer_name = 0;
10258 if(!tng_data->last_computer_name)
10260 tng_data->last_computer_name = malloc(len);
10261 if(!tng_data->last_computer_name)
10263 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10264 __FILE__, __LINE__);
10265 return(TNG_CRITICAL);
10269 strncpy(tng_data->last_computer_name, new_name, len);
10271 return(TNG_SUCCESS);
10274 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10275 (const tng_trajectory_t tng_data,
10276 char *signature, const int max_len)
10278 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10279 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10281 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
10282 signature[max_len - 1] = 0;
10284 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10286 return(TNG_FAILURE);
10288 return(TNG_SUCCESS);
10291 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10292 (tng_trajectory_t tng_data,
10293 const char *signature)
10297 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10298 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10300 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10302 /* If the currently stored string length is not enough to store the new
10303 * string it is freed and reallocated. */
10304 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10307 free(tng_data->first_pgp_signature);
10308 tng_data->first_pgp_signature = 0;
10310 if(!tng_data->first_pgp_signature)
10312 tng_data->first_pgp_signature = malloc(len);
10313 if(!tng_data->first_pgp_signature)
10315 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10316 __FILE__, __LINE__);
10317 return(TNG_CRITICAL);
10321 strncpy(tng_data->first_pgp_signature, signature, len);
10323 return(TNG_SUCCESS);
10326 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10327 (const tng_trajectory_t tng_data,
10328 char *signature, const int max_len)
10330 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10331 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10333 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10334 signature[max_len - 1] = 0;
10336 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10338 return(TNG_FAILURE);
10340 return(TNG_SUCCESS);
10343 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10344 (tng_trajectory_t tng_data,
10345 const char *signature)
10349 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10350 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10352 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10354 /* If the currently stored string length is not enough to store the new
10355 * string it is freed and reallocated. */
10356 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10359 free(tng_data->last_pgp_signature);
10360 tng_data->last_pgp_signature = 0;
10362 if(!tng_data->last_pgp_signature)
10364 tng_data->last_pgp_signature = malloc(len);
10365 if(!tng_data->last_pgp_signature)
10367 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10368 __FILE__, __LINE__);
10369 return(TNG_CRITICAL);
10373 strncpy(tng_data->last_pgp_signature, signature, len);
10375 return(TNG_SUCCESS);
10378 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10379 (const tng_trajectory_t tng_data,
10380 char *name, const int max_len)
10382 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10383 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10385 strncpy(name, tng_data->forcefield_name, max_len - 1);
10386 name[max_len - 1] = 0;
10388 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10390 return(TNG_FAILURE);
10392 return(TNG_SUCCESS);
10395 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10396 (tng_trajectory_t tng_data,
10397 const char *new_name)
10401 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10402 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10404 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10406 /* If the currently stored string length is not enough to store the new
10407 * string it is freed and reallocated. */
10408 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10410 free(tng_data->forcefield_name);
10411 tng_data->forcefield_name = 0;
10413 if(!tng_data->forcefield_name)
10415 tng_data->forcefield_name = malloc(len);
10416 if(!tng_data->forcefield_name)
10418 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10419 __FILE__, __LINE__);
10420 return(TNG_CRITICAL);
10424 strncpy(tng_data->forcefield_name, new_name, len);
10426 return(TNG_SUCCESS);
10429 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10430 (const tng_trajectory_t tng_data,
10433 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10434 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10436 *len = tng_data->medium_stride_length;
10438 return(TNG_SUCCESS);
10441 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10442 (tng_trajectory_t tng_data,
10445 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10447 if(len >= tng_data->long_stride_length)
10449 return(TNG_FAILURE);
10451 tng_data->medium_stride_length = len;
10453 return(TNG_SUCCESS);
10456 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10457 (const tng_trajectory_t tng_data,
10460 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10461 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10463 *len = tng_data->long_stride_length;
10465 return(TNG_SUCCESS);
10468 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10469 (tng_trajectory_t tng_data,
10472 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10474 if(len <= tng_data->medium_stride_length)
10476 return(TNG_FAILURE);
10478 tng_data->long_stride_length = len;
10480 return(TNG_SUCCESS);
10483 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10484 (const tng_trajectory_t tng_data,
10487 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10488 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10490 *time = tng_data->time_per_frame;
10492 return(TNG_SUCCESS);
10495 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10496 (tng_trajectory_t tng_data,
10499 tng_trajectory_frame_set_t frame_set;
10501 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10502 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10504 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10506 return(TNG_SUCCESS);
10509 frame_set = &tng_data->current_trajectory_frame_set;
10511 /* If the current frame set is not finished write it to disk before
10512 changing time per frame. */
10513 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10515 frame_set->n_frames = frame_set->n_unwritten_frames;
10516 tng_frame_set_write(tng_data, TNG_USE_HASH);
10518 tng_data->time_per_frame = time;
10520 return(TNG_SUCCESS);
10523 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10524 (const tng_trajectory_t tng_data,
10527 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10528 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10530 *len = tng_data->input_file_len;
10532 return(TNG_SUCCESS);
10535 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10536 (const tng_trajectory_t tng_data,
10539 tng_gen_block_t block;
10540 tng_function_status stat;
10542 int64_t last_file_pos, first_frame, n_frames;
10544 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10545 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10546 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10548 file_pos = ftell(tng_data->input_file);
10549 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10551 if(last_file_pos <= 0)
10553 return(TNG_FAILURE);
10556 tng_block_init(&block);
10557 fseek(tng_data->input_file,
10558 (long)last_file_pos,
10560 /* Read block headers first to see that a frame set block is found. */
10561 stat = tng_block_header_read(tng_data, block);
10562 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10564 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
10565 __FILE__, __LINE__);
10566 tng_block_destroy(&block);
10567 return(TNG_FAILURE);
10569 tng_block_destroy(&block);
10571 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
10573 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
10574 __FILE__, __LINE__);
10575 return(TNG_CRITICAL);
10577 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
10579 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
10580 __FILE__, __LINE__);
10581 return(TNG_CRITICAL);
10583 fseek(tng_data->input_file, file_pos, SEEK_SET);
10585 *n = first_frame + n_frames;
10587 return(TNG_SUCCESS);
10590 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10591 (const tng_trajectory_t tng_data,
10594 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10596 *precision = tng_data->compression_precision;
10598 return(TNG_SUCCESS);
10601 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10602 (tng_trajectory_t tng_data,
10603 const double precision)
10605 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10607 tng_data->compression_precision = precision;
10609 return(TNG_SUCCESS);
10612 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10613 (tng_trajectory_t tng_data,
10616 tng_molecule_t mol;
10620 tng_function_status stat;
10621 int64_t diff, n_mod, n_impl;
10623 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
10625 diff = n - tng_data->n_particles;
10627 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10628 if(stat == TNG_SUCCESS)
10630 tng_molecule_cnt_get(tng_data, mol, &n_impl);
10631 diff -= n_impl * mol->n_atoms;
10636 if(stat == TNG_SUCCESS)
10638 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10641 return(TNG_SUCCESS);
10645 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10646 fprintf(stderr, "particle count.\n");
10647 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10648 __FILE__, __LINE__);
10649 /* FIXME: Should we set the count of all other molecules to 0 and add
10650 * implicit molecules? */
10651 return(TNG_FAILURE);
10653 if(stat != TNG_SUCCESS)
10655 stat = tng_molecule_add(tng_data,
10656 "TNG_IMPLICIT_MOL",
10658 if(stat != TNG_SUCCESS)
10662 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10663 if(stat != TNG_SUCCESS)
10667 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10668 if(stat != TNG_SUCCESS)
10672 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10673 if(stat != TNG_SUCCESS)
10680 if(mol->n_atoms > 1)
10682 n_mod = diff % mol->n_atoms;
10685 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10686 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10687 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10688 __FILE__, __LINE__);
10689 return(TNG_FAILURE);
10691 diff /= mol->n_atoms;
10694 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10699 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10700 (const tng_trajectory_t tng_data,
10703 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10704 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10706 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10708 *n = tng_data->n_particles;
10712 *n = tng_data->current_trajectory_frame_set.n_particles;
10715 return(TNG_SUCCESS);
10718 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10719 (const tng_trajectory_t tng_data,
10722 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10723 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10725 *variable = tng_data->var_num_atoms_flag;
10727 return(TNG_SUCCESS);
10730 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10731 (const tng_trajectory_t tng_data,
10734 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10735 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10737 *n = tng_data->n_molecules;
10739 return(TNG_SUCCESS);
10742 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10743 (const tng_trajectory_t tng_data,
10746 int64_t *cnt_list = 0, cnt = 0, i;
10748 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10749 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10751 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10755 return(TNG_FAILURE);
10758 for(i = tng_data->n_molecules; i --;)
10760 cnt += cnt_list[i];
10765 return(TNG_SUCCESS);
10768 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10769 (const tng_trajectory_t tng_data,
10770 int64_t **mol_cnt_list)
10772 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10774 if(tng_data->var_num_atoms_flag)
10776 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10781 *mol_cnt_list = tng_data->molecule_cnt_list;
10783 if(*mol_cnt_list == 0)
10785 return(TNG_FAILURE);
10787 return(TNG_SUCCESS);
10790 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10791 (const tng_trajectory_t tng_data,
10794 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10795 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10797 *exp = tng_data->distance_unit_exponential;
10799 return(TNG_SUCCESS);
10802 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10803 (const tng_trajectory_t tng_data,
10806 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10808 tng_data->distance_unit_exponential = exp;
10810 return(TNG_SUCCESS);
10813 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10814 (const tng_trajectory_t tng_data,
10817 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10818 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10820 *n = tng_data->frame_set_n_frames;
10822 return(TNG_SUCCESS);
10825 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10826 (const tng_trajectory_t tng_data,
10829 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10831 tng_data->frame_set_n_frames = n;
10833 return(TNG_SUCCESS);
10836 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10837 (const tng_trajectory_t tng_data,
10840 int64_t long_stride_length, medium_stride_length;
10841 int64_t file_pos, orig_frame_set_file_pos;
10842 tng_trajectory_frame_set_t frame_set;
10843 struct tng_trajectory_frame_set orig_frame_set;
10844 tng_gen_block_t block;
10845 tng_function_status stat;
10848 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10849 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10851 orig_frame_set = tng_data->current_trajectory_frame_set;
10853 frame_set = &tng_data->current_trajectory_frame_set;
10855 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10856 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10858 tng_block_init(&block);
10859 fseek(tng_data->input_file,
10862 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
10863 /* Read block headers first to see what block is found. */
10864 stat = tng_block_header_read(tng_data, block);
10865 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10867 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
10868 __FILE__, __LINE__);
10869 tng_block_destroy(&block);
10870 return(TNG_CRITICAL);
10873 if(tng_block_read_next(tng_data, block,
10874 TNG_SKIP_HASH) != TNG_SUCCESS)
10876 tng_block_destroy(&block);
10877 return(TNG_CRITICAL);
10882 long_stride_length = tng_data->long_stride_length;
10883 medium_stride_length = tng_data->medium_stride_length;
10885 /* Take long steps forward until a long step forward would be too long or
10886 * the last frame set is found */
10887 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10888 while(file_pos > 0)
10892 cnt += long_stride_length;
10893 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
10894 /* Read block headers first to see what block is found. */
10895 stat = tng_block_header_read(tng_data, block);
10896 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10898 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10899 file_pos, __FILE__, __LINE__);
10900 tng_block_destroy(&block);
10901 return(TNG_CRITICAL);
10904 if(tng_block_read_next(tng_data, block,
10905 TNG_SKIP_HASH) != TNG_SUCCESS)
10907 tng_block_destroy(&block);
10908 return(TNG_CRITICAL);
10911 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10914 /* Take medium steps forward until a medium step forward would be too long
10915 * or the last frame set is found */
10916 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10917 while(file_pos > 0)
10921 cnt += medium_stride_length;
10922 fseek(tng_data->input_file,
10925 /* Read block headers first to see what block is found. */
10926 stat = tng_block_header_read(tng_data, block);
10927 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10929 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10930 file_pos, __FILE__, __LINE__);
10931 tng_block_destroy(&block);
10932 return(TNG_CRITICAL);
10935 if(tng_block_read_next(tng_data, block,
10936 TNG_SKIP_HASH) != TNG_SUCCESS)
10938 tng_block_destroy(&block);
10939 return(TNG_CRITICAL);
10942 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10945 /* Take one step forward until the last frame set is found */
10946 file_pos = frame_set->next_frame_set_file_pos;
10947 while(file_pos > 0)
10952 fseek(tng_data->input_file,
10955 /* Read block headers first to see what block is found. */
10956 stat = tng_block_header_read(tng_data, block);
10957 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10959 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10960 file_pos, __FILE__, __LINE__);
10961 tng_block_destroy(&block);
10962 return(TNG_CRITICAL);
10965 if(tng_block_read_next(tng_data, block,
10966 TNG_SKIP_HASH) != TNG_SUCCESS)
10968 tng_block_destroy(&block);
10969 return(TNG_CRITICAL);
10972 file_pos = frame_set->next_frame_set_file_pos;
10975 tng_block_destroy(&block);
10977 *n = tng_data->n_trajectory_frame_sets = cnt;
10979 *frame_set = orig_frame_set;
10981 fseek(tng_data->input_file,
10982 (long)tng_data->first_trajectory_frame_set_input_file_pos,
10985 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
10987 return(TNG_SUCCESS);
10990 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10991 (tng_trajectory_t tng_data,
10992 tng_trajectory_frame_set_t *frame_set_p)
10994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10996 *frame_set_p = &tng_data->current_trajectory_frame_set;
10998 return(TNG_SUCCESS);
11001 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11002 (tng_trajectory_t tng_data,
11005 int64_t long_stride_length, medium_stride_length;
11006 int64_t file_pos, curr_nr = 0, n_frame_sets;
11007 tng_trajectory_frame_set_t frame_set;
11008 tng_gen_block_t block;
11009 tng_function_status stat;
11011 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11012 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11014 frame_set = &tng_data->current_trajectory_frame_set;
11016 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11018 if(stat != TNG_SUCCESS)
11023 if(nr >= n_frame_sets)
11025 return(TNG_FAILURE);
11028 long_stride_length = tng_data->long_stride_length;
11029 medium_stride_length = tng_data->medium_stride_length;
11031 /* FIXME: The frame set number of the current frame set is not stored */
11033 if(nr < n_frame_sets - 1 - nr)
11035 /* Start from the beginning */
11036 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11040 /* Start from the end */
11041 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11042 curr_nr = n_frame_sets - 1;
11046 return(TNG_FAILURE);
11049 tng_block_init(&block);
11050 fseek(tng_data->input_file,
11053 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11054 /* Read block headers first to see what block is found. */
11055 stat = tng_block_header_read(tng_data, block);
11056 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11058 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11059 __FILE__, __LINE__);
11060 tng_block_destroy(&block);
11061 return(TNG_CRITICAL);
11064 if(tng_block_read_next(tng_data, block,
11065 TNG_SKIP_HASH) != TNG_SUCCESS)
11067 tng_block_destroy(&block);
11068 return(TNG_CRITICAL);
11073 tng_block_destroy(&block);
11074 return(TNG_SUCCESS);
11077 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11079 /* Take long steps forward until a long step forward would be too long or
11080 * the right frame set is found */
11081 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11083 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11086 curr_nr += long_stride_length;
11087 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11088 /* Read block headers first to see what block is found. */
11089 stat = tng_block_header_read(tng_data, block);
11090 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11092 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11093 file_pos, __FILE__, __LINE__);
11094 tng_block_destroy(&block);
11095 return(TNG_CRITICAL);
11098 if(tng_block_read_next(tng_data, block,
11099 TNG_SKIP_HASH) != TNG_SUCCESS)
11101 tng_block_destroy(&block);
11102 return(TNG_CRITICAL);
11106 tng_block_destroy(&block);
11107 return(TNG_SUCCESS);
11112 /* Take medium steps forward until a medium step forward would be too long
11113 * or the right frame set is found */
11114 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11116 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11119 curr_nr += medium_stride_length;
11120 fseek(tng_data->input_file,
11123 /* Read block headers first to see what block is found. */
11124 stat = tng_block_header_read(tng_data, block);
11125 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11127 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11128 file_pos, __FILE__, __LINE__);
11129 tng_block_destroy(&block);
11130 return(TNG_CRITICAL);
11133 if(tng_block_read_next(tng_data, block,
11134 TNG_SKIP_HASH) != TNG_SUCCESS)
11136 tng_block_destroy(&block);
11137 return(TNG_CRITICAL);
11141 tng_block_destroy(&block);
11142 return(TNG_SUCCESS);
11147 /* Take one step forward until the right frame set is found */
11148 while(file_pos > 0 && curr_nr < nr)
11150 file_pos = frame_set->next_frame_set_file_pos;
11155 fseek(tng_data->input_file,
11158 /* Read block headers first to see what block is found. */
11159 stat = tng_block_header_read(tng_data, block);
11160 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11162 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11163 file_pos, __FILE__, __LINE__);
11164 tng_block_destroy(&block);
11165 return(TNG_CRITICAL);
11168 if(tng_block_read_next(tng_data, block,
11169 TNG_SKIP_HASH) != TNG_SUCCESS)
11171 tng_block_destroy(&block);
11172 return(TNG_CRITICAL);
11176 tng_block_destroy(&block);
11177 return(TNG_SUCCESS);
11182 /* Take long steps backward until a long step backward would be too long
11183 * or the right frame set is found */
11184 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11186 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11189 curr_nr -= long_stride_length;
11190 fseek(tng_data->input_file,
11193 /* Read block headers first to see what block is found. */
11194 stat = tng_block_header_read(tng_data, block);
11195 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11197 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11198 file_pos, __FILE__, __LINE__);
11199 tng_block_destroy(&block);
11200 return(TNG_CRITICAL);
11203 if(tng_block_read_next(tng_data, block,
11204 TNG_SKIP_HASH) != TNG_SUCCESS)
11206 tng_block_destroy(&block);
11207 return(TNG_CRITICAL);
11211 tng_block_destroy(&block);
11212 return(TNG_SUCCESS);
11217 /* Take medium steps backward until a medium step backward would be too long
11218 * or the right frame set is found */
11219 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11221 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11224 curr_nr -= medium_stride_length;
11225 fseek(tng_data->input_file,
11228 /* Read block headers first to see what block is found. */
11229 stat = tng_block_header_read(tng_data, block);
11230 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11232 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11233 file_pos, __FILE__, __LINE__);
11234 tng_block_destroy(&block);
11235 return(TNG_CRITICAL);
11238 if(tng_block_read_next(tng_data, block,
11239 TNG_SKIP_HASH) != TNG_SUCCESS)
11241 tng_block_destroy(&block);
11242 return(TNG_CRITICAL);
11246 tng_block_destroy(&block);
11247 return(TNG_SUCCESS);
11252 /* Take one step backward until the right frame set is found */
11253 while(file_pos > 0 && curr_nr > nr)
11255 file_pos = frame_set->prev_frame_set_file_pos;
11259 fseek(tng_data->input_file,
11262 /* Read block headers first to see what block is found. */
11263 stat = tng_block_header_read(tng_data, block);
11264 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11266 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11267 file_pos, __FILE__, __LINE__);
11268 tng_block_destroy(&block);
11269 return(TNG_CRITICAL);
11272 if(tng_block_read_next(tng_data, block,
11273 TNG_SKIP_HASH) != TNG_SUCCESS)
11275 tng_block_destroy(&block);
11276 return(TNG_CRITICAL);
11280 tng_block_destroy(&block);
11281 return(TNG_SUCCESS);
11286 /* If for some reason the current frame set is not yet found,
11287 * take one step forward until the right frame set is found */
11288 while(file_pos > 0 && curr_nr < nr)
11290 file_pos = frame_set->next_frame_set_file_pos;
11294 fseek(tng_data->input_file,
11297 /* Read block headers first to see what block is found. */
11298 stat = tng_block_header_read(tng_data, block);
11299 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11301 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11302 file_pos, __FILE__, __LINE__);
11303 tng_block_destroy(&block);
11304 return(TNG_CRITICAL);
11307 if(tng_block_read_next(tng_data, block,
11308 TNG_SKIP_HASH) != TNG_SUCCESS)
11310 tng_block_destroy(&block);
11311 return(TNG_CRITICAL);
11315 tng_block_destroy(&block);
11316 return(TNG_SUCCESS);
11321 tng_block_destroy(&block);
11322 return(TNG_FAILURE);
11325 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11326 (tng_trajectory_t tng_data,
11327 const int64_t frame)
11329 int64_t first_frame, last_frame, n_frames_per_frame_set;
11330 int64_t long_stride_length, medium_stride_length;
11331 int64_t file_pos, temp_frame, n_frames;
11332 tng_trajectory_frame_set_t frame_set;
11333 tng_gen_block_t block;
11334 tng_function_status stat;
11336 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11337 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11339 frame_set = &tng_data->current_trajectory_frame_set;
11341 tng_block_init(&block);
11343 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11345 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11346 fseek(tng_data->input_file,
11349 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11350 /* Read block headers first to see what block is found. */
11351 stat = tng_block_header_read(tng_data, block);
11352 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11354 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11355 file_pos, __FILE__, __LINE__);
11356 tng_block_destroy(&block);
11357 return(TNG_CRITICAL);
11360 if(tng_block_read_next(tng_data, block,
11361 TNG_SKIP_HASH) != TNG_SUCCESS)
11363 tng_block_destroy(&block);
11364 return(TNG_CRITICAL);
11368 first_frame = tng_max_i64(frame_set->first_frame, 0);
11369 last_frame = first_frame + frame_set->n_frames - 1;
11370 /* Is this the right frame set? */
11371 if(first_frame <= frame && frame <= last_frame)
11373 tng_block_destroy(&block);
11374 return(TNG_SUCCESS);
11377 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11378 long_stride_length = tng_data->long_stride_length;
11379 medium_stride_length = tng_data->medium_stride_length;
11381 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11384 if(temp_frame - first_frame > n_frames_per_frame_set)
11386 n_frames_per_frame_set = temp_frame - first_frame;
11390 tng_num_frames_get(tng_data, &n_frames);
11392 if(frame >= n_frames)
11394 tng_block_destroy(&block);
11395 return(TNG_FAILURE);
11398 if(first_frame - frame >= frame ||
11399 frame - last_frame >
11400 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11402 /* Start from the beginning */
11403 if(first_frame - frame >= frame)
11405 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11409 tng_block_destroy(&block);
11410 return(TNG_FAILURE);
11413 /* Start from the end */
11414 else if(frame - first_frame > (n_frames - 1) - frame)
11416 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11418 /* If the last frame set position is not set start from the current
11419 * frame set, since it will be closer than the first frame set. */
11421 /* Start from current */
11424 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11429 fseek(tng_data->input_file,
11432 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11433 /* Read block headers first to see what block is found. */
11434 stat = tng_block_header_read(tng_data, block);
11435 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11437 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11438 file_pos, __FILE__, __LINE__);
11439 tng_block_destroy(&block);
11440 return(TNG_CRITICAL);
11443 if(tng_block_read_next(tng_data, block,
11444 TNG_SKIP_HASH) != TNG_SUCCESS)
11446 tng_block_destroy(&block);
11447 return(TNG_CRITICAL);
11452 first_frame = tng_max_i64(frame_set->first_frame, 0);
11453 last_frame = first_frame + frame_set->n_frames - 1;
11455 if(frame >= first_frame && frame <= last_frame)
11457 tng_block_destroy(&block);
11458 return(TNG_SUCCESS);
11461 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11463 /* Take long steps forward until a long step forward would be too long or
11464 * the right frame set is found */
11465 while(file_pos > 0 && first_frame + long_stride_length *
11466 n_frames_per_frame_set <= frame)
11468 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11471 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11472 /* Read block headers first to see what block is found. */
11473 stat = tng_block_header_read(tng_data, block);
11474 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11476 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11477 file_pos, __FILE__, __LINE__);
11478 tng_block_destroy(&block);
11479 return(TNG_CRITICAL);
11482 if(tng_block_read_next(tng_data, block,
11483 TNG_SKIP_HASH) != TNG_SUCCESS)
11485 tng_block_destroy(&block);
11486 return(TNG_CRITICAL);
11489 first_frame = tng_max_i64(frame_set->first_frame, 0);
11490 last_frame = first_frame + frame_set->n_frames - 1;
11491 if(frame >= first_frame && frame <= last_frame)
11493 tng_block_destroy(&block);
11494 return(TNG_SUCCESS);
11498 /* Take medium steps forward until a medium step forward would be too long
11499 * or the right frame set is found */
11500 while(file_pos > 0 && first_frame + medium_stride_length *
11501 n_frames_per_frame_set <= frame)
11503 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11506 fseek(tng_data->input_file,
11509 /* Read block headers first to see what block is found. */
11510 stat = tng_block_header_read(tng_data, block);
11511 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11513 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11514 file_pos, __FILE__, __LINE__);
11515 tng_block_destroy(&block);
11516 return(TNG_CRITICAL);
11519 if(tng_block_read_next(tng_data, block,
11520 TNG_SKIP_HASH) != TNG_SUCCESS)
11522 tng_block_destroy(&block);
11523 return(TNG_CRITICAL);
11526 first_frame = tng_max_i64(frame_set->first_frame, 0);
11527 last_frame = first_frame + frame_set->n_frames - 1;
11528 if(frame >= first_frame && frame <= last_frame)
11530 tng_block_destroy(&block);
11531 return(TNG_SUCCESS);
11535 /* Take one step forward until the right frame set is found */
11536 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11538 file_pos = frame_set->next_frame_set_file_pos;
11541 fseek(tng_data->input_file,
11544 /* Read block headers first to see what block is found. */
11545 stat = tng_block_header_read(tng_data, block);
11546 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11548 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11549 file_pos, __FILE__, __LINE__);
11550 tng_block_destroy(&block);
11551 return(TNG_CRITICAL);
11554 if(tng_block_read_next(tng_data, block,
11555 TNG_SKIP_HASH) != TNG_SUCCESS)
11557 tng_block_destroy(&block);
11558 return(TNG_CRITICAL);
11561 first_frame = tng_max_i64(frame_set->first_frame, 0);
11562 last_frame = first_frame + frame_set->n_frames - 1;
11563 if(frame >= first_frame && frame <= last_frame)
11565 tng_block_destroy(&block);
11566 return(TNG_SUCCESS);
11570 /* Take long steps backward until a long step backward would be too long
11571 * or the right frame set is found */
11572 while(file_pos > 0 && first_frame - long_stride_length *
11573 n_frames_per_frame_set >= frame)
11575 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11578 fseek(tng_data->input_file,
11581 /* Read block headers first to see what block is found. */
11582 stat = tng_block_header_read(tng_data, block);
11583 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11585 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11586 file_pos, __FILE__, __LINE__);
11587 tng_block_destroy(&block);
11588 return(TNG_CRITICAL);
11591 if(tng_block_read_next(tng_data, block,
11592 TNG_SKIP_HASH) != TNG_SUCCESS)
11594 tng_block_destroy(&block);
11595 return(TNG_CRITICAL);
11598 first_frame = tng_max_i64(frame_set->first_frame, 0);
11599 last_frame = first_frame + frame_set->n_frames - 1;
11600 if(frame >= first_frame && frame <= last_frame)
11602 tng_block_destroy(&block);
11603 return(TNG_SUCCESS);
11607 /* Take medium steps backward until a medium step backward would be too long
11608 * or the right frame set is found */
11609 while(file_pos > 0 && first_frame - medium_stride_length *
11610 n_frames_per_frame_set >= frame)
11612 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11615 fseek(tng_data->input_file,
11618 /* Read block headers first to see what block is found. */
11619 stat = tng_block_header_read(tng_data, block);
11620 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11622 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11623 file_pos, __FILE__, __LINE__);
11624 tng_block_destroy(&block);
11625 return(TNG_CRITICAL);
11628 if(tng_block_read_next(tng_data, block,
11629 TNG_SKIP_HASH) != TNG_SUCCESS)
11631 tng_block_destroy(&block);
11632 return(TNG_CRITICAL);
11635 first_frame = tng_max_i64(frame_set->first_frame, 0);
11636 last_frame = first_frame + frame_set->n_frames - 1;
11637 if(frame >= first_frame && frame <= last_frame)
11639 tng_block_destroy(&block);
11640 return(TNG_SUCCESS);
11644 /* Take one step backward until the right frame set is found */
11645 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11647 file_pos = frame_set->prev_frame_set_file_pos;
11650 fseek(tng_data->input_file,
11653 /* Read block headers first to see what block is found. */
11654 stat = tng_block_header_read(tng_data, block);
11655 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11657 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11658 file_pos, __FILE__, __LINE__);
11659 tng_block_destroy(&block);
11660 return(TNG_CRITICAL);
11663 if(tng_block_read_next(tng_data, block,
11664 TNG_SKIP_HASH) != TNG_SUCCESS)
11666 tng_block_destroy(&block);
11667 return(TNG_CRITICAL);
11670 first_frame = tng_max_i64(frame_set->first_frame, 0);
11671 last_frame = first_frame + frame_set->n_frames - 1;
11672 if(frame >= first_frame && frame <= last_frame)
11674 tng_block_destroy(&block);
11675 return(TNG_SUCCESS);
11679 /* If for some reason the current frame set is not yet found,
11680 * take one step forward until the right frame set is found */
11681 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11683 file_pos = frame_set->next_frame_set_file_pos;
11686 fseek(tng_data->input_file,
11689 /* Read block headers first to see what block is found. */
11690 stat = tng_block_header_read(tng_data, block);
11691 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11693 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11694 file_pos, __FILE__, __LINE__);
11695 tng_block_destroy(&block);
11696 return(TNG_CRITICAL);
11699 if(tng_block_read_next(tng_data, block,
11700 TNG_SKIP_HASH) != TNG_SUCCESS)
11702 tng_block_destroy(&block);
11703 return(TNG_CRITICAL);
11706 first_frame = tng_max_i64(frame_set->first_frame, 0);
11707 last_frame = first_frame + frame_set->n_frames - 1;
11708 if(frame >= first_frame && frame <= last_frame)
11710 tng_block_destroy(&block);
11711 return(TNG_SUCCESS);
11715 tng_block_destroy(&block);
11716 return(TNG_FAILURE);
11719 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11720 (const tng_trajectory_t tng_data,
11721 const tng_trajectory_frame_set_t frame_set,
11726 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11727 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11729 *pos = frame_set->next_frame_set_file_pos;
11731 return(TNG_SUCCESS);
11734 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11735 (const tng_trajectory_t tng_data,
11736 const tng_trajectory_frame_set_t frame_set,
11741 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11742 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11744 *pos = frame_set->prev_frame_set_file_pos;
11746 return(TNG_SUCCESS);
11749 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11750 (const tng_trajectory_t tng_data,
11751 const tng_trajectory_frame_set_t frame_set,
11752 int64_t *first_frame,
11753 int64_t *last_frame)
11757 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11758 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11759 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11761 *first_frame = frame_set->first_frame;
11762 *last_frame = *first_frame + frame_set->n_frames - 1;
11764 return(TNG_SUCCESS);
11767 /** Translate from the particle numbering used in a frame set to the real
11768 * particle numbering - used in the molecule description.
11769 * @param frame_set is the frame_set containing the mappings to use.
11770 * @param local is the index number of the atom in this frame set
11771 * @param real is set to the index of the atom in the molecular system.
11772 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11775 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11776 (const tng_trajectory_frame_set_t frame_set,
11777 const int64_t local,
11780 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11781 tng_particle_mapping_t mapping;
11785 return(TNG_SUCCESS);
11787 for(i = 0; i < n_blocks; i++)
11789 mapping = &frame_set->mappings[i];
11790 first = mapping->num_first_particle;
11791 if(local < first ||
11792 local >= first + mapping->n_particles)
11796 *real = mapping->real_particle_numbers[local-first];
11797 return(TNG_SUCCESS);
11800 return(TNG_FAILURE);
11803 /** Translate from the real particle numbering to the particle numbering
11804 * used in a frame set.
11805 * @param frame_set is the frame_set containing the mappings to use.
11806 * @param real is the index number of the atom in the molecular system.
11807 * @param local is set to the index of the atom in this frame set.
11808 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11811 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11812 (const tng_trajectory_frame_set_t frame_set,
11813 const int64_t real,
11816 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11817 tng_particle_mapping_t mapping;
11821 return(TNG_SUCCESS);
11823 for(i = 0; i < n_blocks; i++)
11825 mapping = &frame_set->mappings[i];
11826 for(j = mapping->n_particles; j--;)
11828 if(mapping->real_particle_numbers[j] == real)
11831 return(TNG_SUCCESS);
11835 return(TNG_FAILURE);
11839 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11840 (tng_trajectory_t tng_data,
11841 const char hash_mode)
11843 int cnt = 0, prev_pos = 0;
11844 tng_gen_block_t block;
11846 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11848 tng_data->n_trajectory_frame_sets = 0;
11850 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11852 return(TNG_CRITICAL);
11855 if(!tng_data->input_file_len)
11857 fseek(tng_data->input_file, 0, SEEK_END);
11858 tng_data->input_file_len = ftell(tng_data->input_file);
11859 fseek(tng_data->input_file, 0, SEEK_SET);
11862 tng_block_init(&block);
11863 /* Non trajectory blocks (they come before the trajectory
11864 * blocks in the file) */
11865 while (prev_pos < tng_data->input_file_len &&
11866 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11868 block->id != TNG_TRAJECTORY_FRAME_SET)
11870 if(tng_block_read_next(tng_data, block,
11871 hash_mode) == TNG_SUCCESS)
11875 prev_pos = ftell(tng_data->input_file);
11878 /* Go back if a trajectory block was encountered */
11879 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11881 fseek(tng_data->input_file, prev_pos, SEEK_SET);
11884 tng_block_destroy(&block);
11886 return(TNG_SUCCESS);
11889 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11890 (tng_trajectory_t tng_data,
11891 const char hash_mode)
11894 tng_gen_block_t data_block;
11896 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11898 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11900 return(TNG_CRITICAL);
11903 /* TODO: If there is already frame set data written to this file (e.g. when
11904 * appending to an already existing file we might need to move frame sets to
11905 * the end of the file. */
11907 if(tng_general_info_block_write(tng_data, hash_mode)
11910 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11911 tng_data->input_file_path, __FILE__, __LINE__);
11912 return(TNG_CRITICAL);
11915 if(tng_molecules_block_write(tng_data, hash_mode)
11918 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11919 tng_data->input_file_path, __FILE__, __LINE__);
11920 return(TNG_CRITICAL);
11923 /* FIXME: Currently writing non-trajectory data blocks here.
11924 * Should perhaps be moved. */
11925 tng_block_init(&data_block);
11926 for(i = 0; i < tng_data->n_data_blocks; i++)
11928 data_block->id = tng_data->non_tr_data[i].block_id;
11929 tng_data_block_write(tng_data, data_block,
11933 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11935 data_block->id = tng_data->non_tr_particle_data[i].block_id;
11936 tng_particle_data_block_write(tng_data, data_block,
11940 tng_block_destroy(&data_block);
11942 return(TNG_SUCCESS);
11945 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
11946 tng_gen_block_t block,
11947 const char hash_mode)
11949 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11950 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
11954 case TNG_TRAJECTORY_FRAME_SET:
11955 return(tng_frame_set_block_read(tng_data, block, hash_mode));
11956 case TNG_PARTICLE_MAPPING:
11957 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
11958 case TNG_GENERAL_INFO:
11959 return(tng_general_info_block_read(tng_data, block, hash_mode));
11960 case TNG_MOLECULES:
11961 return(tng_molecules_block_read(tng_data, block, hash_mode));
11963 if(block->id >= TNG_TRAJ_BOX_SHAPE)
11965 return(tng_data_block_contents_read(tng_data, block, hash_mode));
11969 /* Skip to the next block */
11970 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
11971 return(TNG_FAILURE);
11976 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11977 (tng_trajectory_t tng_data,
11978 const char hash_mode)
11981 tng_gen_block_t block;
11982 tng_function_status stat;
11984 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11986 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11988 return(TNG_CRITICAL);
11991 file_pos = ftell(tng_data->input_file);
11993 tng_block_init(&block);
11995 if(!tng_data->input_file_len)
11997 fseek(tng_data->input_file, 0, SEEK_END);
11998 tng_data->input_file_len = ftell(tng_data->input_file);
11999 fseek(tng_data->input_file, file_pos, SEEK_SET);
12002 /* Read block headers first to see what block is found. */
12003 stat = tng_block_header_read(tng_data, block);
12004 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12006 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12007 file_pos, __FILE__, __LINE__);
12008 tng_block_destroy(&block);
12009 return(TNG_CRITICAL);
12012 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12014 if(tng_block_read_next(tng_data, block,
12015 hash_mode) == TNG_SUCCESS)
12017 tng_data->n_trajectory_frame_sets++;
12018 file_pos = ftell(tng_data->input_file);
12019 /* Read all blocks until next frame set block */
12020 stat = tng_block_header_read(tng_data, block);
12021 while(file_pos < tng_data->input_file_len &&
12022 stat != TNG_CRITICAL &&
12023 block->id != TNG_TRAJECTORY_FRAME_SET)
12025 stat = tng_block_read_next(tng_data, block,
12027 if(stat != TNG_CRITICAL)
12029 file_pos = ftell(tng_data->input_file);
12030 if(file_pos < tng_data->input_file_len)
12032 stat = tng_block_header_read(tng_data, block);
12036 if(stat == TNG_CRITICAL)
12038 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12039 file_pos, __FILE__, __LINE__);
12040 tng_block_destroy(&block);
12044 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12046 fseek(tng_data->input_file, file_pos, SEEK_SET);
12050 tng_block_destroy(&block);
12052 return(TNG_SUCCESS);
12056 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12057 (tng_trajectory_t tng_data,
12058 const char hash_mode,
12059 const int64_t block_id)
12062 tng_gen_block_t block;
12063 tng_function_status stat;
12064 int found_flag = 1;
12066 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12068 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12070 return(TNG_CRITICAL);
12073 file_pos = (long)tng_data->current_trajectory_frame_set_input_file_pos;
12077 /* No current frame set. This means that the first frame set must be
12080 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12085 fseek(tng_data->input_file,
12091 return(TNG_FAILURE);
12094 tng_block_init(&block);
12096 if(!tng_data->input_file_len)
12098 fseek(tng_data->input_file, 0, SEEK_END);
12099 tng_data->input_file_len = ftell(tng_data->input_file);
12100 fseek(tng_data->input_file, file_pos, SEEK_SET);
12103 /* Read block headers first to see what block is found. */
12104 stat = tng_block_header_read(tng_data, block);
12105 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12107 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12108 file_pos, __FILE__, __LINE__);
12109 tng_block_destroy(&block);
12110 return(TNG_CRITICAL);
12112 /* If the current frame set had already been read skip its block contents */
12115 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12117 /* Otherwiese read the frame set block */
12120 stat = tng_block_read_next(tng_data, block,
12122 if(stat != TNG_SUCCESS)
12124 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12125 tng_block_destroy(&block);
12129 file_pos = ftell(tng_data->input_file);
12133 /* Read only blocks of the requested ID
12134 * until next frame set block */
12135 stat = tng_block_header_read(tng_data, block);
12136 while(file_pos < tng_data->input_file_len &&
12137 stat != TNG_CRITICAL &&
12138 block->id != TNG_TRAJECTORY_FRAME_SET)
12140 if(block->id == block_id)
12142 stat = tng_block_read_next(tng_data, block,
12144 if(stat != TNG_CRITICAL)
12146 file_pos = ftell(tng_data->input_file);
12148 if(file_pos < tng_data->input_file_len)
12150 stat = tng_block_header_read(tng_data, block);
12156 file_pos += (long)(block->block_contents_size + block->header_contents_size);
12157 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12158 if(file_pos < tng_data->input_file_len)
12160 stat = tng_block_header_read(tng_data, block);
12164 if(stat == TNG_CRITICAL)
12166 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12167 file_pos, __FILE__, __LINE__);
12168 tng_block_destroy(&block);
12172 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12174 fseek(tng_data->input_file, file_pos, SEEK_SET);
12177 tng_block_destroy(&block);
12181 return(TNG_SUCCESS);
12185 return(TNG_FAILURE);
12189 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12190 (tng_trajectory_t tng_data,
12191 const char hash_mode)
12195 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12197 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12199 return(TNG_CRITICAL);
12202 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12204 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12206 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12211 fseek(tng_data->input_file,
12217 return(TNG_FAILURE);
12220 return(tng_frame_set_read(tng_data, hash_mode));
12223 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12224 (tng_trajectory_t tng_data,
12225 const char hash_mode,
12226 const int64_t block_id)
12229 tng_gen_block_t block;
12230 tng_function_status stat;
12232 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12234 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12236 return(TNG_CRITICAL);
12239 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12241 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12243 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12248 fseek(tng_data->input_file,
12254 return(TNG_FAILURE);
12257 tng_block_init(&block);
12259 if(!tng_data->input_file_len)
12261 fseek(tng_data->input_file, 0, SEEK_END);
12262 tng_data->input_file_len = ftell(tng_data->input_file);
12263 fseek(tng_data->input_file, file_pos, SEEK_SET);
12266 /* Read block headers first to see what block is found. */
12267 stat = tng_block_header_read(tng_data, block);
12268 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12270 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12271 file_pos, __FILE__, __LINE__);
12272 tng_block_destroy(&block);
12273 return(TNG_CRITICAL);
12276 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12278 if(tng_block_read_next(tng_data, block,
12279 hash_mode) == TNG_SUCCESS)
12281 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12284 tng_block_destroy(&block);
12289 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
12290 const char hash_mode)
12293 tng_gen_block_t block;
12294 tng_trajectory_frame_set_t frame_set;
12295 tng_function_status stat;
12297 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12299 frame_set = &tng_data->current_trajectory_frame_set;
12301 if(frame_set->n_written_frames == frame_set->n_frames)
12303 return(TNG_SUCCESS);
12306 tng_data->current_trajectory_frame_set_output_file_pos =
12307 ftell(tng_data->output_file);
12308 tng_data->last_trajectory_frame_set_output_file_pos =
12309 tng_data->current_trajectory_frame_set_output_file_pos;
12311 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12313 return(TNG_FAILURE);
12316 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12318 tng_data->first_trajectory_frame_set_output_file_pos =
12319 tng_data->current_trajectory_frame_set_output_file_pos;
12322 tng_block_init(&block);
12324 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12326 tng_block_destroy(&block);
12327 return(TNG_FAILURE);
12330 /* Write non-particle data blocks */
12331 for(i = 0; i<frame_set->n_data_blocks; i++)
12333 block->id = frame_set->tr_data[i].block_id;
12334 tng_data_block_write(tng_data, block, i, hash_mode);
12336 /* Write the mapping blocks and particle data blocks*/
12337 if(frame_set->n_mapping_blocks)
12339 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12341 block->id = TNG_PARTICLE_MAPPING;
12342 if(frame_set->mappings[i].n_particles > 0)
12344 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12345 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12347 block->id = frame_set->tr_particle_data[j].block_id;
12348 tng_particle_data_block_write(tng_data, block,
12349 j, &frame_set->mappings[i],
12357 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12359 block->id = frame_set->tr_particle_data[i].block_id;
12360 tng_particle_data_block_write(tng_data, block,
12366 /* Update pointers in the general info block */
12367 stat = tng_header_pointers_update(tng_data, hash_mode);
12369 if(stat == TNG_SUCCESS)
12371 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12374 tng_block_destroy(&block);
12376 frame_set->n_unwritten_frames = 0;
12378 fflush(tng_data->output_file);
12383 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12384 (tng_trajectory_t tng_data,
12385 const char hash_mode)
12387 tng_trajectory_frame_set_t frame_set;
12389 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12391 frame_set = &tng_data->current_trajectory_frame_set;
12393 if(frame_set->n_unwritten_frames == 0)
12395 return(TNG_SUCCESS);
12397 frame_set->n_frames = frame_set->n_unwritten_frames;
12399 return(tng_frame_set_write(tng_data, hash_mode));
12402 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12403 (tng_trajectory_t tng_data,
12404 const int64_t first_frame,
12405 const int64_t n_frames)
12407 tng_gen_block_t block;
12408 tng_trajectory_frame_set_t frame_set;
12409 FILE *temp = tng_data->input_file;
12412 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12413 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12414 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12416 frame_set = &tng_data->current_trajectory_frame_set;
12418 curr_pos = ftell(tng_data->output_file);
12422 tng_file_headers_write(tng_data, TNG_USE_HASH);
12425 /* Set pointer to previous frame set to the one that was loaded
12427 * FIXME: This is a bit risky. If they are not added in order
12428 * it will be wrong. */
12429 if(tng_data->n_trajectory_frame_sets)
12431 frame_set->prev_frame_set_file_pos =
12432 tng_data->current_trajectory_frame_set_output_file_pos;
12435 tng_data->current_trajectory_frame_set_output_file_pos =
12436 ftell(tng_data->output_file);
12438 tng_data->n_trajectory_frame_sets++;
12440 /* Set the medium range pointers */
12441 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12443 frame_set->medium_stride_prev_frame_set_file_pos =
12444 tng_data->first_trajectory_frame_set_output_file_pos;
12446 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12448 /* FIXME: Currently only working if the previous frame set has its
12449 * medium stride pointer already set. This might need some fixing. */
12450 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12451 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12453 tng_block_init(&block);
12454 tng_data->input_file = tng_data->output_file;
12456 curr_pos = ftell(tng_data->output_file);
12457 fseek(tng_data->output_file,
12458 (long)frame_set->medium_stride_prev_frame_set_file_pos,
12461 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12463 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12464 __FILE__, __LINE__);
12465 tng_data->input_file = temp;
12466 tng_block_destroy(&block);
12467 return(TNG_CRITICAL);
12470 /* Read the next frame set from the previous frame set and one
12471 * medium stride step back */
12472 fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
12473 sizeof(int64_t), SEEK_CUR);
12474 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12475 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12476 1, tng_data->output_file) == 0)
12478 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12479 tng_data->input_file = temp;
12480 tng_block_destroy(&block);
12481 return(TNG_CRITICAL);
12484 if(tng_data->input_endianness_swap_func_64)
12486 if(tng_data->input_endianness_swap_func_64(tng_data,
12487 &frame_set->medium_stride_prev_frame_set_file_pos)
12490 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12491 __FILE__, __LINE__);
12495 tng_block_destroy(&block);
12497 /* Set the long range pointers */
12498 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12500 frame_set->long_stride_prev_frame_set_file_pos =
12501 tng_data->first_trajectory_frame_set_output_file_pos;
12503 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12505 /* FIXME: Currently only working if the previous frame set has its
12506 * long stride pointer already set. This might need some fixing. */
12507 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12508 frame_set->long_stride_prev_frame_set_file_pos != 0)
12510 tng_block_init(&block);
12511 tng_data->input_file = tng_data->output_file;
12513 fseek(tng_data->output_file,
12514 (long)frame_set->long_stride_prev_frame_set_file_pos,
12517 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12519 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12520 __FILE__, __LINE__);
12521 tng_data->input_file = temp;
12522 tng_block_destroy(&block);
12523 return(TNG_CRITICAL);
12526 /* Read the next frame set from the previous frame set and one
12527 * long stride step back */
12528 fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
12529 sizeof(int64_t), SEEK_CUR);
12531 tng_block_destroy(&block);
12533 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12534 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12535 1, tng_data->output_file) == 0)
12537 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12538 tng_data->input_file = temp;
12539 return(TNG_CRITICAL);
12542 if(tng_data->input_endianness_swap_func_64)
12544 if(tng_data->input_endianness_swap_func_64(tng_data,
12545 &frame_set->long_stride_prev_frame_set_file_pos)
12548 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12549 __FILE__, __LINE__);
12556 tng_data->input_file = temp;
12557 fseek(tng_data->output_file, (long)curr_pos, SEEK_SET);
12561 frame_set->first_frame = first_frame;
12562 frame_set->n_frames = n_frames;
12563 frame_set->n_written_frames = 0;
12564 frame_set->n_unwritten_frames = 0;
12565 frame_set->first_frame_time = -1;
12567 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12568 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12570 tng_data->first_trajectory_frame_set_output_file_pos =
12571 tng_data->current_trajectory_frame_set_output_file_pos;
12573 /* FIXME: Should check the frame number instead of the file_pos,
12574 * in case frame sets are not in order */
12575 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12576 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12577 tng_data->last_trajectory_frame_set_output_file_pos <
12578 tng_data->current_trajectory_frame_set_output_file_pos)
12580 tng_data->last_trajectory_frame_set_output_file_pos =
12581 tng_data->current_trajectory_frame_set_output_file_pos;
12584 return(TNG_SUCCESS);
12587 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12588 (tng_trajectory_t tng_data,
12589 const int64_t first_frame,
12590 const int64_t n_frames,
12591 const double first_frame_time)
12593 tng_function_status stat;
12595 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12596 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12597 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12598 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12601 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12602 if(stat != TNG_SUCCESS)
12606 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12611 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12612 (tng_trajectory_t tng_data,
12613 const double first_frame_time)
12615 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12616 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12618 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12620 return(TNG_SUCCESS);
12623 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12624 (tng_trajectory_t tng_data,
12627 long file_pos, next_frame_set_file_pos;
12628 tng_gen_block_t block;
12629 tng_function_status stat;
12631 tng_trajectory_frame_set_t frame_set;
12633 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12634 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12635 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12637 file_pos = ftell(tng_data->input_file);
12639 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12641 next_frame_set_file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12645 frame_set = &tng_data->current_trajectory_frame_set;
12646 next_frame_set_file_pos = (long)frame_set->next_frame_set_file_pos;
12649 if(next_frame_set_file_pos <= 0)
12651 return(TNG_FAILURE);
12654 fseek(tng_data->input_file, (long)next_frame_set_file_pos, SEEK_SET);
12655 /* Read block headers first to see that a frame set block is found. */
12656 tng_block_init(&block);
12657 stat = tng_block_header_read(tng_data, block);
12658 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12660 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12661 file_pos, __FILE__, __LINE__);
12662 return(TNG_CRITICAL);
12664 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12666 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12668 tng_block_destroy(&block);
12670 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12672 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12673 __FILE__, __LINE__);
12674 return(TNG_CRITICAL);
12676 fseek(tng_data->input_file, file_pos, SEEK_SET);
12678 return(TNG_SUCCESS);
12681 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12682 (tng_trajectory_t tng_data,
12684 const char *block_name,
12685 const char datatype,
12686 const char block_type_flag,
12688 const int64_t n_values_per_frame,
12689 int64_t stride_length,
12690 const int64_t codec_id,
12693 int i, j, size, len;
12694 tng_trajectory_frame_set_t frame_set;
12695 tng_non_particle_data_t data;
12696 char **first_dim_values;
12697 char *new_data_c=new_data;
12698 int64_t n_frames_div;
12700 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12701 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12702 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12704 frame_set = &tng_data->current_trajectory_frame_set;
12706 if(stride_length <= 0)
12711 /* If the block does not exist, create it */
12712 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
12714 if(tng_data_block_create(tng_data, block_type_flag) !=
12717 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
12718 __FILE__, __LINE__);
12719 return(TNG_CRITICAL);
12721 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12723 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12727 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12729 data->block_id = id;
12731 data->block_name = malloc(strlen(block_name) + 1);
12732 if(!data->block_name)
12734 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12735 (int)strlen(block_name)+1, __FILE__, __LINE__);
12736 return(TNG_CRITICAL);
12738 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12741 /* FIXME: Memory leak from strings. */
12743 data->last_retrieved_frame = -1;
12746 data->datatype = datatype;
12747 data->stride_length = tng_max_i64(stride_length, 1);
12748 data->n_values_per_frame = n_values_per_frame;
12749 data->n_frames = n_frames;
12750 data->codec_id = codec_id;
12751 data->compression_multiplier = 1.0;
12752 /* FIXME: This can cause problems. */
12753 data->first_frame_with_data = frame_set->first_frame;
12757 case TNG_FLOAT_DATA:
12758 size = sizeof(float);
12761 size = sizeof(int64_t);
12763 case TNG_DOUBLE_DATA:
12765 size = sizeof(double);
12771 /* Allocate memory */
12772 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12773 n_values_per_frame) !=
12776 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
12777 __FILE__, __LINE__);
12778 return(TNG_CRITICAL);
12781 if(n_frames > frame_set->n_unwritten_frames)
12783 frame_set->n_unwritten_frames = n_frames;
12786 n_frames_div = (n_frames % stride_length) ?
12787 n_frames / stride_length + 1:
12788 n_frames / stride_length;
12790 if(datatype == TNG_CHAR_DATA)
12792 for(i = 0; i < n_frames_div; i++)
12794 first_dim_values = data->strings[i];
12795 for(j = 0; j < n_values_per_frame; j++)
12797 len = tng_min_i((int)strlen(new_data_c) + 1,
12799 if(first_dim_values[j])
12801 free(first_dim_values[j]);
12803 first_dim_values[j] = malloc(len);
12804 if(!first_dim_values[j])
12806 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12807 len, __FILE__, __LINE__);
12808 return(TNG_CRITICAL);
12810 strncpy(first_dim_values[j],
12818 memcpy(data->values, new_data, size * n_frames_div *
12819 n_values_per_frame);
12823 return(TNG_SUCCESS);
12826 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12827 (tng_trajectory_t tng_data,
12829 const char *block_name,
12830 const char datatype,
12831 const char block_type_flag,
12833 const int64_t n_values_per_frame,
12834 int64_t stride_length,
12835 const int64_t num_first_particle,
12836 const int64_t n_particles,
12837 const int64_t codec_id,
12842 int64_t tot_n_particles, n_frames_div;
12843 char ***first_dim_values, **second_dim_values;
12844 tng_trajectory_frame_set_t frame_set;
12845 tng_particle_data_t data;
12846 char *new_data_c=new_data;
12848 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12849 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12850 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12851 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12852 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12855 frame_set = &tng_data->current_trajectory_frame_set;
12857 if(stride_length <= 0)
12862 /* If the block does not exist, create it */
12863 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
12865 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
12868 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12869 __FILE__, __LINE__);
12870 return(TNG_CRITICAL);
12872 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12874 data = &frame_set->tr_particle_data[frame_set->
12875 n_particle_data_blocks - 1];
12879 data = &tng_data->non_tr_particle_data[tng_data->
12880 n_particle_data_blocks - 1];
12882 data->block_id = id;
12884 data->block_name = malloc(strlen(block_name) + 1);
12885 if(!data->block_name)
12887 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12888 (int)strlen(block_name)+1, __FILE__, __LINE__);
12889 return(TNG_CRITICAL);
12891 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12893 data->datatype = datatype;
12896 /* FIXME: Memory leak from strings. */
12898 data->last_retrieved_frame = -1;
12901 data->stride_length = tng_max_i64(stride_length, 1);
12902 data->n_values_per_frame = n_values_per_frame;
12903 data->n_frames = n_frames;
12904 data->codec_id = codec_id;
12905 data->compression_multiplier = 1.0;
12906 /* FIXME: This can cause problems. */
12907 data->first_frame_with_data = frame_set->first_frame;
12909 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12911 tot_n_particles = frame_set->n_particles;
12915 tot_n_particles = tng_data->n_particles;
12918 /* If data values are supplied add that data to the data block. */
12921 /* Allocate memory */
12922 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
12923 stride_length, tot_n_particles,
12924 n_values_per_frame) !=
12927 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12928 __FILE__, __LINE__);
12929 return(TNG_CRITICAL);
12932 if(n_frames > frame_set->n_unwritten_frames)
12934 frame_set->n_unwritten_frames = n_frames;
12937 n_frames_div = (n_frames % stride_length) ?
12938 n_frames / stride_length + 1:
12939 n_frames / stride_length;
12941 if(datatype == TNG_CHAR_DATA)
12943 for(i = 0; i < n_frames_div; i++)
12945 first_dim_values = data->strings[i];
12946 for(j = num_first_particle; j < num_first_particle + n_particles;
12949 second_dim_values = first_dim_values[j];
12950 for(k = 0; k < n_values_per_frame; k++)
12952 len = tng_min_i((int)strlen(new_data_c) + 1,
12954 if(second_dim_values[k])
12956 free(second_dim_values[k]);
12958 second_dim_values[k] = malloc(len);
12959 if(!second_dim_values[k])
12961 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12962 len, __FILE__, __LINE__);
12963 return(TNG_CRITICAL);
12965 strncpy(second_dim_values[k],
12977 size = sizeof(int64_t);
12979 case TNG_FLOAT_DATA:
12980 size = sizeof(float);
12982 case TNG_DOUBLE_DATA:
12984 size = sizeof(double);
12987 memcpy(data->values, new_data, size * n_frames_div *
12988 n_particles * n_values_per_frame);
12992 return(TNG_SUCCESS);
12995 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12996 (tng_trajectory_t tng_data,
13002 tng_trajectory_frame_set_t frame_set;
13003 tng_function_status stat;
13004 tng_particle_data_t p_data;
13005 tng_non_particle_data_t np_data;
13006 int block_type = -1;
13008 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13009 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13011 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13013 p_data = &tng_data->non_tr_particle_data[i];
13014 if(p_data->block_id == block_id)
13016 strncpy(name, p_data->block_name, max_len);
13017 name[max_len - 1] = '\0';
13018 return(TNG_SUCCESS);
13021 for(i = 0; i < tng_data->n_data_blocks; i++)
13023 np_data = &tng_data->non_tr_data[i];
13024 if(np_data->block_id == block_id)
13026 strncpy(name, np_data->block_name, max_len);
13027 name[max_len - 1] = '\0';
13028 return(TNG_SUCCESS);
13032 frame_set = &tng_data->current_trajectory_frame_set;
13034 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13035 if(stat == TNG_SUCCESS)
13037 block_type = TNG_PARTICLE_BLOCK_DATA;
13041 stat = tng_data_find(tng_data, block_id, &np_data);
13042 if(stat == TNG_SUCCESS)
13044 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13048 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13049 if(stat != TNG_SUCCESS)
13053 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13054 if(stat == TNG_SUCCESS)
13056 block_type = TNG_PARTICLE_BLOCK_DATA;
13060 stat = tng_data_find(tng_data, block_id, &np_data);
13061 if(stat == TNG_SUCCESS)
13063 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13068 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13070 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13072 p_data = &frame_set->tr_particle_data[i];
13073 if(p_data->block_id == block_id)
13075 strncpy(name, p_data->block_name, max_len);
13076 name[max_len - 1] = '\0';
13077 return(TNG_SUCCESS);
13081 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13083 for(i = 0; i < frame_set->n_data_blocks; i++)
13085 np_data = &frame_set->tr_data[i];
13086 if(np_data->block_id == block_id)
13088 strncpy(name, np_data->block_name, max_len);
13089 name[max_len - 1] = '\0';
13090 return(TNG_SUCCESS);
13095 return(TNG_FAILURE);
13098 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13099 (tng_trajectory_t tng_data,
13101 int *block_dependency)
13104 tng_function_status stat;
13105 tng_particle_data_t p_data;
13106 tng_non_particle_data_t np_data;
13108 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13109 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13111 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13113 p_data = &tng_data->non_tr_particle_data[i];
13114 if(p_data->block_id == block_id)
13116 *block_dependency = TNG_PARTICLE_DEPENDENT;
13117 return(TNG_SUCCESS);
13120 for(i = 0; i < tng_data->n_data_blocks; i++)
13122 np_data = &tng_data->non_tr_data[i];
13123 if(np_data->block_id == block_id)
13125 *block_dependency = 0;
13126 return(TNG_SUCCESS);
13130 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13131 if(stat == TNG_SUCCESS)
13133 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13134 return(TNG_SUCCESS);
13138 stat = tng_data_find(tng_data, block_id, &np_data);
13139 if(stat == TNG_SUCCESS)
13141 *block_dependency = TNG_FRAME_DEPENDENT;
13142 return(TNG_SUCCESS);
13146 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13147 if(stat != TNG_SUCCESS)
13151 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13152 if(stat == TNG_SUCCESS)
13154 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13155 return(TNG_SUCCESS);
13159 stat = tng_data_find(tng_data, block_id, &np_data);
13160 if(stat == TNG_SUCCESS)
13162 *block_dependency = TNG_FRAME_DEPENDENT;
13163 return(TNG_SUCCESS);
13169 return(TNG_FAILURE);
13172 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13173 (tng_trajectory_t tng_data,
13175 int64_t *n_values_per_frame)
13178 tng_function_status stat;
13179 tng_particle_data_t p_data;
13180 tng_non_particle_data_t np_data;
13182 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13183 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13185 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13187 p_data = &tng_data->non_tr_particle_data[i];
13188 if(p_data->block_id == block_id)
13190 *n_values_per_frame = p_data->n_values_per_frame;
13191 return(TNG_SUCCESS);
13194 for(i = 0; i < tng_data->n_data_blocks; i++)
13196 np_data = &tng_data->non_tr_data[i];
13197 if(np_data->block_id == block_id)
13199 *n_values_per_frame = np_data->n_values_per_frame;
13200 return(TNG_SUCCESS);
13204 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13205 if(stat == TNG_SUCCESS)
13207 *n_values_per_frame = p_data->n_values_per_frame;
13208 return(TNG_SUCCESS);
13212 stat = tng_data_find(tng_data, block_id, &np_data);
13213 if(stat == TNG_SUCCESS)
13215 *n_values_per_frame = np_data->n_values_per_frame;
13216 return(TNG_SUCCESS);
13220 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13221 if(stat != TNG_SUCCESS)
13225 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13226 if(stat == TNG_SUCCESS)
13228 *n_values_per_frame = p_data->n_values_per_frame;
13229 return(TNG_SUCCESS);
13233 stat = tng_data_find(tng_data, block_id, &np_data);
13234 if(stat == TNG_SUCCESS)
13236 *n_values_per_frame = np_data->n_values_per_frame;
13237 return(TNG_SUCCESS);
13243 return(TNG_FAILURE);
13246 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13247 (tng_trajectory_t tng_data,
13248 const int64_t frame_nr,
13249 const int64_t block_id,
13250 const void *values,
13251 const char hash_mode)
13253 int64_t header_pos, file_pos;
13254 int64_t output_file_len, n_values_per_frame, size, contents_size;
13255 int64_t header_size, temp_first, temp_last;
13256 int64_t i, last_frame;
13258 tng_gen_block_t block;
13259 tng_trajectory_frame_set_t frame_set;
13260 FILE *temp = tng_data->input_file;
13261 struct tng_non_particle_data data;
13262 tng_function_status stat;
13263 char dependency, sparse_data, datatype;
13266 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13267 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13268 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13270 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13272 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13273 __FILE__, __LINE__);
13274 return(TNG_CRITICAL);
13277 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13278 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13279 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13280 tng_data->first_trajectory_frame_set_input_file_pos =
13281 tng_data->first_trajectory_frame_set_output_file_pos;
13282 tng_data->last_trajectory_frame_set_input_file_pos =
13283 tng_data->last_trajectory_frame_set_output_file_pos;
13284 tng_data->current_trajectory_frame_set_input_file_pos =
13285 tng_data->current_trajectory_frame_set_output_file_pos;
13287 tng_data->input_file = tng_data->output_file;
13289 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13291 frame_set = &tng_data->current_trajectory_frame_set;
13293 if(stat != TNG_SUCCESS)
13295 last_frame = frame_set->first_frame +
13296 frame_set->n_frames - 1;
13297 /* If the wanted frame would be in the frame set after the last
13298 * frame set create a new frame set. */
13299 if(stat == TNG_FAILURE &&
13300 last_frame < frame_nr)
13301 /* (last_frame < frame_nr &&
13302 tng_data->current_trajectory_frame_set.first_frame +
13303 tng_data->frame_set_n_frames >= frame_nr))*/
13305 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13307 last_frame = frame_nr - 1;
13309 tng_frame_set_new(tng_data,
13311 tng_data->frame_set_n_frames);
13312 file_pos = ftell(tng_data->output_file);
13313 fseek(tng_data->output_file, 0, SEEK_END);
13314 output_file_len = ftell(tng_data->output_file);
13315 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13317 /* Read mapping blocks from the last frame set */
13318 tng_block_init(&block);
13320 stat = tng_block_header_read(tng_data, block);
13321 while(file_pos < output_file_len &&
13322 stat != TNG_CRITICAL &&
13323 block->id != TNG_TRAJECTORY_FRAME_SET)
13325 if(block->id == TNG_PARTICLE_MAPPING)
13327 tng_trajectory_mapping_block_read(tng_data, block,
13332 fseek(tng_data->output_file, (long)block->block_contents_size,
13335 file_pos = ftell(tng_data->output_file);
13336 if(file_pos < output_file_len)
13338 stat = tng_block_header_read(tng_data, block);
13342 tng_block_destroy(&block);
13343 /* Write the frame set to disk */
13344 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13346 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13347 return(TNG_CRITICAL);
13352 tng_data->input_file = temp;
13353 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13354 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13355 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13360 tng_block_init(&block);
13362 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13364 fseek(tng_data->output_file, 0, SEEK_END);
13365 output_file_len = ftell(tng_data->output_file);
13366 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13368 /* Read past the frame set block first */
13369 stat = tng_block_header_read(tng_data, block);
13370 if(stat == TNG_CRITICAL)
13372 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13373 file_pos, __FILE__, __LINE__);
13374 tng_block_destroy(&block);
13375 tng_data->input_file = temp;
13377 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13378 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13379 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13382 fseek(tng_data->output_file, (long)block->block_contents_size,
13385 /* Read all block headers until next frame set block or
13386 * until the wanted block id is found */
13387 stat = tng_block_header_read(tng_data, block);
13388 while(file_pos < output_file_len &&
13389 stat != TNG_CRITICAL &&
13390 block->id != block_id &&
13391 block->id != TNG_TRAJECTORY_FRAME_SET)
13393 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
13394 file_pos = ftell(tng_data->output_file);
13395 if(file_pos < output_file_len)
13397 stat = tng_block_header_read(tng_data, block);
13400 if(stat == TNG_CRITICAL)
13402 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13403 file_pos, __FILE__, __LINE__);
13404 tng_block_destroy(&block);
13405 tng_data->input_file = temp;
13406 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13407 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13408 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13412 contents_size = block->block_contents_size;
13413 header_size = block->header_contents_size;
13415 header_pos = ftell(tng_data->output_file) - header_size;
13416 frame_set = &tng_data->current_trajectory_frame_set;
13418 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
13420 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13421 tng_block_destroy(&block);
13422 return(TNG_CRITICAL);
13424 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
13426 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13427 tng_block_destroy(&block);
13428 return(TNG_CRITICAL);
13430 data.datatype = datatype;
13432 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13433 (dependency & TNG_PARTICLE_DEPENDENT))
13435 tng_block_destroy(&block);
13436 tng_data->input_file = temp;
13438 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13439 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13440 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13441 return(TNG_FAILURE);
13444 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
13446 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13447 tng_block_destroy(&block);
13448 return(TNG_CRITICAL);
13451 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
13452 tng_data->input_file) == 0)
13454 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13455 tng_block_destroy(&block);
13456 return(TNG_CRITICAL);
13458 if(tng_data->output_endianness_swap_func_64)
13460 if(tng_data->output_endianness_swap_func_64(tng_data,
13461 &data.n_values_per_frame)
13464 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13465 __FILE__, __LINE__);
13469 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
13470 tng_data->input_file) == 0)
13472 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13473 tng_block_destroy(&block);
13474 return(TNG_CRITICAL);
13476 if(tng_data->output_endianness_swap_func_64)
13478 if(tng_data->output_endianness_swap_func_64(tng_data,
13482 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13483 __FILE__, __LINE__);
13487 if(data.codec_id != TNG_UNCOMPRESSED)
13489 if(fread(&data.compression_multiplier,
13490 sizeof(data.compression_multiplier), 1, tng_data->input_file)
13493 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13494 tng_block_destroy(&block);
13495 return(TNG_CRITICAL);
13497 if(tng_data->output_endianness_swap_func_64)
13499 if(tng_data->output_endianness_swap_func_64(tng_data,
13500 (int64_t *)&data.compression_multiplier)
13503 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13504 __FILE__, __LINE__);
13510 data.compression_multiplier = 1;
13515 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
13516 1, tng_data->input_file) == 0)
13518 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13519 tng_block_destroy(&block);
13520 return(TNG_CRITICAL);
13522 if(tng_data->output_endianness_swap_func_64)
13524 if(tng_data->output_endianness_swap_func_64(tng_data,
13525 &data.first_frame_with_data)
13528 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13529 __FILE__, __LINE__);
13533 if(fread(&data.stride_length, sizeof(data.stride_length),
13534 1, tng_data->input_file) == 0)
13536 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13537 tng_block_destroy(&block);
13538 return(TNG_CRITICAL);
13540 if(tng_data->output_endianness_swap_func_64)
13542 if(tng_data->output_endianness_swap_func_64(tng_data,
13543 &data.stride_length)
13546 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13547 __FILE__, __LINE__);
13553 data.first_frame_with_data = 0;
13554 data.stride_length = 1;
13556 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13558 tng_data->input_file = temp;
13560 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13561 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13562 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13564 switch(data.datatype)
13566 case(TNG_INT_DATA):
13567 size = sizeof(int64_t);
13569 case(TNG_FLOAT_DATA):
13570 size = sizeof(float);
13572 case(TNG_DOUBLE_DATA):
13573 size = sizeof(double);
13576 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13578 tng_block_destroy(&block);
13579 return(TNG_FAILURE);
13582 n_values_per_frame = data.n_values_per_frame;
13584 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13585 data.first_frame_with_data)) /
13586 data.stride_length;
13587 file_pos *= size * n_values_per_frame;
13589 if(file_pos > contents_size)
13591 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13593 tng_block_destroy(&block);
13594 return(TNG_FAILURE);
13597 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
13599 /* If the endianness is not big endian the data needs to be swapped */
13600 if((data.datatype == TNG_INT_DATA ||
13601 data.datatype == TNG_DOUBLE_DATA) &&
13602 tng_data->output_endianness_swap_func_64)
13604 copy = malloc(n_values_per_frame * size);
13605 memcpy(copy, values, n_values_per_frame * size);
13606 for(i = 0; i < n_values_per_frame; i++)
13608 if(tng_data->output_endianness_swap_func_64(tng_data,
13612 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13613 __FILE__, __LINE__);
13616 fwrite(copy, n_values_per_frame, size,
13617 tng_data->output_file);
13620 else if(data.datatype == TNG_FLOAT_DATA &&
13621 tng_data->output_endianness_swap_func_32)
13623 copy = malloc(n_values_per_frame * size);
13624 memcpy(copy, values, n_values_per_frame * size);
13625 for(i = 0; i < n_values_per_frame; i++)
13627 if(tng_data->output_endianness_swap_func_32(tng_data,
13631 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13632 __FILE__, __LINE__);
13635 fwrite(copy, n_values_per_frame, size,
13636 tng_data->output_file);
13642 fwrite(values, n_values_per_frame, size, tng_data->output_file);
13645 fflush(tng_data->output_file);
13647 /* Update the number of written frames in the frame set. */
13648 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13650 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13653 /* If the last frame has been written update the hash */
13654 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13655 data.first_frame_with_data) >=
13656 frame_set->n_frames)
13658 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13662 tng_block_destroy(&block);
13664 return(TNG_SUCCESS);
13667 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13668 (tng_trajectory_t tng_data,
13669 const int64_t frame_nr,
13670 const int64_t block_id,
13671 const int64_t val_first_particle,
13672 const int64_t val_n_particles,
13673 const void *values,
13674 const char hash_mode)
13676 int64_t header_pos, file_pos, tot_n_particles;
13677 int64_t output_file_len, n_values_per_frame, size, contents_size;
13678 int64_t header_size, temp_first, temp_last;
13679 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13680 int64_t i, last_frame;
13682 tng_gen_block_t block;
13683 tng_trajectory_frame_set_t frame_set;
13684 FILE *temp = tng_data->input_file;
13685 struct tng_particle_data data;
13686 tng_function_status stat;
13687 tng_particle_mapping_t mapping;
13688 char dependency, sparse_data, datatype;
13691 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13692 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13693 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13694 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13695 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13697 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13699 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13700 __FILE__, __LINE__);
13701 return(TNG_CRITICAL);
13704 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13705 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13706 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13707 tng_data->first_trajectory_frame_set_input_file_pos =
13708 tng_data->first_trajectory_frame_set_output_file_pos;
13709 tng_data->last_trajectory_frame_set_input_file_pos =
13710 tng_data->last_trajectory_frame_set_output_file_pos;
13711 tng_data->current_trajectory_frame_set_input_file_pos =
13712 tng_data->current_trajectory_frame_set_output_file_pos;
13714 tng_data->input_file = tng_data->output_file;
13716 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13718 frame_set = &tng_data->current_trajectory_frame_set;
13720 if(stat != TNG_SUCCESS)
13722 last_frame = frame_set->first_frame +
13723 frame_set->n_frames - 1;
13724 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
13726 /* If the wanted frame would be in the frame set after the last
13727 * frame set create a new frame set. */
13728 if(stat == TNG_FAILURE &&
13729 (last_frame < frame_nr &&
13730 last_frame + tng_data->frame_set_n_frames >= frame_nr))
13732 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13734 last_frame = frame_nr - 1;
13736 tng_frame_set_new(tng_data,
13738 tng_data->frame_set_n_frames);
13740 file_pos = ftell(tng_data->output_file);
13741 fseek(tng_data->output_file, 0, SEEK_END);
13742 output_file_len = ftell(tng_data->output_file);
13743 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13745 /* Read mapping blocks from the last frame set */
13746 tng_block_init(&block);
13748 stat = tng_block_header_read(tng_data, block);
13749 while(file_pos < output_file_len &&
13750 stat != TNG_CRITICAL &&
13751 block->id != TNG_TRAJECTORY_FRAME_SET)
13753 if(block->id == TNG_PARTICLE_MAPPING)
13755 tng_trajectory_mapping_block_read(tng_data, block,
13760 fseek(tng_data->output_file, (long)block->block_contents_size,
13763 file_pos = ftell(tng_data->output_file);
13764 if(file_pos < output_file_len)
13766 stat = tng_block_header_read(tng_data, block);
13770 tng_block_destroy(&block);
13771 /* Write the frame set to disk */
13772 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13774 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13780 tng_data->input_file = temp;
13781 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13782 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13783 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13789 tng_block_init(&block);
13791 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13793 fseek(tng_data->output_file, 0, SEEK_END);
13794 output_file_len = ftell(tng_data->output_file);
13795 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
13797 /* Read past the frame set block first */
13798 stat = tng_block_header_read(tng_data, block);
13799 if(stat == TNG_CRITICAL)
13801 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13802 file_pos, __FILE__, __LINE__);
13803 tng_block_destroy(&block);
13804 tng_data->input_file = temp;
13806 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13807 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13808 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13811 fseek(tng_data->output_file, (long)block->block_contents_size,
13814 if(tng_data->var_num_atoms_flag)
13816 tot_n_particles = frame_set->n_particles;
13820 tot_n_particles = tng_data->n_particles;
13823 if(val_n_particles < tot_n_particles)
13825 mapping_block_end_pos = -1;
13826 /* Read all mapping blocks to find the right place to put the data */
13827 stat = tng_block_header_read(tng_data, block);
13828 while(file_pos < output_file_len &&
13829 stat != TNG_CRITICAL &&
13830 block->id != TNG_TRAJECTORY_FRAME_SET)
13832 if(block->id == TNG_PARTICLE_MAPPING)
13834 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13838 fseek(tng_data->output_file, (long)block->block_contents_size,
13841 file_pos = ftell(tng_data->output_file);
13842 if(block->id == TNG_PARTICLE_MAPPING)
13844 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13845 if(val_first_particle >= mapping->num_first_particle &&
13846 val_first_particle < mapping->num_first_particle +
13847 mapping->n_particles &&
13848 val_first_particle + val_n_particles <=
13849 mapping->num_first_particle + mapping->n_particles)
13851 mapping_block_end_pos = file_pos;
13854 if(file_pos < output_file_len)
13856 stat = tng_block_header_read(tng_data, block);
13859 if(stat == TNG_CRITICAL)
13861 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13862 file_pos, __FILE__, __LINE__);
13863 tng_block_destroy(&block);
13864 tng_data->input_file = temp;
13866 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13867 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13868 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13871 if(mapping_block_end_pos < 0)
13873 tng_block_destroy(&block);
13874 tng_data->input_file = temp;
13876 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13877 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13878 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13879 return(TNG_FAILURE);
13881 fseek(tng_data->output_file, (long)mapping_block_end_pos, SEEK_SET);
13884 /* Read all block headers until next frame set block or
13885 * until the wanted block id is found */
13886 stat = tng_block_header_read(tng_data, block);
13887 while(file_pos < output_file_len &&
13888 stat != TNG_CRITICAL &&
13889 block->id != block_id &&
13890 block->id != TNG_PARTICLE_MAPPING &&
13891 block->id != TNG_TRAJECTORY_FRAME_SET)
13893 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
13894 file_pos = ftell(tng_data->output_file);
13895 if(file_pos < output_file_len)
13897 stat = tng_block_header_read(tng_data, block);
13900 if(stat == TNG_CRITICAL)
13902 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13903 file_pos, __FILE__, __LINE__);
13904 tng_block_destroy(&block);
13905 tng_data->input_file = temp;
13907 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13908 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13909 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13913 contents_size = block->block_contents_size;
13914 header_size = block->header_contents_size;
13916 header_pos = ftell(tng_data->output_file) - header_size;
13917 frame_set = &tng_data->current_trajectory_frame_set;
13919 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
13921 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13922 tng_block_destroy(&block);
13923 return(TNG_CRITICAL);
13926 data.datatype = datatype;
13928 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
13930 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13931 tng_block_destroy(&block);
13932 return(TNG_CRITICAL);
13935 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13936 !(dependency & TNG_PARTICLE_DEPENDENT))
13938 tng_block_destroy(&block);
13939 tng_data->input_file = temp;
13941 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13942 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13943 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13944 return(TNG_FAILURE);
13947 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
13949 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13950 tng_block_destroy(&block);
13951 return(TNG_CRITICAL);
13954 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
13955 tng_data->input_file) == 0)
13957 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13958 tng_block_destroy(&block);
13959 return(TNG_CRITICAL);
13961 if(tng_data->output_endianness_swap_func_64)
13963 if(tng_data->output_endianness_swap_func_64(tng_data,
13964 &data.n_values_per_frame)
13967 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13968 __FILE__, __LINE__);
13972 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
13973 tng_data->input_file) == 0)
13975 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13976 tng_block_destroy(&block);
13977 return(TNG_CRITICAL);
13979 if(tng_data->output_endianness_swap_func_64)
13981 if(tng_data->output_endianness_swap_func_64(tng_data,
13985 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13986 __FILE__, __LINE__);
13990 if(data.codec_id != TNG_UNCOMPRESSED)
13992 if(fread(&data.compression_multiplier,
13993 sizeof(data.compression_multiplier), 1, tng_data->input_file)
13996 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
13997 tng_block_destroy(&block);
13998 return(TNG_CRITICAL);
14001 if(tng_data->output_endianness_swap_func_64)
14003 if(tng_data->output_endianness_swap_func_64(tng_data,
14004 (int64_t *)&data.compression_multiplier)
14007 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14008 __FILE__, __LINE__);
14014 data.compression_multiplier = 1;
14019 if(fread(&data.first_frame_with_data,
14020 sizeof(data.first_frame_with_data),
14021 1, tng_data->input_file) == 0)
14023 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14024 tng_block_destroy(&block);
14025 return(TNG_CRITICAL);
14027 if(tng_data->output_endianness_swap_func_64)
14029 if(tng_data->output_endianness_swap_func_64(tng_data,
14030 &data.first_frame_with_data)
14033 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14034 __FILE__, __LINE__);
14038 if(fread(&data.stride_length, sizeof(data.stride_length),
14039 1, tng_data->input_file) == 0)
14041 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14042 tng_block_destroy(&block);
14043 return(TNG_CRITICAL);
14045 if(tng_data->output_endianness_swap_func_64)
14047 if(tng_data->output_endianness_swap_func_64(tng_data,
14048 &data.stride_length)
14051 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14052 __FILE__, __LINE__);
14058 data.first_frame_with_data = 0;
14059 data.stride_length = 1;
14061 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14063 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14064 tng_data->input_file) == 0)
14066 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14067 tng_block_destroy(&block);
14068 return(TNG_CRITICAL);
14070 if(tng_data->output_endianness_swap_func_64)
14072 if(tng_data->output_endianness_swap_func_64(tng_data,
14073 &num_first_particle)
14076 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14077 __FILE__, __LINE__);
14081 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14082 tng_data->input_file) == 0)
14084 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14085 tng_block_destroy(&block);
14086 return(TNG_CRITICAL);
14088 if(tng_data->output_endianness_swap_func_64)
14090 if(tng_data->output_endianness_swap_func_64(tng_data,
14091 &block_n_particles)
14094 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14095 __FILE__, __LINE__);
14100 tng_data->input_file = temp;
14102 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14103 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14104 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14107 switch(data.datatype)
14109 case(TNG_INT_DATA):
14110 size = sizeof(int64_t);
14112 case(TNG_FLOAT_DATA):
14113 size = sizeof(float);
14115 case(TNG_DOUBLE_DATA):
14116 size = sizeof(double);
14119 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14121 tng_block_destroy(&block);
14122 return(TNG_FAILURE);
14125 n_values_per_frame = data.n_values_per_frame;
14127 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14128 data.first_frame_with_data)) /
14129 data.stride_length;
14130 file_pos *= block_n_particles * size * n_values_per_frame;
14132 if(file_pos > contents_size)
14134 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14136 tng_block_destroy(&block);
14137 return(TNG_FAILURE);
14140 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14142 /* If the endianness is not big endian the data needs to be swapped */
14143 if((data.datatype == TNG_INT_DATA ||
14144 data.datatype == TNG_DOUBLE_DATA) &&
14145 tng_data->output_endianness_swap_func_64)
14147 copy = malloc(val_n_particles * n_values_per_frame * size);
14148 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14149 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14151 if(tng_data->output_endianness_swap_func_64(tng_data,
14152 (int64_t *) copy+i)
14155 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14156 __FILE__, __LINE__);
14159 fwrite(copy, val_n_particles * n_values_per_frame, size,
14160 tng_data->output_file);
14163 else if(data.datatype == TNG_FLOAT_DATA &&
14164 tng_data->output_endianness_swap_func_32)
14166 copy = malloc(val_n_particles * n_values_per_frame * size);
14167 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14168 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14170 if(tng_data->output_endianness_swap_func_32(tng_data,
14171 (int32_t *) copy+i)
14174 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14175 __FILE__, __LINE__);
14178 fwrite(copy, val_n_particles * n_values_per_frame, size,
14179 tng_data->output_file);
14185 fwrite(values, val_n_particles * n_values_per_frame, size,
14186 tng_data->output_file);
14188 fflush(tng_data->output_file);
14190 /* Update the number of written frames in the frame set. */
14191 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14193 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14196 /* If the last frame has been written update the hash */
14197 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14198 data.first_frame_with_data) >=
14199 frame_set->n_frames)
14201 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14205 tng_block_destroy(&block);
14206 return(TNG_SUCCESS);
14209 static tng_function_status tng_data_values_alloc
14210 (const tng_trajectory_t tng_data,
14211 union data_values ***values,
14212 const int64_t n_frames,
14213 const int64_t n_values_per_frame,
14217 tng_function_status stat;
14219 if(n_frames <= 0 || n_values_per_frame <= 0)
14221 return(TNG_FAILURE);
14226 stat = tng_data_values_free(tng_data, *values, n_frames,
14227 n_values_per_frame,
14229 if(stat != TNG_SUCCESS)
14231 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
14232 __FILE__, __LINE__);
14236 *values = malloc(sizeof(union data_values *) * n_frames);
14239 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14240 sizeof(union data_values **) * n_frames,
14241 __FILE__, __LINE__);
14242 return(TNG_CRITICAL);
14246 for(i = n_frames; i--;)
14248 (*values)[i] = malloc(sizeof(union data_values) *
14249 n_values_per_frame);
14252 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14253 sizeof(union data_values) * n_values_per_frame,
14254 __FILE__, __LINE__);
14257 return(TNG_CRITICAL);
14260 return(TNG_SUCCESS);
14263 /* FIXME: This needs ***values */
14264 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
14265 (const tng_trajectory_t tng_data,
14266 union data_values **values,
14267 const int64_t n_frames,
14268 const int64_t n_values_per_frame,
14276 for(i = 0; i < n_frames; i++)
14280 if(type == TNG_CHAR_DATA)
14282 for(j = n_values_per_frame; j--;)
14286 free(values[i][j].c);
14287 values[i][j].c = 0;
14299 return(TNG_SUCCESS);
14302 static tng_function_status tng_particle_data_values_alloc
14303 (const tng_trajectory_t tng_data,
14304 union data_values ****values,
14305 const int64_t n_frames,
14306 const int64_t n_particles,
14307 const int64_t n_values_per_frame,
14311 tng_function_status stat;
14313 if(n_particles == 0 || n_values_per_frame == 0)
14315 return(TNG_FAILURE);
14320 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
14321 n_particles, n_values_per_frame,
14323 if(stat != TNG_SUCCESS)
14325 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
14326 __FILE__, __LINE__);
14330 *values = malloc(sizeof(union data_values **) * n_frames);
14333 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14334 sizeof(union data_values **) * n_frames,
14335 __FILE__, __LINE__);
14336 return(TNG_CRITICAL);
14340 for(i = n_frames; i--;)
14342 (*values)[i] = malloc(sizeof(union data_values *) *
14346 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14347 sizeof(union data_values *) * n_particles,
14348 __FILE__, __LINE__);
14351 return(TNG_CRITICAL);
14353 for(j = n_particles; j--;)
14355 (*values)[i][j] = malloc(sizeof(union data_values) *
14356 n_values_per_frame);
14357 if(!(*values)[i][j])
14359 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14360 sizeof(union data_values *) * n_particles,
14361 __FILE__, __LINE__);
14362 tng_particle_data_values_free(tng_data, *values, n_frames,
14363 n_particles, n_values_per_frame,
14366 return(TNG_CRITICAL);
14370 return(TNG_SUCCESS);
14373 /* FIXME: This needs ****values */
14374 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
14375 (const tng_trajectory_t tng_data,
14376 union data_values ***values,
14377 const int64_t n_frames,
14378 const int64_t n_particles,
14379 const int64_t n_values_per_frame,
14387 for(i = 0; i < n_frames; i++)
14391 for(j = 0; j < n_particles; j++)
14393 if(type == TNG_CHAR_DATA)
14395 for(k = n_values_per_frame; k--;)
14397 if(values[i][j][k].c)
14399 free(values[i][j][k].c);
14400 values[i][j][k].c = 0;
14404 free(values[i][j]);
14415 return(TNG_SUCCESS);
14419 tng_function_status DECLSPECDLLEXPORT tng_data_get
14420 (tng_trajectory_t tng_data,
14421 const int64_t block_id,
14422 union data_values ***values,
14424 int64_t *n_values_per_frame,
14427 int64_t i, j, file_pos, block_index;
14430 tng_non_particle_data_t data;
14431 tng_trajectory_frame_set_t frame_set;
14432 tng_gen_block_t block;
14433 tng_function_status stat;
14435 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14436 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14437 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14438 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14440 frame_set = &tng_data->current_trajectory_frame_set;
14445 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
14447 tng_block_init(&block);
14448 file_pos = ftell(tng_data->input_file);
14449 /* Read all blocks until next frame set block */
14450 stat = tng_block_header_read(tng_data, block);
14451 while(file_pos < tng_data->input_file_len &&
14452 stat != TNG_CRITICAL &&
14453 block->id != TNG_TRAJECTORY_FRAME_SET)
14455 /* Use hash by default */
14456 stat = tng_block_read_next(tng_data, block,
14458 if(stat != TNG_CRITICAL)
14460 file_pos = ftell(tng_data->input_file);
14461 if(file_pos < tng_data->input_file_len)
14463 stat = tng_block_header_read(tng_data, block);
14467 tng_block_destroy(&block);
14468 if(stat == TNG_CRITICAL)
14470 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14471 file_pos, __FILE__, __LINE__);
14475 for(i = frame_set->n_data_blocks; i-- ;)
14477 data = &frame_set->tr_data[i];
14478 if(data->block_id == block_id)
14484 if(block_index < 0)
14486 return(TNG_FAILURE);
14490 *n_frames = tng_max_i64(1, data->n_frames);
14491 *n_values_per_frame = data->n_values_per_frame;
14492 *type = data->datatype;
14496 if(tng_data_values_alloc(tng_data, values, *n_frames,
14497 *n_values_per_frame,
14501 return(TNG_CRITICAL);
14507 case TNG_CHAR_DATA:
14508 for(i=*n_frames; i--;)
14510 for(j=*n_values_per_frame; j--;)
14512 len = strlen(data->strings[i][j]) + 1;
14513 (*values)[i][j].c = malloc(len);
14514 strncpy((*values)[i][j].c, data->strings[i][j], len);
14519 size = sizeof(int);
14520 for(i=*n_frames; i--;)
14522 for(j=*n_values_per_frame; j--;)
14524 (*values)[i][j].i = *(int *)((char *)data->values + size *
14525 (i*(*n_values_per_frame) + j));
14529 case TNG_FLOAT_DATA:
14530 size = sizeof(float);
14531 for(i=*n_frames; i--;)
14533 for(j=*n_values_per_frame; j--;)
14535 (*values)[i][j].f = *(float *)((char *)data->values + size *
14536 (i*(*n_values_per_frame) + j));
14540 case TNG_DOUBLE_DATA:
14542 size = sizeof(double);
14543 for(i=*n_frames; i--;)
14545 for(j=*n_values_per_frame; j--;)
14547 (*values)[i][j].d = *(double *)((char *)data->values + size *
14548 (i*(*n_values_per_frame) + j));
14553 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14555 return(TNG_SUCCESS);
14558 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
14559 const int64_t block_id,
14562 int64_t *stride_length,
14563 int64_t *n_values_per_frame,
14566 int64_t file_pos, data_size, n_frames_div, block_index;
14568 tng_non_particle_data_t data;
14569 tng_trajectory_frame_set_t frame_set;
14570 tng_gen_block_t block;
14572 tng_function_status stat;
14574 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14575 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14576 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14577 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14578 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14580 frame_set = &tng_data->current_trajectory_frame_set;
14585 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
14587 tng_block_init(&block);
14588 file_pos = ftell(tng_data->input_file);
14589 /* Read all blocks until next frame set block */
14590 stat = tng_block_header_read(tng_data, block);
14591 while(file_pos < tng_data->input_file_len &&
14592 stat != TNG_CRITICAL &&
14593 block->id != TNG_TRAJECTORY_FRAME_SET)
14595 /* Use hash by default */
14596 stat = tng_block_read_next(tng_data, block,
14598 if(stat != TNG_CRITICAL)
14600 file_pos = ftell(tng_data->input_file);
14601 if(file_pos < tng_data->input_file_len)
14603 stat = tng_block_header_read(tng_data, block);
14607 tng_block_destroy(&block);
14608 if(stat == TNG_CRITICAL)
14610 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14611 file_pos, __FILE__, __LINE__);
14615 for(i = frame_set->n_data_blocks; i-- ;)
14617 data = &frame_set->tr_data[i];
14618 if(data->block_id == block_id)
14624 if(block_index < 0)
14626 return(TNG_FAILURE);
14630 *type = data->datatype;
14634 case TNG_CHAR_DATA:
14635 return(TNG_FAILURE);
14637 size = sizeof(int64_t);
14639 case TNG_FLOAT_DATA:
14640 size = sizeof(float);
14642 case TNG_DOUBLE_DATA:
14644 size = sizeof(double);
14647 *n_frames = data->n_frames;
14648 *n_values_per_frame = data->n_values_per_frame;
14649 *stride_length = data->stride_length;
14650 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
14651 *n_frames / *stride_length;
14653 data_size = n_frames_div * size *
14654 *n_values_per_frame;
14656 temp = realloc(*values, data_size);
14659 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14660 data_size, __FILE__, __LINE__);
14663 return(TNG_CRITICAL);
14668 memcpy(*values, data->values, data_size);
14670 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14672 return(TNG_SUCCESS);
14675 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14676 (tng_trajectory_t tng_data,
14677 const int64_t block_id,
14678 const int64_t start_frame_nr,
14679 const int64_t end_frame_nr,
14680 const char hash_mode,
14681 union data_values ***values,
14682 int64_t *n_values_per_frame,
14685 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
14686 int64_t block_index;
14689 tng_non_particle_data_t data;
14690 tng_trajectory_frame_set_t frame_set;
14691 tng_gen_block_t block;
14692 tng_function_status stat;
14694 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14695 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14696 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14697 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14701 frame_set = &tng_data->current_trajectory_frame_set;
14702 first_frame = frame_set->first_frame;
14704 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14705 if(stat != TNG_SUCCESS)
14711 /* Do not re-read the frame set. */
14712 if(first_frame != frame_set->first_frame ||
14713 frame_set->n_data_blocks <= 0)
14715 tng_block_init(&block);
14716 file_pos = ftell(tng_data->input_file);
14717 /* Read all blocks until next frame set block */
14718 stat = tng_block_header_read(tng_data, block);
14719 while(file_pos < tng_data->input_file_len &&
14720 stat != TNG_CRITICAL &&
14721 block->id != TNG_TRAJECTORY_FRAME_SET)
14723 stat = tng_block_read_next(tng_data, block,
14725 if(stat != TNG_CRITICAL)
14727 file_pos = ftell(tng_data->input_file);
14728 if(file_pos < tng_data->input_file_len)
14730 stat = tng_block_header_read(tng_data, block);
14734 tng_block_destroy(&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__);
14744 /* See if there is a data block of this ID.
14745 * Start checking the last read frame set */
14746 for(i = frame_set->n_data_blocks; i-- ;)
14748 data = &frame_set->tr_data[i];
14749 if(data->block_id == block_id)
14756 if(block_index < 0)
14758 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
14759 block_id, __FILE__, __LINE__);
14760 return(TNG_FAILURE);
14763 n_frames = end_frame_nr - start_frame_nr + 1;
14764 *n_values_per_frame = data->n_values_per_frame;
14765 *type = data->datatype;
14769 if(tng_data_values_alloc(tng_data, values, n_frames,
14770 *n_values_per_frame,
14771 *type) != TNG_SUCCESS)
14773 return(TNG_CRITICAL);
14777 current_frame_pos = start_frame_nr - frame_set->first_frame;
14778 /* It's not very elegant to reuse so much of the code in the different case
14779 * statements, but it's unnecessarily slow to have the switch-case block
14780 * inside the for loops. */
14783 case TNG_CHAR_DATA:
14784 for(i=0; i<n_frames; i++)
14786 if(current_frame_pos == frame_set->n_frames)
14788 stat = tng_frame_set_read_next(tng_data, hash_mode);
14789 if(stat != TNG_SUCCESS)
14793 current_frame_pos = 0;
14795 for(j=*n_values_per_frame; j--;)
14797 len = strlen(data->strings[current_frame_pos][j]) + 1;
14798 (*values)[i][j].c = malloc(len);
14799 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
14801 current_frame_pos++;
14805 size = sizeof(int);
14806 for(i=0; i<n_frames; i++)
14808 if(current_frame_pos == frame_set->n_frames)
14810 stat = tng_frame_set_read_next(tng_data, hash_mode);
14811 if(stat != TNG_SUCCESS)
14815 current_frame_pos = 0;
14817 for(j=*n_values_per_frame; j--;)
14819 (*values)[i][j].i = *(int *)((char *)data->values + size *
14820 (current_frame_pos *
14821 (*n_values_per_frame) + j));
14823 current_frame_pos++;
14826 case TNG_FLOAT_DATA:
14827 size = sizeof(float);
14828 for(i=0; i<n_frames; i++)
14830 if(current_frame_pos == frame_set->n_frames)
14832 stat = tng_frame_set_read_next(tng_data, hash_mode);
14833 if(stat != TNG_SUCCESS)
14837 current_frame_pos = 0;
14839 for(j=*n_values_per_frame; j--;)
14841 (*values)[i][j].f = *(float *)((char *)data->values + size *
14842 (current_frame_pos *
14843 (*n_values_per_frame) + j));
14845 current_frame_pos++;
14848 case TNG_DOUBLE_DATA:
14850 size = sizeof(double);
14851 for(i=0; i<n_frames; i++)
14853 if(current_frame_pos == frame_set->n_frames)
14855 stat = tng_frame_set_read_next(tng_data, hash_mode);
14856 if(stat != TNG_SUCCESS)
14860 current_frame_pos = 0;
14862 for(j=*n_values_per_frame; j--;)
14864 (*values)[i][j].d = *(double *)((char *)data->values + size *
14865 (current_frame_pos *
14866 (*n_values_per_frame) + j));
14868 current_frame_pos++;
14872 data->last_retrieved_frame = end_frame_nr;
14874 return(TNG_SUCCESS);
14877 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14878 (tng_trajectory_t tng_data,
14879 const int64_t block_id,
14880 const int64_t start_frame_nr,
14881 const int64_t end_frame_nr,
14882 const char hash_mode,
14884 int64_t *stride_length,
14885 int64_t *n_values_per_frame,
14888 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14889 int64_t file_pos, current_frame_pos, data_size, frame_size;
14890 int64_t last_frame_pos;
14892 tng_trajectory_frame_set_t frame_set;
14893 tng_non_particle_data_t np_data;
14894 tng_gen_block_t block;
14895 void *current_values = 0, *temp;
14896 tng_function_status stat;
14898 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14899 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14900 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14901 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14902 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14904 frame_set = &tng_data->current_trajectory_frame_set;
14905 first_frame = frame_set->first_frame;
14907 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14908 if(stat != TNG_SUCCESS)
14913 /* Do not re-read the frame set and only need the requested block. */
14914 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
14915 stat = tng_data_find(tng_data, block_id, &np_data);
14916 if(first_frame != frame_set->first_frame ||
14917 stat != TNG_SUCCESS)
14919 tng_block_init(&block);
14920 if(stat != TNG_SUCCESS)
14922 fseek(tng_data->input_file,
14923 (long)tng_data->current_trajectory_frame_set_input_file_pos,
14925 stat = tng_block_header_read(tng_data, block);
14926 if(stat != TNG_SUCCESS)
14928 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
14929 __FILE__, __LINE__);
14933 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
14935 file_pos = ftell(tng_data->input_file);
14936 /* Read until next frame set block */
14937 stat = tng_block_header_read(tng_data, block);
14938 while(file_pos < tng_data->input_file_len &&
14939 stat != TNG_CRITICAL &&
14940 block->id != TNG_TRAJECTORY_FRAME_SET)
14942 if(block->id == block_id)
14944 stat = tng_block_read_next(tng_data, block,
14946 if(stat != TNG_CRITICAL)
14948 file_pos = ftell(tng_data->input_file);
14949 if(file_pos < tng_data->input_file_len)
14951 stat = tng_block_header_read(tng_data, block);
14957 file_pos += block->block_contents_size + block->header_contents_size;
14958 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
14959 if(file_pos < tng_data->input_file_len)
14961 stat = tng_block_header_read(tng_data, block);
14965 tng_block_destroy(&block);
14966 if(stat == TNG_CRITICAL)
14968 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14969 file_pos, __FILE__, __LINE__);
14974 stat = tng_data_find(tng_data, block_id, &np_data);
14975 if(stat != TNG_SUCCESS)
14980 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
14981 &n_frames, stride_length,
14982 n_values_per_frame, type);
14984 if(stat != TNG_SUCCESS)
14988 free(current_values);
14993 if(n_frames == 1 && n_frames < frame_set->n_frames)
14999 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15004 case TNG_CHAR_DATA:
15005 return(TNG_FAILURE);
15007 size = sizeof(int64_t);
15009 case TNG_FLOAT_DATA:
15010 size = sizeof(float);
15012 case TNG_DOUBLE_DATA:
15014 size = sizeof(double);
15017 n_frames_div = (tot_n_frames % *stride_length) ?
15018 tot_n_frames / *stride_length + 1:
15019 tot_n_frames / *stride_length;
15020 data_size = n_frames_div * size * (*n_values_per_frame);
15022 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15023 size, n_frames_div, data_size);
15025 temp = realloc(*values, data_size);
15028 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15029 data_size, __FILE__, __LINE__);
15032 return(TNG_CRITICAL);
15037 if( n_frames == 1 && n_frames < frame_set->n_frames)
15039 memcpy(*values, current_values, size * (*n_values_per_frame));
15043 current_frame_pos = start_frame_nr - frame_set->first_frame;
15045 frame_size = size * (*n_values_per_frame);
15047 last_frame_pos = tng_min_i64(n_frames,
15048 end_frame_nr - start_frame_nr);
15050 n_frames_div = current_frame_pos / *stride_length;
15051 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15052 last_frame_pos / *stride_length + 1:
15053 last_frame_pos / *stride_length;
15054 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15056 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15057 n_frames_div_2 * frame_size);
15059 current_frame_pos += n_frames - current_frame_pos;
15061 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15063 stat = tng_frame_set_read_next(tng_data, hash_mode);
15064 if(stat != TNG_SUCCESS)
15068 free(current_values);
15075 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15076 &n_frames, stride_length,
15077 n_values_per_frame, type);
15079 if(stat != TNG_SUCCESS)
15083 free(current_values);
15090 last_frame_pos = tng_min_i64(n_frames,
15091 end_frame_nr - current_frame_pos);
15093 n_frames_div = current_frame_pos / *stride_length;
15094 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15095 last_frame_pos / *stride_length + 1:
15096 last_frame_pos / *stride_length;
15097 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15099 memcpy(((char *)*values) + n_frames_div * frame_size,
15101 n_frames_div_2 * frame_size);
15103 current_frame_pos += n_frames;
15109 free(current_values);
15112 np_data->last_retrieved_frame = end_frame_nr;
15114 return(TNG_SUCCESS);
15117 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15118 (tng_trajectory_t tng_data,
15119 const int64_t block_id,
15120 union data_values ****values,
15122 int64_t *n_particles,
15123 int64_t *n_values_per_frame,
15126 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15129 tng_particle_data_t data;
15130 tng_trajectory_frame_set_t frame_set;
15131 tng_gen_block_t block;
15132 char block_type_flag;
15133 tng_function_status stat;
15135 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15136 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15137 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15138 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15139 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15141 frame_set = &tng_data->current_trajectory_frame_set;
15146 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15148 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15150 block_type_flag = TNG_TRAJECTORY_BLOCK;
15154 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15157 tng_block_init(&block);
15158 file_pos = ftell(tng_data->input_file);
15159 /* Read all blocks until next frame set block */
15160 stat = tng_block_header_read(tng_data, block);
15161 while(file_pos < tng_data->input_file_len &&
15162 stat != TNG_CRITICAL &&
15163 block->id != TNG_TRAJECTORY_FRAME_SET)
15165 /* Use hash by default */
15166 stat = tng_block_read_next(tng_data, block,
15168 if(stat != TNG_CRITICAL)
15170 file_pos = ftell(tng_data->input_file);
15171 if(file_pos < tng_data->input_file_len)
15173 stat = tng_block_header_read(tng_data, block);
15177 tng_block_destroy(&block);
15178 if(stat == TNG_CRITICAL)
15180 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15181 file_pos, __FILE__, __LINE__);
15185 for(i = frame_set->n_particle_data_blocks; i-- ;)
15187 data = &frame_set->tr_particle_data[i];
15188 if(data->block_id == block_id)
15191 block_type_flag = TNG_TRAJECTORY_BLOCK;
15195 if(block_index < 0)
15197 return(TNG_FAILURE);
15202 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15204 block_type_flag = TNG_TRAJECTORY_BLOCK;
15208 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15212 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15213 tng_data->var_num_atoms_flag)
15215 *n_particles = frame_set->n_particles;
15219 *n_particles = tng_data->n_particles;
15222 *n_frames = tng_max_i64(1, data->n_frames);
15223 *n_values_per_frame = data->n_values_per_frame;
15224 *type = data->datatype;
15228 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
15229 *n_particles, *n_values_per_frame,
15233 return(TNG_CRITICAL);
15237 /* It's not very elegant to reuse so much of the code in the different case
15238 * statements, but it's unnecessarily slow to have the switch-case block
15239 * inside the for loops. */
15242 case TNG_CHAR_DATA:
15243 for(i=*n_frames; i--;)
15245 for(j=*n_particles; j--;)
15247 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15248 for(k=*n_values_per_frame; k--;)
15250 len = strlen(data->strings[i][j][k]) + 1;
15251 (*values)[i][mapping][k].c = malloc(len);
15252 strncpy((*values)[i][mapping][k].c,
15253 data->strings[i][j][k], len);
15259 size = sizeof(int);
15260 i_step = (*n_particles) * (*n_values_per_frame);
15261 for(i=*n_frames; i--;)
15263 for(j=*n_particles; j--;)
15265 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15266 for(k=*n_values_per_frame; k--;)
15268 (*values)[i][mapping][k].i = *(int *)
15269 ((char *)data->values + size *
15271 (*n_values_per_frame) + k));
15276 case TNG_FLOAT_DATA:
15277 size = sizeof(float);
15278 i_step = (*n_particles) * (*n_values_per_frame);
15279 for(i=*n_frames; i--;)
15281 for(j=*n_particles; j--;)
15283 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15284 for(k=*n_values_per_frame; k--;)
15286 (*values)[i][mapping][k].f = *(float *)
15287 ((char *)data->values + size *
15289 (*n_values_per_frame) + k));
15294 case TNG_DOUBLE_DATA:
15296 size = sizeof(double);
15297 i_step = (*n_particles) * (*n_values_per_frame);
15298 for(i=*n_frames; i--;)
15300 for(j=*n_particles; j--;)
15302 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15303 for(k=*n_values_per_frame; k--;)
15305 (*values)[i][mapping][k].d = *(double *)
15306 ((char *)data->values + size *
15308 (*n_values_per_frame) + k));
15314 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15316 return(TNG_SUCCESS);
15319 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
15320 (tng_trajectory_t tng_data,
15321 const int64_t block_id,
15324 int64_t *stride_length,
15325 int64_t *n_particles,
15326 int64_t *n_values_per_frame,
15329 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
15330 int64_t block_index;
15332 tng_particle_data_t data;
15333 tng_trajectory_frame_set_t frame_set;
15334 tng_gen_block_t block;
15336 char block_type_flag;
15337 tng_function_status stat;
15339 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15340 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15341 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15342 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15343 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15345 frame_set = &tng_data->current_trajectory_frame_set;
15350 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15352 tng_block_init(&block);
15353 file_pos = ftell(tng_data->input_file);
15354 /* Read all blocks until next frame set block */
15355 stat = tng_block_header_read(tng_data, block);
15356 while(file_pos < tng_data->input_file_len &&
15357 stat != TNG_CRITICAL &&
15358 block->id != TNG_TRAJECTORY_FRAME_SET)
15360 /* Use hash by default */
15361 stat = tng_block_read_next(tng_data, block,
15363 if(stat != TNG_CRITICAL)
15365 file_pos = ftell(tng_data->input_file);
15366 if(file_pos < tng_data->input_file_len)
15368 stat = tng_block_header_read(tng_data, block);
15372 tng_block_destroy(&block);
15373 if(stat == TNG_CRITICAL)
15375 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15376 file_pos, __FILE__, __LINE__);
15380 for(i = frame_set->n_particle_data_blocks; i-- ;)
15382 data = &frame_set->tr_particle_data[i];
15383 if(data->block_id == block_id)
15389 if(block_index < 0)
15391 return(TNG_FAILURE);
15395 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15397 block_type_flag = TNG_TRAJECTORY_BLOCK;
15401 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15404 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15405 tng_data->var_num_atoms_flag)
15407 *n_particles = frame_set->n_particles;
15411 *n_particles = tng_data->n_particles;
15414 *type = data->datatype;
15418 case TNG_CHAR_DATA:
15419 return(TNG_FAILURE);
15421 size = sizeof(int64_t);
15423 case TNG_FLOAT_DATA:
15424 size = sizeof(float);
15426 case TNG_DOUBLE_DATA:
15428 size = sizeof(double);
15431 *n_frames = tng_max_i64(1, data->n_frames);
15432 *n_values_per_frame = data->n_values_per_frame;
15433 *stride_length = data->stride_length;
15435 n_frames_div = (*n_frames % *stride_length) ?
15436 *n_frames / *stride_length + 1:
15437 *n_frames / *stride_length;
15439 data_size = n_frames_div * size * (*n_particles) *
15440 (*n_values_per_frame);
15442 temp = realloc(*values, data_size);
15445 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15446 data_size, __FILE__, __LINE__);
15449 return(TNG_CRITICAL);
15454 if(frame_set->n_mapping_blocks <= 0)
15456 memcpy(*values, data->values, data_size);
15460 i_step = (*n_particles) * (*n_values_per_frame);
15461 for(i = *n_frames; i--;)
15463 for(j = *n_particles; j--;)
15465 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15466 memcpy(((char *)*values) + size * (i * i_step + mapping *
15467 (*n_values_per_frame)),
15468 (char *)data->values + size *
15469 (i * i_step + j * (*n_values_per_frame)),
15470 size * (*n_values_per_frame));
15475 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15477 return(TNG_SUCCESS);
15480 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15481 (tng_trajectory_t tng_data,
15482 const int64_t block_id,
15483 const int64_t start_frame_nr,
15484 const int64_t end_frame_nr,
15485 const char hash_mode,
15486 union data_values ****values,
15487 int64_t *n_particles,
15488 int64_t *n_values_per_frame,
15491 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
15492 int64_t first_frame, block_index;
15495 tng_particle_data_t data;
15496 tng_trajectory_frame_set_t frame_set;
15497 tng_gen_block_t block;
15498 char block_type_flag;
15499 tng_function_status stat;
15501 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15502 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15503 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15504 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15505 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15509 frame_set = &tng_data->current_trajectory_frame_set;
15510 first_frame = frame_set->first_frame;
15512 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15513 if(stat != TNG_SUCCESS)
15518 /* Do not re-read the frame set. */
15519 if(first_frame != frame_set->first_frame ||
15520 frame_set->n_particle_data_blocks <= 0)
15522 tng_block_init(&block);
15523 file_pos = ftell(tng_data->input_file);
15524 /* Read all blocks until next frame set block */
15525 stat = tng_block_header_read(tng_data, block);
15526 while(file_pos < tng_data->input_file_len &&
15527 stat != TNG_CRITICAL &&
15528 block->id != TNG_TRAJECTORY_FRAME_SET)
15530 stat = tng_block_read_next(tng_data, block,
15532 if(stat != TNG_CRITICAL)
15534 file_pos = ftell(tng_data->input_file);
15535 if(file_pos < tng_data->input_file_len)
15537 stat = tng_block_header_read(tng_data, block);
15541 tng_block_destroy(&block);
15542 if(stat == TNG_CRITICAL)
15544 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15545 file_pos, __FILE__, __LINE__);
15550 /* See if there is already a data block of this ID.
15551 * Start checking the last read frame set */
15552 for(i = frame_set->n_particle_data_blocks; i-- ;)
15554 data = &frame_set->tr_particle_data[i];
15555 if(data->block_id == block_id)
15558 block_type_flag = TNG_TRAJECTORY_BLOCK;
15563 if(block_index < 0)
15565 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
15566 block_id, __FILE__, __LINE__);
15567 return(TNG_FAILURE);
15570 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15571 tng_data->var_num_atoms_flag)
15573 *n_particles = frame_set->n_particles;
15577 *n_particles = tng_data->n_particles;
15580 n_frames = end_frame_nr - start_frame_nr + 1;
15581 *n_values_per_frame = data->n_values_per_frame;
15582 *type = data->datatype;
15586 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
15587 *n_particles, *n_values_per_frame,
15591 return(TNG_CRITICAL);
15595 current_frame_pos = start_frame_nr - frame_set->first_frame;
15596 /* It's not very elegant to reuse so much of the code in the different case
15597 * statements, but it's unnecessarily slow to have the switch-case block
15598 * inside the for loops. */
15601 case TNG_CHAR_DATA:
15602 for(i=0; i<n_frames; i++)
15604 if(current_frame_pos == frame_set->n_frames)
15606 stat = tng_frame_set_read_next(tng_data, hash_mode);
15607 if(stat != TNG_SUCCESS)
15611 current_frame_pos = 0;
15613 for(j=*n_particles; j--;)
15615 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15616 for(k=*n_values_per_frame; k--;)
15618 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
15619 (*values)[i][mapping][k].c = malloc(len);
15620 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
15623 current_frame_pos++;
15627 size = sizeof(int);
15628 i_step = (*n_particles) * (*n_values_per_frame);
15629 for(i=0; i<n_frames; i++)
15631 if(current_frame_pos == frame_set->n_frames)
15633 stat = tng_frame_set_read_next(tng_data, hash_mode);
15634 if(stat != TNG_SUCCESS)
15638 current_frame_pos = 0;
15640 for(j=*n_particles; j--;)
15642 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15643 for(k=*n_values_per_frame; k--;)
15645 (*values)[i][mapping][k].i = *(int *)
15646 ((char *)data->values + size *
15647 (current_frame_pos *
15649 (*n_values_per_frame) + k));
15652 current_frame_pos++;
15655 case TNG_FLOAT_DATA:
15656 size = sizeof(float);
15657 i_step = (*n_particles) * (*n_values_per_frame);
15658 for(i=0; i<n_frames; i++)
15660 if(current_frame_pos == frame_set->n_frames)
15662 stat = tng_frame_set_read_next(tng_data, hash_mode);
15663 if(stat != TNG_SUCCESS)
15667 current_frame_pos = 0;
15669 for(j=*n_particles; j--;)
15671 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15672 for(k=*n_values_per_frame; k--;)
15674 (*values)[i][mapping][k].f = *(float *)
15675 ((char *)data->values + size *
15676 (current_frame_pos *
15678 (*n_values_per_frame) + k));
15681 current_frame_pos++;
15684 case TNG_DOUBLE_DATA:
15686 size = sizeof(double);
15687 i_step = (*n_particles) * (*n_values_per_frame);
15688 for(i=0; i<n_frames; i++)
15690 if(current_frame_pos == frame_set->n_frames)
15692 stat = tng_frame_set_read_next(tng_data, hash_mode);
15693 if(stat != TNG_SUCCESS)
15697 current_frame_pos = 0;
15699 for(j=*n_particles; j--;)
15701 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
15702 for(k=*n_values_per_frame; k--;)
15704 (*values)[i][mapping][k].d = *(double *)
15705 ((char *)data->values + size *
15706 (current_frame_pos *
15708 (*n_values_per_frame) + k));
15711 current_frame_pos++;
15715 data->last_retrieved_frame = end_frame_nr;
15717 return(TNG_SUCCESS);
15720 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15721 (tng_trajectory_t tng_data,
15722 const int64_t block_id,
15723 const int64_t start_frame_nr,
15724 const int64_t end_frame_nr,
15725 const char hash_mode,
15727 int64_t *n_particles,
15728 int64_t *stride_length,
15729 int64_t *n_values_per_frame,
15732 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15733 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
15735 tng_trajectory_frame_set_t frame_set;
15736 tng_particle_data_t p_data;
15737 tng_gen_block_t block;
15738 void *current_values = 0, *temp;
15739 tng_function_status stat;
15741 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15742 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15743 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15744 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15745 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15746 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15748 frame_set = &tng_data->current_trajectory_frame_set;
15749 first_frame = frame_set->first_frame;
15751 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15752 if(stat != TNG_SUCCESS)
15757 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
15758 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
15759 stat = tng_particle_data_find(tng_data, block_id, &p_data);
15760 if(first_frame != frame_set->first_frame ||
15761 stat != TNG_SUCCESS)
15763 tng_block_init(&block);
15764 if(stat != TNG_SUCCESS)
15766 fseek(tng_data->input_file,
15767 (long)tng_data->current_trajectory_frame_set_input_file_pos,
15769 stat = tng_block_header_read(tng_data, block);
15770 if(stat != TNG_SUCCESS)
15772 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15773 __FILE__, __LINE__);
15777 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15779 file_pos = ftell(tng_data->input_file);
15780 /* Read until next frame set block */
15781 stat = tng_block_header_read(tng_data, block);
15782 while(file_pos < tng_data->input_file_len &&
15783 stat != TNG_CRITICAL &&
15784 block->id != TNG_TRAJECTORY_FRAME_SET)
15786 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
15788 stat = tng_block_read_next(tng_data, block,
15790 if(stat != TNG_CRITICAL)
15792 file_pos = ftell(tng_data->input_file);
15793 if(file_pos < tng_data->input_file_len)
15795 stat = tng_block_header_read(tng_data, block);
15801 file_pos += block->block_contents_size + block->header_contents_size;
15802 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15803 if(file_pos < tng_data->input_file_len)
15805 stat = tng_block_header_read(tng_data, block);
15809 tng_block_destroy(&block);
15810 if(stat == TNG_CRITICAL)
15812 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15813 file_pos, __FILE__, __LINE__);
15817 stat = tng_particle_data_find(tng_data, block_id, &p_data);
15818 if(stat != TNG_SUCCESS)
15823 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
15824 &n_frames, stride_length, n_particles,
15825 n_values_per_frame, type);
15827 if(stat != TNG_SUCCESS || *n_particles == 0)
15831 free(current_values);
15836 if(n_frames == 1 && n_frames < frame_set->n_frames)
15842 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15847 case TNG_CHAR_DATA:
15848 return(TNG_FAILURE);
15850 size = sizeof(int64_t);
15852 case TNG_FLOAT_DATA:
15853 size = sizeof(float);
15855 case TNG_DOUBLE_DATA:
15857 size = sizeof(double);
15860 n_frames_div = (tot_n_frames % *stride_length) ?
15861 tot_n_frames / *stride_length + 1:
15862 tot_n_frames / *stride_length;
15864 data_size = n_frames_div * size * (*n_particles) *
15865 (*n_values_per_frame);
15867 temp = realloc(*values, data_size);
15870 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15871 data_size, __FILE__, __LINE__);
15874 return(TNG_CRITICAL);
15879 if( n_frames == 1 && n_frames < frame_set->n_frames)
15881 memcpy(*values, current_values, size * (*n_particles) *
15882 (*n_values_per_frame));
15886 current_frame_pos = start_frame_nr - frame_set->first_frame;
15888 frame_size = size * (*n_particles) * (*n_values_per_frame);
15890 last_frame_pos = tng_min_i64(n_frames,
15891 end_frame_nr - start_frame_nr);
15893 n_frames_div = current_frame_pos / *stride_length;
15894 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15895 last_frame_pos / *stride_length + 1:
15896 last_frame_pos / *stride_length;
15897 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
15899 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15900 n_frames_div_2 * frame_size);
15902 current_frame_pos += n_frames - current_frame_pos;
15904 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15906 stat = tng_frame_set_read_next(tng_data, hash_mode);
15907 if(stat != TNG_SUCCESS)
15911 free(current_values);
15918 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
15919 &n_frames, stride_length, n_particles,
15920 n_values_per_frame, type);
15922 if(stat != TNG_SUCCESS)
15926 free(current_values);
15933 last_frame_pos = tng_min_i64(n_frames,
15934 end_frame_nr - current_frame_pos);
15936 n_frames_div = current_frame_pos / *stride_length;
15937 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15938 last_frame_pos / *stride_length + 1:
15939 last_frame_pos / *stride_length;
15940 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15942 memcpy(((char *)*values) + n_frames_div * frame_size,
15944 n_frames_div_2 * frame_size);
15946 current_frame_pos += n_frames;
15952 free(current_values);
15955 p_data->last_retrieved_frame = end_frame_nr;
15957 return(TNG_SUCCESS);
15960 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15961 (tng_trajectory_t tng_data,
15962 const int64_t block_id,
15964 int64_t *stride_length)
15966 tng_function_status stat;
15967 tng_non_particle_data_t np_data;
15968 tng_particle_data_t p_data;
15970 int is_particle_data;
15972 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
15979 stat = tng_frame_set_of_frame_find(tng_data, frame);
15980 if(stat != TNG_SUCCESS)
15985 stat = tng_data_find(tng_data, block_id, &np_data);
15986 if(stat != TNG_SUCCESS)
15988 stat = tng_particle_data_find(tng_data, block_id, &p_data);
15989 if(stat != TNG_SUCCESS)
15991 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15992 /* If no specific frame was required read until this data block is found */
15995 file_pos = ftell(tng_data->input_file);
15996 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15998 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15999 file_pos = ftell(tng_data->input_file);
16002 if(stat != TNG_SUCCESS)
16006 stat = tng_data_find(tng_data, block_id, &np_data);
16007 if(stat != TNG_SUCCESS)
16009 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16010 if(stat != TNG_SUCCESS)
16016 is_particle_data = 1;
16021 is_particle_data = 0;
16026 is_particle_data = 1;
16031 is_particle_data = 0;
16033 if(is_particle_data)
16035 *stride_length = p_data->stride_length;
16039 *stride_length = np_data->stride_length;
16041 return(TNG_SUCCESS);
16044 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16045 (const tng_trajectory_t tng_data,
16048 struct tm *time_data;
16051 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16052 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16054 secs = tng_data->time;
16056 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16057 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16058 "%4d-%02d-%02d %02d:%02d:%02d",
16059 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16060 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16062 return(TNG_SUCCESS);
16066 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16067 (const char *filename,
16069 tng_trajectory_t *tng_data_p)
16071 tng_function_status stat;
16073 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16075 if(mode != 'r' && mode != 'w' && mode != 'a')
16077 return(TNG_FAILURE);
16080 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16082 tng_trajectory_destroy(tng_data_p);
16083 return(TNG_CRITICAL);
16086 if(mode == 'r' || mode == 'a')
16088 tng_input_file_set(*tng_data_p, filename);
16090 /* Read the file headers */
16091 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16093 tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16098 tng_output_file_set(*tng_data_p, filename);
16100 else if(mode == 'a')
16102 fseek((*tng_data_p)->input_file,
16103 (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16106 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16107 if(stat != TNG_SUCCESS)
16109 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16110 __FILE__, __LINE__);
16113 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16114 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16115 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16116 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16117 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16118 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16119 (*tng_data_p)->first_trajectory_frame_set_input_file_pos = -1;
16120 (*tng_data_p)->last_trajectory_frame_set_input_file_pos = -1;
16121 (*tng_data_p)->current_trajectory_frame_set_input_file_pos = -1;
16122 if((*tng_data_p)->input_file)
16124 fclose((*tng_data_p)->input_file);
16125 (*tng_data_p)->input_file = 0;
16127 if((*tng_data_p)->input_file_path)
16129 free((*tng_data_p)->input_file_path);
16130 (*tng_data_p)->input_file_path = 0;
16132 tng_output_append_file_set(*tng_data_p, filename);
16134 fseek((*tng_data_p)->output_file, 0, SEEK_END);
16137 return(TNG_SUCCESS);
16140 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
16141 (tng_trajectory_t *tng_data_p)
16143 tng_trajectory_frame_set_t frame_set;
16145 if(tng_data_p == 0)
16147 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
16148 __FILE__, __LINE__);
16149 return(TNG_FAILURE);
16152 if(*tng_data_p == 0)
16154 return(TNG_SUCCESS);
16157 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
16159 if(frame_set->n_unwritten_frames > 0)
16161 frame_set->n_frames = frame_set->n_unwritten_frames;
16162 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
16165 return(tng_trajectory_destroy(tng_data_p));
16168 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
16169 (tng_trajectory_t tng_data,
16170 const int64_t frame_nr,
16173 int64_t first_frame;
16174 tng_trajectory_frame_set_t frame_set;
16175 tng_function_status stat;
16177 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16178 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16180 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
16181 if(stat != TNG_SUCCESS)
16183 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
16184 frame_nr, __FILE__, __LINE__);
16188 frame_set = &tng_data->current_trajectory_frame_set;
16189 first_frame = frame_set->first_frame;
16191 if(tng_data->time_per_frame <= 0)
16193 return(TNG_FAILURE);
16196 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
16198 return(TNG_SUCCESS);
16202 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
16203 (tng_trajectory_t tng_data,
16205 int64_t **molecule_cnt_list,
16206 tng_molecule_t *mols)
16208 tng_trajectory_frame_set_t frame_set;
16210 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16211 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
16213 *n_mols = tng_data->n_molecules;
16215 frame_set = &tng_data->current_trajectory_frame_set;
16216 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
16218 *molecule_cnt_list = frame_set->molecule_cnt_list;
16222 *molecule_cnt_list = tng_data->molecule_cnt_list;
16225 *mols = tng_data->molecules;
16227 return(TNG_SUCCESS);
16231 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
16232 (tng_trajectory_t tng_data,
16235 tng_molecule_t *mol)
16237 tng_function_status stat;
16239 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
16240 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
16242 stat = tng_molecule_add(tng_data, name, mol);
16243 if(stat != TNG_SUCCESS)
16247 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
16252 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
16253 (tng_trajectory_t tng_data,
16254 const tng_molecule_t mol,
16255 int64_t *n_particles,
16260 char ***chain_names,
16261 int64_t **chain_ids)
16269 *n_particles = mol->n_atoms;
16271 *names = malloc(sizeof(char *) * *n_particles);
16272 *types = malloc(sizeof(char *) * *n_particles);
16273 *res_names = malloc(sizeof(char *) * *n_particles);
16274 *chain_names = malloc(sizeof(char *) * *n_particles);
16275 *res_ids = malloc(sizeof(int64_t) * *n_particles);
16276 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
16278 for(i = 0; i < *n_particles; i++)
16280 atom = &mol->atoms[i];
16281 res = atom->residue;
16282 chain = res->chain;
16283 (*names)[i] = malloc(strlen(atom->name));
16284 strcpy(*names[i], atom->name);
16285 (*types)[i] = malloc(strlen(atom->atom_type));
16286 strcpy(*types[i], atom->atom_type);
16287 (*res_names)[i] = malloc(strlen(res->name));
16288 strcpy(*res_names[i], res->name);
16289 (*chain_names)[i] = malloc(strlen(chain->name));
16290 strcpy(*chain_names[i], chain->name);
16291 (*res_ids)[i] = res->id;
16292 (*chain_ids)[i] = chain->id;
16295 return(TNG_SUCCESS);
16298 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
16299 (tng_trajectory_t tng_data,
16300 tng_molecule_t mol,
16301 const int64_t n_particles,
16302 const char **names,
16303 const char **types,
16304 const char **res_names,
16305 const int64_t *res_ids,
16306 const char **chain_names,
16307 const int64_t *chain_ids)
16311 tng_residue_t residue;
16313 tng_function_status stat;
16315 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16316 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
16317 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
16318 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
16319 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
16320 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
16321 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
16323 for(i = 0; i < n_particles; i++)
16325 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
16326 &chain) == TNG_FAILURE)
16328 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
16330 if(stat != TNG_SUCCESS)
16335 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
16336 &residue) == TNG_FAILURE)
16338 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
16340 if(stat != TNG_SUCCESS)
16345 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
16346 if(stat != TNG_SUCCESS)
16351 return(TNG_SUCCESS);
16354 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
16355 (tng_trajectory_t tng_data,
16356 float **positions, int64_t *stride_length)
16358 int64_t n_frames, n_particles, n_values_per_frame;
16360 tng_function_status stat;
16362 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16363 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16364 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16366 stat = tng_num_frames_get(tng_data, &n_frames);
16367 if(stat != TNG_SUCCESS)
16372 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
16373 0, n_frames - 1, TNG_USE_HASH,
16374 (void **)positions,
16377 &n_values_per_frame,
16383 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
16384 (tng_trajectory_t tng_data,
16385 float **velocities, int64_t *stride_length)
16387 int64_t n_frames, n_particles, n_values_per_frame;
16389 tng_function_status stat;
16391 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16392 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16393 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16395 stat = tng_num_frames_get(tng_data, &n_frames);
16396 if(stat != TNG_SUCCESS)
16401 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
16402 0, n_frames - 1, TNG_USE_HASH,
16403 (void **)velocities,
16406 &n_values_per_frame,
16412 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
16413 (tng_trajectory_t tng_data,
16414 float **forces, int64_t *stride_length)
16416 int64_t n_frames, n_particles, n_values_per_frame;
16418 tng_function_status stat;
16420 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16421 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16422 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16424 stat = tng_num_frames_get(tng_data, &n_frames);
16425 if(stat != TNG_SUCCESS)
16430 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16431 0, n_frames - 1, TNG_USE_HASH,
16435 &n_values_per_frame,
16441 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
16442 (tng_trajectory_t tng_data,
16444 int64_t *stride_length)
16446 int64_t n_frames, n_values_per_frame;
16448 tng_function_status stat;
16450 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16451 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16452 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16454 stat = tng_num_frames_get(tng_data, &n_frames);
16455 if(stat != TNG_SUCCESS)
16460 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16461 0, n_frames - 1, TNG_USE_HASH,
16462 (void **)box_shape,
16464 &n_values_per_frame,
16470 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
16471 (tng_trajectory_t tng_data,
16472 const int64_t block_id,
16475 int64_t *retrieved_frame_number,
16476 double *retrieved_time)
16478 tng_trajectory_frame_set_t frame_set;
16479 tng_particle_data_t data;
16480 tng_function_status stat;
16482 int64_t i, data_size, n_particles;
16486 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16487 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
16488 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
16489 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
16490 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
16492 frame_set = &tng_data->current_trajectory_frame_set;
16494 stat = tng_particle_data_find(tng_data, block_id, &data);
16495 if(stat != TNG_SUCCESS)
16497 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16498 file_pos = ftell(tng_data->input_file);
16499 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16501 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16502 file_pos = ftell(tng_data->input_file);
16504 if(stat != TNG_SUCCESS)
16508 stat = tng_particle_data_find(tng_data, block_id, &data);
16509 if(stat != TNG_SUCCESS)
16514 if(data->last_retrieved_frame < 0)
16516 fseek(tng_data->input_file,
16517 (long)tng_data->first_trajectory_frame_set_input_file_pos,
16519 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
16520 if(stat != TNG_SUCCESS)
16524 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16525 if(stat != TNG_SUCCESS)
16530 i = data->first_frame_with_data;
16534 i = data->last_retrieved_frame + data->stride_length;
16535 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
16537 stat = tng_frame_set_of_frame_find(tng_data, i);
16538 if(stat != TNG_SUCCESS)
16540 /* If the frame set search found the frame set after the starting
16541 * frame set there is a gap in the frame sets. So, even if the frame
16542 * was not found the next frame with data is still in the found
16544 if(stat == TNG_CRITICAL)
16548 i = frame_set->first_frame;
16551 if(data->last_retrieved_frame < frame_set->first_frame)
16553 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16554 if(stat != TNG_SUCCESS)
16560 data->last_retrieved_frame = i;
16561 *retrieved_frame_number = i;
16562 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
16564 *retrieved_time = frame_set->first_frame_time +
16565 (i - frame_set->first_frame) *
16566 tng_data->time_per_frame;
16570 *retrieved_time = 0;
16573 if(data->stride_length > 1)
16575 i = (i - data->first_frame_with_data) / data->stride_length;
16579 i = (i - frame_set->first_frame);
16582 tng_num_particles_get(tng_data, &n_particles);
16584 *data_type = data->datatype;
16588 case TNG_CHAR_DATA:
16589 return(TNG_FAILURE);
16591 size = sizeof(int64_t);
16593 case TNG_FLOAT_DATA:
16594 size = sizeof(float);
16596 case TNG_DOUBLE_DATA:
16598 size = sizeof(double);
16601 data_size = size * n_particles * data->n_values_per_frame;
16603 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
16604 // i, data_size, size, n_particles, data->n_values_per_frame);
16606 temp = realloc(*values, data_size);
16609 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16610 data_size, __FILE__, __LINE__);
16613 return(TNG_CRITICAL);
16618 memcpy(*values, (char *)data->values + i * data_size, data_size);
16620 return(TNG_SUCCESS);
16623 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
16624 (tng_trajectory_t tng_data,
16625 const int64_t block_id,
16628 int64_t *retrieved_frame_number,
16629 double *retrieved_time)
16631 tng_trajectory_frame_set_t frame_set;
16632 tng_non_particle_data_t data;
16633 tng_function_status stat;
16635 int64_t i, data_size;
16639 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16640 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
16641 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
16642 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
16643 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
16645 frame_set = &tng_data->current_trajectory_frame_set;
16647 stat = tng_data_find(tng_data, block_id, &data);
16648 if(stat != TNG_SUCCESS)
16650 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16651 file_pos = ftell(tng_data->input_file);
16652 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16654 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16655 file_pos = ftell(tng_data->input_file);
16657 if(stat != TNG_SUCCESS)
16661 stat = tng_data_find(tng_data, block_id, &data);
16662 if(stat != TNG_SUCCESS)
16667 if(data->last_retrieved_frame < 0)
16669 fseek(tng_data->input_file,
16670 (long)tng_data->first_trajectory_frame_set_input_file_pos,
16672 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
16673 if(stat != TNG_SUCCESS)
16677 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16678 if(stat != TNG_SUCCESS)
16683 i = data->first_frame_with_data;
16687 i = data->last_retrieved_frame + data->stride_length;
16688 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
16690 stat = tng_frame_set_of_frame_find(tng_data, i);
16691 if(stat != TNG_SUCCESS)
16693 /* If the frame set search found the frame set after the starting
16694 * frame set there is a gap in the frame sets. So, even if the frame
16695 * was not found the next frame with data is still in the found
16697 if(stat == TNG_CRITICAL)
16701 i = frame_set->first_frame;
16704 if(data->last_retrieved_frame < frame_set->first_frame)
16706 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16707 if(stat != TNG_SUCCESS)
16713 data->last_retrieved_frame = i;
16714 *retrieved_frame_number = i;
16715 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
16717 *retrieved_time = frame_set->first_frame_time +
16718 (i - frame_set->first_frame) *
16719 tng_data->time_per_frame;
16723 *retrieved_time = 0;
16726 if(data->stride_length > 1)
16728 i = (i - data->first_frame_with_data) / data->stride_length;
16732 i = (i - frame_set->first_frame);
16735 *data_type = data->datatype;
16739 case TNG_CHAR_DATA:
16740 return(TNG_FAILURE);
16742 size = sizeof(int64_t);
16744 case TNG_FLOAT_DATA:
16745 size = sizeof(float);
16747 case TNG_DOUBLE_DATA:
16749 size = sizeof(double);
16752 data_size = size * data->n_values_per_frame;
16754 temp = realloc(*values, data_size);
16757 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16758 data_size, __FILE__, __LINE__);
16761 return(TNG_CRITICAL);
16766 memcpy(*values, (char *)data->values + i * data_size, data_size);
16768 return(TNG_SUCCESS);
16771 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
16772 (tng_trajectory_t tng_data,
16773 const int64_t first_frame,
16774 const int64_t last_frame,
16776 int64_t *stride_length)
16778 int64_t n_particles, n_values_per_frame;
16780 tng_function_status stat;
16782 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16783 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16784 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16785 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16787 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
16788 first_frame, last_frame,
16790 (void **)positions,
16793 &n_values_per_frame,
16799 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
16800 (tng_trajectory_t tng_data,
16801 const int64_t first_frame,
16802 const int64_t last_frame,
16803 float **velocities,
16804 int64_t *stride_length)
16806 int64_t n_particles, n_values_per_frame;
16808 tng_function_status stat;
16810 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16811 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16812 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16813 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16815 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
16816 first_frame, last_frame,
16818 (void **)velocities,
16821 &n_values_per_frame,
16827 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
16828 (tng_trajectory_t tng_data,
16829 const int64_t first_frame,
16830 const int64_t last_frame,
16832 int64_t *stride_length)
16834 int64_t n_particles, n_values_per_frame;
16836 tng_function_status stat;
16838 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16839 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16840 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16841 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16843 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16844 first_frame, last_frame,
16849 &n_values_per_frame,
16855 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16856 (tng_trajectory_t tng_data,
16857 const int64_t first_frame,
16858 const int64_t last_frame,
16860 int64_t *stride_length)
16862 int64_t n_values_per_frame;
16864 tng_function_status stat;
16866 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16867 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16868 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16869 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16871 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16872 first_frame, last_frame,
16874 (void **)box_shape,
16876 &n_values_per_frame,
16882 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16883 (tng_trajectory_t tng_data,
16885 const int64_t n_values_per_frame,
16886 const int64_t block_id,
16887 const char *block_name,
16888 const char particle_dependency,
16889 const char compression)
16891 tng_trajectory_frame_set_t frame_set;
16892 tng_particle_data_t p_data;
16893 tng_non_particle_data_t np_data;
16894 int64_t n_particles, n_frames;
16895 tng_function_status stat;
16897 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16898 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16902 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16903 i, __FILE__, __LINE__);
16904 return(TNG_FAILURE);
16907 frame_set = &tng_data->current_trajectory_frame_set;
16909 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16911 n_frames = tng_data->frame_set_n_frames;
16913 stat = tng_frame_set_new(tng_data, 0, n_frames);
16914 if(stat != TNG_SUCCESS)
16916 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16923 n_frames = frame_set->n_frames;
16926 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16928 tng_num_particles_get(tng_data, &n_particles);
16929 if(n_particles <= 0)
16931 return(TNG_FAILURE);
16934 if(tng_particle_data_find(tng_data, block_id, &p_data)
16937 stat = tng_particle_data_block_add(tng_data, block_id,
16940 TNG_TRAJECTORY_BLOCK,
16941 n_frames, n_values_per_frame, i,
16944 if(stat != TNG_SUCCESS)
16946 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16947 __FILE__, __LINE__);
16950 p_data = &frame_set->tr_particle_data[frame_set->
16951 n_particle_data_blocks - 1];
16952 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
16954 n_values_per_frame);
16955 if(stat != TNG_SUCCESS)
16957 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16958 __FILE__, __LINE__);
16964 if(p_data->stride_length != i)
16966 p_data->stride_length = i;
16967 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
16969 n_values_per_frame);
16970 if(stat != TNG_SUCCESS)
16972 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16973 __FILE__, __LINE__);
16981 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
16983 stat = tng_data_block_add(tng_data, block_id, block_name,
16984 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
16985 n_frames, n_values_per_frame,
16986 i, compression, 0);
16987 if(stat != TNG_SUCCESS)
16989 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16990 __FILE__, __LINE__);
16993 np_data = &frame_set->tr_data[frame_set->
16994 n_data_blocks - 1];
16995 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
16996 i, n_values_per_frame);
16997 if(stat != TNG_SUCCESS)
16999 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17000 __FILE__, __LINE__);
17006 if(np_data->stride_length != i)
17008 np_data->stride_length = i;
17009 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17010 i, n_values_per_frame);
17011 if(stat != TNG_SUCCESS)
17013 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17014 __FILE__, __LINE__);
17021 return(TNG_SUCCESS);
17024 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17025 (tng_trajectory_t tng_data,
17027 const int64_t n_values_per_frame,
17028 const int64_t block_id,
17029 const char *block_name,
17030 const char particle_dependency,
17031 const char compression)
17033 tng_trajectory_frame_set_t frame_set;
17034 tng_particle_data_t p_data;
17035 tng_non_particle_data_t np_data;
17036 int64_t n_particles, n_frames;
17037 tng_function_status stat;
17039 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17040 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17044 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17045 i, __FILE__, __LINE__);
17046 return(TNG_FAILURE);
17049 frame_set = &tng_data->current_trajectory_frame_set;
17051 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17053 n_frames = tng_data->frame_set_n_frames;
17055 stat = tng_frame_set_new(tng_data, 0, n_frames);
17056 if(stat != TNG_SUCCESS)
17058 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17065 n_frames = frame_set->n_frames;
17068 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17070 tng_num_particles_get(tng_data, &n_particles);
17072 if(n_particles <= 0)
17074 return(TNG_FAILURE);
17077 if(tng_particle_data_find(tng_data, block_id, &p_data)
17080 stat = tng_particle_data_block_add(tng_data, block_id,
17083 TNG_TRAJECTORY_BLOCK,
17084 n_frames, n_values_per_frame, i,
17087 if(stat != TNG_SUCCESS)
17089 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17090 __FILE__, __LINE__);
17093 p_data = &frame_set->tr_particle_data[frame_set->
17094 n_particle_data_blocks - 1];
17095 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17097 n_values_per_frame);
17098 if(stat != TNG_SUCCESS)
17100 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17101 __FILE__, __LINE__);
17107 p_data->stride_length = i;
17112 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17114 stat = tng_data_block_add(tng_data, block_id, block_name,
17115 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
17116 n_frames, n_values_per_frame,
17117 i, compression, 0);
17118 if(stat != TNG_SUCCESS)
17120 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17121 __FILE__, __LINE__);
17124 np_data = &frame_set->tr_data[frame_set->
17125 n_data_blocks - 1];
17126 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17127 i, n_values_per_frame);
17128 if(stat != TNG_SUCCESS)
17130 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17131 __FILE__, __LINE__);
17137 np_data->stride_length = i;
17141 return(TNG_SUCCESS);
17144 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
17145 (tng_trajectory_t tng_data,
17147 const int64_t n_values_per_frame,
17148 const int64_t block_id,
17149 const char *block_name,
17150 const char particle_dependency,
17151 const char compression)
17153 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
17154 "See documentation. %s: %d", __FILE__, __LINE__);
17155 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
17156 block_id, block_name,
17157 particle_dependency,
17160 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
17161 (tng_trajectory_t tng_data,
17164 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17165 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17167 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17168 TNG_TRAJ_POSITIONS,
17170 TNG_PARTICLE_BLOCK_DATA,
17171 TNG_TNG_COMPRESSION));
17174 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
17175 (tng_trajectory_t tng_data,
17178 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17179 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17181 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17182 TNG_TRAJ_POSITIONS,
17184 TNG_PARTICLE_BLOCK_DATA,
17185 TNG_TNG_COMPRESSION));
17188 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
17189 (tng_trajectory_t tng_data,
17192 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
17193 "See documentation. %s: %d", __FILE__, __LINE__);
17194 return(tng_util_pos_write_interval_set(tng_data, i));
17197 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
17198 (tng_trajectory_t tng_data,
17201 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17202 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17204 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17205 TNG_TRAJ_VELOCITIES,
17207 TNG_PARTICLE_BLOCK_DATA,
17208 TNG_TNG_COMPRESSION));
17211 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
17212 (tng_trajectory_t tng_data,
17215 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17216 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17218 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17219 TNG_TRAJ_VELOCITIES,
17221 TNG_PARTICLE_BLOCK_DATA,
17222 TNG_TNG_COMPRESSION));
17225 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
17226 (tng_trajectory_t tng_data,
17229 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
17230 "See documentation. %s: %d", __FILE__, __LINE__);
17231 return(tng_util_vel_write_interval_set(tng_data, i));
17234 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
17235 (tng_trajectory_t tng_data,
17238 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17239 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17241 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17244 TNG_PARTICLE_BLOCK_DATA,
17245 TNG_GZIP_COMPRESSION));
17248 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
17249 (tng_trajectory_t tng_data,
17252 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17253 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17255 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17258 TNG_PARTICLE_BLOCK_DATA,
17259 TNG_GZIP_COMPRESSION));
17262 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
17263 (tng_trajectory_t tng_data,
17266 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
17267 "See documentation. %s: %d", __FILE__, __LINE__);
17268 return(tng_util_force_write_interval_set(tng_data, i));
17271 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
17272 (tng_trajectory_t tng_data,
17275 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17276 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17278 return(tng_util_generic_write_interval_set(tng_data, i, 9,
17279 TNG_TRAJ_BOX_SHAPE,
17281 TNG_NON_PARTICLE_BLOCK_DATA,
17282 TNG_GZIP_COMPRESSION));
17285 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
17286 (tng_trajectory_t tng_data,
17289 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17290 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17292 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
17293 TNG_TRAJ_BOX_SHAPE,
17295 TNG_NON_PARTICLE_BLOCK_DATA,
17296 TNG_GZIP_COMPRESSION));
17299 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
17300 (tng_trajectory_t tng_data,
17303 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
17304 "See documentation. %s: %d", __FILE__, __LINE__);
17305 return(tng_util_box_shape_write_interval_set(tng_data, i));
17308 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
17309 (tng_trajectory_t tng_data,
17310 const int64_t frame_nr,
17311 const float *values,
17312 const int64_t n_values_per_frame,
17313 const int64_t block_id,
17314 const char *block_name,
17315 const char particle_dependency,
17316 const char compression)
17318 tng_trajectory_frame_set_t frame_set;
17319 tng_particle_data_t p_data;
17320 tng_non_particle_data_t np_data;
17321 int64_t n_particles, n_frames, stride_length = 100, frame_pos;
17322 int64_t last_frame;
17323 int is_first_frame_flag = 0;
17324 char block_type_flag;
17325 tng_function_status stat;
17327 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17328 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17329 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17331 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17333 tng_num_particles_get(tng_data, &n_particles);
17334 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
17339 return(TNG_FAILURE);
17342 frame_set = &tng_data->current_trajectory_frame_set;
17346 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
17347 n_frames = stride_length = 1;
17351 block_type_flag = TNG_TRAJECTORY_BLOCK;
17353 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17355 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
17356 if(stat != TNG_SUCCESS)
17358 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17363 last_frame = frame_set->first_frame +
17364 frame_set->n_frames - 1;
17365 if(frame_nr > last_frame)
17367 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
17368 if(stat != TNG_SUCCESS)
17370 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
17374 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
17376 last_frame = frame_nr - 1;
17378 stat = tng_frame_set_new(tng_data, last_frame + 1,
17379 tng_data->frame_set_n_frames);
17380 if(stat != TNG_SUCCESS)
17382 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17387 if(frame_set->n_unwritten_frames == 0)
17389 is_first_frame_flag = 1;
17391 frame_set->n_unwritten_frames = frame_nr -
17392 frame_set->first_frame + 1;
17394 n_frames = frame_set->n_frames;
17397 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17399 if(tng_particle_data_find(tng_data, block_id, &p_data)
17402 stat = tng_particle_data_block_add(tng_data, block_id,
17406 n_frames, n_values_per_frame,
17410 if(stat != TNG_SUCCESS)
17412 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17413 __FILE__, __LINE__);
17416 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17418 p_data = &frame_set->tr_particle_data[frame_set->
17419 n_particle_data_blocks - 1];
17423 p_data = &tng_data->non_tr_particle_data[tng_data->
17424 n_particle_data_blocks - 1];
17426 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17427 stride_length, n_particles,
17428 n_values_per_frame);
17429 if(stat != TNG_SUCCESS)
17431 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17432 __FILE__, __LINE__);
17437 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17439 stride_length = p_data->stride_length;
17441 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
17443 p_data->first_frame_with_data = frame_nr;
17448 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17451 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
17452 n_values_per_frame, values, sizeof(float) *
17453 n_particles * n_values_per_frame);
17457 memcpy(p_data->values, values, sizeof(float) * n_particles *
17458 n_values_per_frame);
17463 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17465 stat = tng_data_block_add(tng_data, block_id, block_name,
17466 TNG_FLOAT_DATA, block_type_flag,
17467 n_frames, n_values_per_frame,
17468 stride_length, compression, 0);
17469 if(stat != TNG_SUCCESS)
17471 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17472 __FILE__, __LINE__);
17475 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17477 np_data = &frame_set->tr_data[frame_set->
17478 n_data_blocks - 1];
17482 np_data = &tng_data->non_tr_data[tng_data->
17483 n_data_blocks - 1];
17485 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17486 stride_length, n_values_per_frame);
17487 if(stat != TNG_SUCCESS)
17489 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17490 __FILE__, __LINE__);
17495 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17497 stride_length = np_data->stride_length;
17499 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
17501 np_data->first_frame_with_data = frame_nr;
17506 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17509 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
17510 n_values_per_frame, values, sizeof(float) *
17511 n_values_per_frame);
17515 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
17519 return(TNG_SUCCESS);
17522 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
17523 (tng_trajectory_t tng_data,
17524 const int64_t frame_nr,
17525 const double *values,
17526 const int64_t n_values_per_frame,
17527 const int64_t block_id,
17528 const char *block_name,
17529 const char particle_dependency,
17530 const char compression)
17532 tng_trajectory_frame_set_t frame_set;
17533 tng_particle_data_t p_data;
17534 tng_non_particle_data_t np_data;
17535 int64_t n_particles, n_frames, stride_length = 100, frame_pos;
17536 int64_t last_frame;
17537 int is_first_frame_flag = 0;
17538 char block_type_flag;
17539 tng_function_status stat;
17541 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17542 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17543 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17545 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17547 tng_num_particles_get(tng_data, &n_particles);
17548 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
17553 return(TNG_FAILURE);
17556 frame_set = &tng_data->current_trajectory_frame_set;
17560 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
17561 n_frames = stride_length = 1;
17565 block_type_flag = TNG_TRAJECTORY_BLOCK;
17567 n_frames = tng_data->frame_set_n_frames;
17569 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17571 stat = tng_frame_set_new(tng_data, 0, n_frames);
17572 if(stat != TNG_SUCCESS)
17574 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17581 n_frames = frame_set->n_frames;
17583 last_frame = frame_set->first_frame +
17584 frame_set->n_frames - 1;
17585 if(frame_nr > last_frame)
17587 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
17588 if(stat != TNG_SUCCESS)
17590 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
17594 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
17596 last_frame = frame_nr - 1;
17598 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
17599 if(stat != TNG_SUCCESS)
17601 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17606 if(frame_set->n_unwritten_frames == 0)
17608 is_first_frame_flag = 1;
17610 frame_set->n_unwritten_frames = frame_nr -
17611 frame_set->first_frame + 1;
17614 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17616 if(tng_particle_data_find(tng_data, block_id, &p_data)
17619 stat = tng_particle_data_block_add(tng_data, block_id,
17623 n_frames, n_values_per_frame,
17627 if(stat != TNG_SUCCESS)
17629 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17630 __FILE__, __LINE__);
17633 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17635 p_data = &frame_set->tr_particle_data[frame_set->
17636 n_particle_data_blocks - 1];
17640 p_data = &tng_data->non_tr_particle_data[tng_data->
17641 n_particle_data_blocks - 1];
17643 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17644 stride_length, n_particles,
17645 n_values_per_frame);
17646 if(stat != TNG_SUCCESS)
17648 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17649 __FILE__, __LINE__);
17654 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17656 stride_length = p_data->stride_length;
17658 if(is_first_frame_flag)
17660 p_data->first_frame_with_data = frame_nr;
17665 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17668 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
17669 n_values_per_frame, values, sizeof(double) *
17670 n_particles * n_values_per_frame);
17674 memcpy(p_data->values, values, sizeof(double) * n_particles *
17675 n_values_per_frame);
17680 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17682 stat = tng_data_block_add(tng_data, block_id, block_name,
17683 TNG_DOUBLE_DATA, block_type_flag,
17684 n_frames, n_values_per_frame,
17685 stride_length, compression, 0);
17686 if(stat != TNG_SUCCESS)
17688 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17689 __FILE__, __LINE__);
17692 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17694 np_data = &frame_set->tr_data[frame_set->
17695 n_data_blocks - 1];
17699 np_data = &tng_data->non_tr_data[tng_data->
17700 n_data_blocks - 1];
17702 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17703 stride_length, n_values_per_frame);
17704 if(stat != TNG_SUCCESS)
17706 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17707 __FILE__, __LINE__);
17712 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
17714 stride_length = np_data->stride_length;
17716 if(is_first_frame_flag)
17718 np_data->first_frame_with_data = frame_nr;
17723 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
17726 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
17727 n_values_per_frame, values, sizeof(double) *
17728 n_values_per_frame);
17732 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
17736 return(TNG_SUCCESS);
17739 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
17740 (tng_trajectory_t tng_data,
17741 const int64_t frame_nr,
17742 const float *positions)
17744 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17745 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17746 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17748 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
17749 TNG_TRAJ_POSITIONS, "POSITIONS",
17750 TNG_PARTICLE_BLOCK_DATA,
17751 TNG_TNG_COMPRESSION));
17754 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
17755 (tng_trajectory_t tng_data,
17756 const int64_t frame_nr,
17757 const double *positions)
17759 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17760 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17761 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17763 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
17764 TNG_TRAJ_POSITIONS, "POSITIONS",
17765 TNG_PARTICLE_BLOCK_DATA,
17766 TNG_TNG_COMPRESSION));
17769 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
17770 (tng_trajectory_t tng_data,
17771 const int64_t frame_nr,
17772 const float *velocities)
17774 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17775 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17776 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17778 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
17779 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17780 TNG_PARTICLE_BLOCK_DATA,
17781 TNG_TNG_COMPRESSION));
17784 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
17785 (tng_trajectory_t tng_data,
17786 const int64_t frame_nr,
17787 const double *velocities)
17789 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17790 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17791 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17793 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
17794 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17795 TNG_PARTICLE_BLOCK_DATA,
17796 TNG_TNG_COMPRESSION));
17799 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17800 (tng_trajectory_t tng_data,
17801 const int64_t frame_nr,
17802 const float *forces)
17804 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17805 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17806 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17808 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17809 TNG_TRAJ_FORCES, "FORCES",
17810 TNG_PARTICLE_BLOCK_DATA,
17811 TNG_GZIP_COMPRESSION));
17814 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17815 (tng_trajectory_t tng_data,
17816 const int64_t frame_nr,
17817 const double *forces)
17819 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17820 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17821 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17823 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17824 TNG_TRAJ_FORCES, "FORCES",
17825 TNG_PARTICLE_BLOCK_DATA,
17826 TNG_GZIP_COMPRESSION));
17829 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17830 (tng_trajectory_t tng_data,
17831 const int64_t frame_nr,
17832 const float *box_shape)
17834 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17835 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17836 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17838 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17839 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17840 TNG_NON_PARTICLE_BLOCK_DATA,
17841 TNG_GZIP_COMPRESSION));
17844 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17845 (tng_trajectory_t tng_data,
17846 const int64_t frame_nr,
17847 const double *box_shape)
17849 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17850 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17851 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17853 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17854 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17855 TNG_NON_PARTICLE_BLOCK_DATA,
17856 TNG_GZIP_COMPRESSION));
17859 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17860 (tng_trajectory_t tng_data,
17861 const int64_t frame_nr,
17863 const float *values,
17864 const int64_t n_values_per_frame,
17865 const int64_t block_id,
17866 const char *block_name,
17867 const char particle_dependency,
17868 const char compression)
17870 tng_trajectory_frame_set_t frame_set;
17871 tng_function_status stat;
17873 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17874 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17875 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17876 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17878 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17879 block_id, block_name,
17880 particle_dependency,
17883 if(stat != TNG_SUCCESS)
17888 frame_set = &tng_data->current_trajectory_frame_set;
17890 /* first_frame_time is -1 when it is not yet set. */
17891 if(frame_set->first_frame_time < -0.1)
17893 if(frame_nr > frame_set->first_frame)
17895 stat = tng_frame_set_first_frame_time_set(tng_data,
17898 frame_set->first_frame) *
17899 tng_data->time_per_frame);
17903 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17909 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17910 (tng_trajectory_t tng_data,
17911 const int64_t frame_nr,
17913 const double *values,
17914 const int64_t n_values_per_frame,
17915 const int64_t block_id,
17916 const char *block_name,
17917 const char particle_dependency,
17918 const char compression)
17920 tng_trajectory_frame_set_t frame_set;
17921 tng_function_status stat;
17923 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17924 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17925 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17926 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17928 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
17929 block_id, block_name,
17930 particle_dependency,
17933 if(stat != TNG_SUCCESS)
17938 frame_set = &tng_data->current_trajectory_frame_set;
17940 /* first_frame_time is -1 when it is not yet set. */
17941 if(frame_set->first_frame_time < -0.1)
17943 if(frame_nr > frame_set->first_frame)
17945 stat = tng_frame_set_first_frame_time_set(tng_data,
17948 frame_set->first_frame) *
17949 tng_data->time_per_frame);
17953 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17959 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17960 (tng_trajectory_t tng_data,
17961 const int64_t frame_nr,
17963 const float *positions)
17965 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17966 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17967 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17968 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17970 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
17971 3, TNG_TRAJ_POSITIONS, "POSITIONS",
17972 TNG_PARTICLE_BLOCK_DATA,
17973 TNG_TNG_COMPRESSION));
17976 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17977 (tng_trajectory_t tng_data,
17978 const int64_t frame_nr,
17980 const double *positions)
17982 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17983 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17984 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17985 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17987 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17989 TNG_TRAJ_POSITIONS,
17991 TNG_PARTICLE_BLOCK_DATA,
17992 TNG_TNG_COMPRESSION));
17995 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17996 (tng_trajectory_t tng_data,
17997 const int64_t frame_nr,
17999 const float *velocities)
18001 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18002 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18003 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18004 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18006 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18008 TNG_TRAJ_VELOCITIES,
18010 TNG_PARTICLE_BLOCK_DATA,
18011 TNG_TNG_COMPRESSION));
18014 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18015 (tng_trajectory_t tng_data,
18016 const int64_t frame_nr,
18018 const double *velocities)
18020 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18021 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18022 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18023 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18025 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18027 TNG_TRAJ_VELOCITIES,
18029 TNG_PARTICLE_BLOCK_DATA,
18030 TNG_TNG_COMPRESSION));
18033 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18034 (tng_trajectory_t tng_data,
18035 const int64_t frame_nr,
18037 const float *forces)
18039 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18040 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18041 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18042 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18044 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18045 3, TNG_TRAJ_FORCES, "FORCES",
18046 TNG_PARTICLE_BLOCK_DATA,
18047 TNG_GZIP_COMPRESSION));
18050 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18051 (tng_trajectory_t tng_data,
18052 const int64_t frame_nr,
18054 const double *forces)
18056 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18057 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18058 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18059 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18061 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18063 TNG_TRAJ_FORCES, "FORCES",
18064 TNG_PARTICLE_BLOCK_DATA,
18065 TNG_GZIP_COMPRESSION));
18068 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18069 (tng_trajectory_t tng_data,
18070 const int64_t frame_nr,
18072 const float *box_shape)
18074 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18075 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18076 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18077 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18079 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18080 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18081 TNG_NON_PARTICLE_BLOCK_DATA,
18082 TNG_GZIP_COMPRESSION));
18085 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18086 (tng_trajectory_t tng_data,
18087 const int64_t frame_nr,
18089 const double *box_shape)
18091 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18092 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18093 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18094 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18096 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18097 time, box_shape, 9,
18098 TNG_TRAJ_BOX_SHAPE,
18100 TNG_NON_PARTICLE_BLOCK_DATA,
18101 TNG_GZIP_COMPRESSION));
18104 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18105 (tng_trajectory_t tng_data,
18106 const int64_t block_id,
18110 tng_trajectory_frame_set_t frame_set;
18111 tng_particle_data_t p_data;
18112 tng_non_particle_data_t np_data;
18113 tng_function_status stat;
18115 int block_type = -1;
18117 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18118 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
18119 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
18121 frame_set = &tng_data->current_trajectory_frame_set;
18123 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18124 if(stat == TNG_SUCCESS)
18126 block_type = TNG_PARTICLE_BLOCK_DATA;
18130 stat = tng_data_find(tng_data, block_id, &np_data);
18131 if(stat == TNG_SUCCESS)
18133 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18137 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18138 if(stat != TNG_SUCCESS)
18142 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18143 if(stat == TNG_SUCCESS)
18145 block_type = TNG_PARTICLE_BLOCK_DATA;
18149 stat = tng_data_find(tng_data, block_id, &np_data);
18150 if(stat == TNG_SUCCESS)
18152 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18161 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18163 if(p_data->last_retrieved_frame < 0)
18165 i = p_data->first_frame_with_data;
18169 i = p_data->last_retrieved_frame;
18172 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
18174 if(np_data->last_retrieved_frame < 0)
18176 i = np_data->first_frame_with_data;
18180 i = np_data->last_retrieved_frame;
18185 return(TNG_FAILURE);
18187 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
18189 stat = tng_frame_set_of_frame_find(tng_data, i);
18190 if(stat != TNG_SUCCESS)
18194 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18195 if(stat != TNG_SUCCESS)
18197 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18198 __FILE__, __LINE__);
18202 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18204 *codec_id = p_data->codec_id;
18205 *factor = p_data->compression_multiplier;
18207 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
18209 *codec_id = np_data->codec_id;
18210 *factor = np_data->compression_multiplier;
18212 return(TNG_SUCCESS);
18215 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
18216 (tng_trajectory_t tng_data,
18217 int64_t current_frame,
18218 const int64_t n_requested_data_block_ids,
18219 const int64_t *requested_data_block_ids,
18220 int64_t *next_frame,
18221 int64_t *n_data_blocks_in_next_frame,
18222 int64_t **data_block_ids_in_next_frame)
18224 tng_trajectory_frame_set_t frame_set;
18225 tng_function_status stat;
18226 tng_particle_data_t p_data;
18227 tng_non_particle_data_t np_data;
18228 tng_gen_block_t block;
18229 int64_t i, j, block_id, *temp;
18230 int64_t data_frame, frame_diff, min_diff;
18231 int64_t size, frame_set_file_pos;
18232 int found, read_all = 0;
18235 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18236 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
18237 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
18238 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
18240 if(n_requested_data_block_ids)
18242 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.");
18243 size = sizeof(int64_t) * n_requested_data_block_ids;
18244 temp = realloc(*data_block_ids_in_next_frame, size);
18247 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
18248 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
18249 __FILE__, __LINE__);
18250 free(*data_block_ids_in_next_frame);
18251 *data_block_ids_in_next_frame = 0;
18252 return(TNG_CRITICAL);
18254 *data_block_ids_in_next_frame = temp;
18257 frame_set = &tng_data->current_trajectory_frame_set;
18259 current_frame += 1;
18261 if(current_frame < frame_set->first_frame ||
18262 current_frame >= frame_set->first_frame + frame_set->n_frames)
18264 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
18265 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
18266 if(stat != TNG_SUCCESS)
18268 /* If the frame set search found the frame set after the starting
18269 * frame set there is a gap in the frame sets. So, even if the frame
18270 * was not found the next frame with data is still in the found
18272 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
18273 frame_set_file_pos)
18277 current_frame = frame_set->first_frame;
18281 if(frame_set->n_particle_data_blocks <= 0 || frame_set->n_data_blocks <= 0)
18283 tng_block_init(&block);
18284 file_pos = ftell(tng_data->input_file);
18285 /* Read all blocks until next frame set block */
18286 stat = tng_block_header_read(tng_data, block);
18287 while(file_pos < tng_data->input_file_len &&
18288 stat != TNG_CRITICAL &&
18289 block->id != TNG_TRAJECTORY_FRAME_SET)
18291 stat = tng_block_read_next(tng_data, block,
18293 if(stat != TNG_CRITICAL)
18295 file_pos = ftell(tng_data->input_file);
18296 if(file_pos < tng_data->input_file_len)
18298 stat = tng_block_header_read(tng_data, block);
18302 tng_block_destroy(&block);
18303 if(stat == TNG_CRITICAL)
18305 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
18306 file_pos, __FILE__, __LINE__);
18314 *n_data_blocks_in_next_frame = 0;
18316 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
18318 p_data = &frame_set->tr_particle_data[i];
18319 block_id = p_data->block_id;
18321 if(n_requested_data_block_ids > 0)
18324 for(j = 0; j < n_requested_data_block_ids; j++)
18326 if(block_id == requested_data_block_ids[j])
18338 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
18339 p_data->last_retrieved_frame >=
18340 frame_set->first_frame + frame_set->n_frames))
18342 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
18343 TNG_USE_HASH, block_id);
18344 if(stat == TNG_CRITICAL)
18346 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18347 __FILE__, __LINE__);
18350 if(stat == TNG_FAILURE)
18355 if(frame_set->first_frame != current_frame &&
18356 p_data->last_retrieved_frame >= 0)
18358 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
18362 data_frame = p_data->first_frame_with_data;
18364 frame_diff = data_frame - current_frame;
18369 if(min_diff == -1 || frame_diff <= min_diff)
18371 if(frame_diff < min_diff)
18373 *n_data_blocks_in_next_frame = 1;
18377 *n_data_blocks_in_next_frame += 1;
18379 if(n_requested_data_block_ids <= 0)
18381 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
18382 temp = realloc(*data_block_ids_in_next_frame, size);
18385 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
18386 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
18387 __FILE__, __LINE__);
18388 free(*data_block_ids_in_next_frame);
18389 *data_block_ids_in_next_frame = 0;
18390 return(TNG_CRITICAL);
18392 *data_block_ids_in_next_frame = temp;
18396 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
18398 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
18400 min_diff = frame_diff;
18403 for(i = 0; i < frame_set->n_data_blocks; i++)
18405 np_data = &frame_set->tr_data[i];
18406 block_id = np_data->block_id;
18408 if(n_requested_data_block_ids > 0)
18411 for(j = 0; j < n_requested_data_block_ids; j++)
18413 if(block_id == requested_data_block_ids[j])
18425 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
18426 np_data->last_retrieved_frame >=
18427 frame_set->first_frame + frame_set->n_frames))
18429 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
18430 TNG_USE_HASH, block_id);
18431 if(stat == TNG_CRITICAL)
18433 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18434 __FILE__, __LINE__);
18437 if(stat == TNG_FAILURE)
18442 if(frame_set->first_frame != current_frame &&
18443 np_data->last_retrieved_frame >= 0)
18445 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
18449 data_frame = np_data->first_frame_with_data;
18451 frame_diff = data_frame - current_frame;
18456 if(min_diff == -1 || frame_diff <= min_diff)
18458 if(frame_diff < min_diff)
18460 *n_data_blocks_in_next_frame = 1;
18464 *n_data_blocks_in_next_frame += 1;
18466 if(n_requested_data_block_ids <= 0)
18468 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
18469 temp = realloc(*data_block_ids_in_next_frame, size);
18472 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
18473 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
18474 __FILE__, __LINE__);
18475 free(*data_block_ids_in_next_frame);
18476 *data_block_ids_in_next_frame = 0;
18477 return(TNG_CRITICAL);
18479 *data_block_ids_in_next_frame = temp;
18483 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
18485 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
18487 min_diff = frame_diff;
18492 return(TNG_FAILURE);
18494 *next_frame = current_frame + min_diff;
18496 return(TNG_SUCCESS);
18500 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
18501 (tng_trajectory_t tng_data,
18502 int64_t *n_data_blocks,
18503 int64_t **data_block_ids,
18504 char ***data_block_names,
18505 int64_t **stride_lengths,
18506 int64_t **n_values_per_frame,
18507 char **block_types,
18508 char **dependencies,
18509 char **compressions)
18511 tng_gen_block_t block;
18512 long orig_file_pos, file_pos;
18514 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18515 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
18516 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
18517 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
18518 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
18520 orig_file_pos = ftell(tng_data->input_file);
18522 if(!tng_data->input_file_len)
18524 fseek(tng_data->input_file, 0, SEEK_END);
18525 tng_data->input_file_len = ftell(tng_data->input_file);
18528 fseek(tng_data->input_file, 0, SEEK_SET);
18531 *n_data_blocks = 0;
18533 tng_block_init(&block);
18535 while(file_pos < tng_data->input_file_len &&
18536 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
18538 if(block->id > TNG_TRAJECTORY_FRAME_SET)
18542 file_pos += (long)(block->block_contents_size + block->header_contents_size);
18543 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
18546 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
18548 return(TNG_SUCCESS);
18551 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
18552 (tng_trajectory_t tng_data,
18553 const int64_t prev_frame)
18555 tng_function_status stat;
18556 FILE *temp = tng_data->input_file;
18558 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18559 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
18561 tng_data->input_file = tng_data->output_file;
18563 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
18564 if(stat != TNG_SUCCESS)
18569 tng_data->current_trajectory_frame_set_output_file_pos =
18570 tng_data->current_trajectory_frame_set_input_file_pos;
18572 tng_data->input_file = temp;
18574 return(TNG_SUCCESS);