1 /* This code is part of the tng binary trajectory format.
3 * Written by Magnus Lundborg
4 * Copyright (c) 2012-2014, The GROMACS development team.
5 * Check out http://www.gromacs.org for more information.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the Revised BSD License.
12 #ifdef USE_STD_INTTYPES_H
25 #include "tng/tng_io.h"
27 #include "compression/tng_compress.h"
28 #include "tng/version.h"
32 /** One of the atoms of the bond */
34 /** The other atom of the bond */
39 /** The residue containing this atom */
40 tng_residue_t residue;
41 /** A unique (per molecule) ID number of the atom */
43 /** The atom_type (depending on the forcefield) */
45 /** The name of the atom */
50 /** The chain containing this residue */
52 /** A unique (per chain) ID number of the residue */
54 /** The name of the residue */
56 /** The number of atoms in the residue */
58 /** A list of atoms in the residue */
63 /** The molecule containing this chain */
64 tng_molecule_t molecule;
65 /** A unique (per molecule) ID number of the chain */
67 /** The name of the chain */
69 /** The number of residues in the chain */
71 /** A list of residues in the chain */
72 tng_residue_t residues;
76 /** A unique ID number of the molecule */
78 /** Quaternary structure of the molecule.
83 int64_t quaternary_str;
84 /** The number of chains in the molecule */
86 /** The number of residues in the molecule */
88 /** The number of atoms in the molecule */
90 /** The number of bonds in the molecule. If the bonds are not specified this
93 /** The name of the molecule */
95 /** A list of chains in the molecule */
97 /** A list of residues in the molecule */
98 tng_residue_t residues;
99 /** A list of the atoms in the molecule */
101 /** A list of the bonds in the molecule */
105 struct tng_gen_block {
106 /** The size of the block header in bytes */
107 int64_t header_contents_size;
108 /** The size of the block contents in bytes */
109 int64_t block_contents_size;
110 /** The ID of the block to determine its type */
112 /** The MD5 hash of the block to verify integrity */
113 char md5_hash[TNG_MD5_HASH_LEN];
114 /** The name of the block */
116 /** The library version used to write the block */
117 int64_t block_version;
118 int64_t alt_hash_type;
119 int64_t alt_hash_len;
121 int64_t signature_type;
122 int64_t signature_len;
124 /** The full block header contents */
125 char *header_contents;
126 /** The full block contents */
127 char *block_contents;
130 struct tng_particle_mapping {
131 /** The index number of the first particle in this mapping block */
132 int64_t num_first_particle;
133 /** The number of particles list in this mapping block */
135 /** the mapping of index numbers to the real particle numbers in the
136 * trajectory. real_particle_numbers[0] is the real particle number
137 * (as it is numbered in the molecular system) of the first particle
138 * in the data blocks covered by this particle mapping block */
139 int64_t *real_particle_numbers;
142 struct tng_trajectory_frame_set {
143 /** The number of different particle mapping blocks present. */
144 int64_t n_mapping_blocks;
145 /** The atom mappings of this frame set */
146 struct tng_particle_mapping *mappings;
147 /** The first frame of this frame set */
149 /** The number of frames in this frame set */
151 /** The number of written frames in this frame set (used when writing one
152 * frame at a time). */
153 int64_t n_written_frames;
154 /** The number of frames not yet written to file in this frame set
155 * (used from the utility functions to finish the writing properly. */
156 int64_t n_unwritten_frames;
159 /** A list of the number of each molecule type - only used when using
160 * variable number of atoms */
161 int64_t *molecule_cnt_list;
162 /** The number of particles/atoms - only used when using variable number
165 /** The file position of the next frame set */
166 int64_t next_frame_set_file_pos;
167 /** The file position of the previous frame set */
168 int64_t prev_frame_set_file_pos;
169 /** The file position of the frame set one long stride step ahead */
170 int64_t medium_stride_next_frame_set_file_pos;
171 /** The file position of the frame set one long stride step behind */
172 int64_t medium_stride_prev_frame_set_file_pos;
173 /** The file position of the frame set one long stride step ahead */
174 int64_t long_stride_next_frame_set_file_pos;
175 /** The file position of the frame set one long stride step behind */
176 int64_t long_stride_prev_frame_set_file_pos;
177 /** Time stamp (in seconds) of first frame in frame set */
178 double first_frame_time;
180 /* The data blocks in a frame set are trajectory data blocks */
181 /** The number of trajectory data blocks of particle dependent data */
182 int n_particle_data_blocks;
183 /** A list of data blocks containing particle dependent data */
184 struct tng_particle_data *tr_particle_data;
185 /** The number of trajectory data blocks independent of particles */
187 /** A list of data blocks containing particle indepdendent data */
188 struct tng_non_particle_data *tr_data;
191 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
192 /* FIXME: Make only one data block struct */
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 2-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 /* These data blocks are non-trajectory data blocks */
356 /** The number of non-frame dependent particle dependent data blocks */
357 int n_particle_data_blocks;
358 /** A list of data blocks containing particle dependent data */
359 struct tng_particle_data *non_tr_particle_data;
361 /** The number of frame and particle independent data blocks */
363 /** A list of frame and particle indepdendent data blocks */
364 struct tng_non_particle_data *non_tr_data;
366 /** TNG compression algorithm for compressing positions */
367 int *compress_algo_pos;
368 /** TNG compression algorithm for compressing velocities */
369 int *compress_algo_vel;
370 /** The precision used for lossy compression */
371 double compression_precision;
375 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
377 #endif /* win32... */
378 #endif /* not defined USE_WINDOWS */
381 #define TNG_INLINE __inline
382 #define TNG_SNPRINTF _snprintf
384 #define TNG_INLINE inline
385 #define TNG_SNPRINTF snprintf
388 static TNG_INLINE int tng_min_i(int a, int b)
390 return (a < b ? a : b);
394 static TNG_INLINE int tng_max_i(int a, int b)
396 return (a > b ? a : b);
399 static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
401 return (a < b ? a : b);
404 static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
406 return (a > b ? a : b);
410 static TNG_INLINE float tng_min_f(float a, float b)
412 return (a < b ? a : b);
415 static TNG_INLINE float tng_max_f(float a, float b)
417 return (a > b ? a : b);
420 static TNG_INLINE double tng_min_d(double a, double b)
422 return (a < b ? a : b);
425 static TNG_INLINE double tng_max_d(double a, double b)
427 return (a > b ? a : b);
431 /** This function swaps the byte order of a 32 bit numerical variable
433 * It does not only work with integer, but e.g. floats need casting.
434 * If the byte order is already big endian no change is needed.
435 * @param tng_data is a trajectory data container.
436 * @param v is a pointer to a 32 bit numerical value (float or integer).
437 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
438 * byte order is not recognised.
440 static tng_function_status tng_swap_byte_order_big_endian_32
441 (const tng_trajectory_t tng_data, int32_t *v)
443 switch(tng_data->endianness_32)
445 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
446 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
447 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
448 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
449 ((*v & 0x000000FF) << 24); /* Move last byte to first */
453 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
454 *v = ((*v & 0xFFFF0000) >> 16) |
455 ((*v & 0x0000FFFF) << 16);
459 case TNG_BIG_ENDIAN_32: /* Already correct */
467 /** This function swaps the byte order of a 64 bit numerical variable
469 * It does not only work with integer, but e.g. floats need casting.
470 * The byte order swapping routine can convert four different byte
471 * orders to big endian.
472 * If the byte order is already big endian no change is needed.
473 * @param tng_data is a trajectory data container.
474 * @param v is a pointer to a 64 bit numerical value (double or integer).
475 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
476 * byte order is not recognised.
478 static tng_function_status tng_swap_byte_order_big_endian_64
479 (const tng_trajectory_t tng_data, int64_t *v)
481 switch(tng_data->endianness_64)
483 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
484 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
485 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
486 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
487 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
488 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
489 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
490 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
491 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
495 case TNG_QUAD_SWAP_64: /* Byte quad swap */
496 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
497 ((*v & 0x00000000FFFFFFFFLL) << 32);
501 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
502 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
503 ((*v & 0x0000FFFF0000FFFFLL) << 16);
507 case TNG_BYTE_SWAP_64: /* Byte swap */
508 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
509 ((*v & 0x00FF00FF00FF00FFLL) << 8);
513 case TNG_BIG_ENDIAN_64: /* Already correct */
521 /** This function swaps the byte order of a 32 bit numerical variable
523 * It does not only work with integer, but e.g. floats need casting.
524 * If the byte order is already little endian no change is needed.
525 * @param tng_data is a trajectory data container.
526 * @param v is a pointer to a 32 bit numerical value (float or integer).
527 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
528 * byte order is not recognised.
530 static tng_function_status tng_swap_byte_order_little_endian_32
531 (const tng_trajectory_t tng_data, int32_t *v)
533 switch(tng_data->endianness_32)
535 case TNG_LITTLE_ENDIAN_32: /* Already correct */
538 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
539 *v = ((*v & 0xFF00FF00) >> 8) |
540 ((*v & 0x00FF00FF) << 8);
544 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
545 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
546 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
547 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
548 ((*v & 0x000000FF) << 24); /* Move last byte to first */
557 /** This function swaps the byte order of a 64 bit numerical variable
559 * It does not only work with integer, but e.g. floats need casting.
560 * The byte order swapping routine can convert four different byte
561 * orders to little endian.
562 * If the byte order is already little endian no change is needed.
563 * @param tng_data is a trajectory data container.
564 * @param v is a pointer to a 64 bit numerical value (double or integer).
565 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
566 * byte order is not recognised.
568 static tng_function_status tng_swap_byte_order_little_endian_64
569 (const tng_trajectory_t tng_data, int64_t *v)
571 switch(tng_data->endianness_64)
573 case TNG_LITTLE_ENDIAN_64: /* Already correct */
576 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
577 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
578 ((*v & 0x00FF000000FF0000LL) >> 8) |
579 ((*v & 0x0000FF000000FF00LL) << 8) |
580 ((*v & 0x000000FF000000FFLL) << 24);
584 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
585 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
586 ((*v & 0x00FF00FF00000000LL) >> 24) |
587 ((*v & 0x00000000FF00FF00LL) << 24) |
588 ((*v & 0x0000000000FF00FFLL) << 40);
592 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
593 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
594 ((*v & 0x0000FFFF00000000LL) >> 16) |
595 ((*v & 0x00000000FFFF0000LL) << 16) |
596 ((*v & 0x000000000000FFFFLL) << 48);
600 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
601 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
602 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
603 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
604 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
605 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
606 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
607 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
608 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
616 /** Generate the md5 hash of a block.
617 * The hash is created based on the actual block contents.
618 * @param block is a general block container.
619 * @return TNG_SUCCESS (0) if successful.
621 static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
623 md5_state_t md5_state;
625 md5_init(&md5_state);
626 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
627 (int)block->block_contents_size);
628 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
633 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
634 * calculated from the current contents.
635 * If the current md5 hash is not set skip the comparison.
636 * @param block is a general block container.
637 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
638 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
639 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
642 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
645 md5_state_t md5_state;
646 char hash[TNG_MD5_HASH_LEN];
648 TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
651 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
655 md5_init(&md5_state);
656 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
657 (int)block->block_contents_size);
658 md5_finish(&md5_state, (md5_byte_t *)hash);
660 if(strncmp(block->md5_hash, hash, 16) != 0)
662 *results = TNG_FALSE;
668 /** Open the input file if it is not already opened.
669 * @param tng_data is a trajectory data container.
670 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
673 static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
675 if(!tng_data->input_file)
677 if(!tng_data->input_file_path)
679 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
681 return(TNG_CRITICAL);
683 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
684 if(!tng_data->input_file)
686 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
687 tng_data->input_file_path, __FILE__, __LINE__);
688 return(TNG_CRITICAL);
694 /** Open the output file if it is not already opened
695 * @param tng_data is a trajectory data container.
696 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
699 static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
701 if(!tng_data->output_file)
703 if(!tng_data->output_file_path)
705 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
707 return(TNG_CRITICAL);
710 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
712 if(!tng_data->output_file)
714 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
715 tng_data->output_file_path, __FILE__, __LINE__);
716 return(TNG_CRITICAL);
722 /** Setup a file block container.
723 * @param block_p a pointer to memory to initialise as a file block container.
724 * @details Memory is allocated during initialisation.
725 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
728 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
730 tng_gen_block_t block;
732 *block_p = malloc(sizeof(struct tng_gen_block));
735 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
736 sizeof(struct tng_gen_block), __FILE__, __LINE__);
737 return(TNG_CRITICAL);
743 /* Reset the md5_hash */
744 memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
746 block->block_version = TNG_API_VERSION;
747 block->header_contents = 0;
748 block->header_contents_size = 0;
749 block->block_contents = 0;
750 block->block_contents_size = 0;
756 * @brief Clean up a file block container.
757 * @param block_p a pointer to the file block container to destroy.
758 * @details All allocated memory in the data structure is freed, as well as
760 * @return TNG_SUCCESS (0) if successful.
762 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
764 tng_gen_block_t block = *block_p;
771 /* fprintf(stderr, "TNG library: Destroying block\n"); */
777 if(block->header_contents)
779 free(block->header_contents);
780 block->header_contents = 0;
782 if(block->block_contents)
784 free(block->block_contents);
785 block->block_contents = 0;
794 /** Read the header of a data block, regardless of its type
795 * @param tng_data is a trajectory data container.
796 * @param block is a general block container.
797 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
798 * error has occured (not able to read the header size, thus skipping
799 * the block) or TNG_CRITICAL (2) if a major error has occured.
801 static tng_function_status tng_block_header_read
802 (tng_trajectory_t tng_data, tng_gen_block_t block)
806 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
808 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
810 return(TNG_CRITICAL);
813 /* First read the header size to be able to read the whole header. */
814 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
815 1, tng_data->input_file) == 0)
817 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
819 return(TNG_CRITICAL);
822 if(block->header_contents_size == 0)
828 /* If this was the size of the general info block check the endianness */
829 if(ftell(tng_data->input_file) < 9)
831 /* File is little endian */
832 if ( *((const char*)&block->header_contents_size) != 0x00 &&
833 *((const char*)(&block->header_contents_size) + 7) == 0x00)
835 /* If the architecture endianness is little endian no byte swap
836 * will be needed. Otherwise use the functions to swap to little
838 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
840 tng_data->input_endianness_swap_func_32 = 0;
844 tng_data->input_endianness_swap_func_32 =
845 &tng_swap_byte_order_little_endian_32;
847 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
849 tng_data->input_endianness_swap_func_64 = 0;
853 tng_data->input_endianness_swap_func_64 =
854 &tng_swap_byte_order_little_endian_64;
857 /* File is big endian */
860 /* If the architecture endianness is big endian no byte swap
861 * will be needed. Otherwise use the functions to swap to big
863 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
865 tng_data->input_endianness_swap_func_32 = 0;
869 tng_data->input_endianness_swap_func_32 =
870 &tng_swap_byte_order_big_endian_32;
872 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
874 tng_data->input_endianness_swap_func_64 = 0;
878 tng_data->input_endianness_swap_func_64 =
879 &tng_swap_byte_order_big_endian_64;
884 if(tng_data->input_endianness_swap_func_64)
886 if(tng_data->input_endianness_swap_func_64(tng_data,
887 &block->header_contents_size)
890 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
895 /* Move the reading position to the beginning of the header. */
896 fseek(tng_data->input_file, -(long)sizeof(block->header_contents_size),
899 /* If there is already memory allocated for the contents free it (we do not
900 * know if the size is correct). */
901 if(block->header_contents)
903 free(block->header_contents);
906 block->header_contents = malloc(block->header_contents_size);
907 if(!block->header_contents)
909 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
910 block->header_contents_size, __FILE__, __LINE__);
911 return(TNG_CRITICAL);
914 /* Read the whole header into header_contents. This way it can be saved
915 * even if it cannot be interpreted
916 * for one reason or another. */
917 if(fread(block->header_contents, block->header_contents_size, 1,
918 tng_data->input_file) == 0)
920 fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
921 return(TNG_CRITICAL);
924 /* The header contents size has already been read. Skip ahead. */
925 offset = sizeof(block->header_contents_size);
928 /* Copy the respective parameters from the header contents block */
929 memcpy(&block->block_contents_size, block->header_contents+offset,
930 sizeof(block->block_contents_size));
931 if(tng_data->input_endianness_swap_func_64)
933 if(tng_data->input_endianness_swap_func_64(tng_data,
934 &block->block_contents_size)
937 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
942 offset += sizeof(block->block_contents_size);
944 memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
945 if(tng_data->input_endianness_swap_func_64)
947 if(tng_data->input_endianness_swap_func_64(tng_data,
951 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
956 offset += sizeof(block->id);
958 memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
959 offset += TNG_MD5_HASH_LEN;
961 if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
966 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
969 block->name = malloc(len);
972 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
974 return(TNG_CRITICAL);
976 strncpy(block->name, block->header_contents+offset, len);
980 memcpy(&block->block_version, block->header_contents+offset,
981 sizeof(block->block_version));
982 if(tng_data->input_endianness_swap_func_64)
984 if(tng_data->input_endianness_swap_func_64(tng_data,
985 &block->block_version)
988 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
996 /** Write a whole block, both header and contents, regardless of it type
997 * @param tng_data is a trajectory data container.
998 * @param block is a general block container.
999 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1000 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1002 /* Disabled until it is used.*/
1004 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1005 // tng_gen_block_t block)
1007 // if(!block->header_contents)
1009 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1010 // return(TNG_FAILURE);
1012 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1013 // tng_data->output_file) != 1)
1015 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1016 // __FILE__, __LINE__);
1017 // return(TNG_CRITICAL);
1020 // if(!block->block_contents)
1022 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1023 // __FILE__, __LINE__);
1024 // return(TNG_FAILURE);
1026 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1027 // tng_data->output_file) != 1)
1029 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1030 // __FILE__, __LINE__);
1031 // return(TNG_CRITICAL);
1033 // return(TNG_SUCCESS);
1037 /** Update the md5 hash of a block already written to the file
1038 * @param tng_data is a trajectory data container.
1039 * @param block is the block, of which to update the md5 hash.
1040 * @param header_start_pos is the file position where the block header starts.
1041 * @param contents_start_pos is the file position where the block contents
1043 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1044 * error has occured.
1046 static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
1047 tng_gen_block_t block,
1048 const int64_t header_start_pos,
1049 const int64_t contents_start_pos)
1051 if(block->block_contents)
1053 free(block->block_contents);
1056 block->block_contents = malloc(block->block_contents_size);
1057 if(!block->block_contents)
1059 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1060 block->block_contents_size, __FILE__, __LINE__);
1061 return(TNG_CRITICAL);
1064 fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
1065 if(fread(block->block_contents, block->block_contents_size, 1,
1066 tng_data->output_file) == 0)
1068 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1069 return(TNG_CRITICAL);
1072 tng_block_md5_hash_generate(block);
1074 fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
1076 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
1078 return(TNG_SUCCESS);
1081 /** Update the frame set pointers in the file header (general info block),
1082 * already written to disk
1083 * @param tng_data is a trajectory data container.
1084 * @param hash_mode specifies whether to update the block md5 hash when
1085 * updating the pointers.
1086 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1087 * error has occured.
1089 static tng_function_status tng_header_pointers_update
1090 (tng_trajectory_t tng_data, const char hash_mode)
1092 tng_gen_block_t block;
1093 FILE *temp = tng_data->input_file;
1094 int64_t output_file_pos, pos, contents_start_pos;
1096 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1098 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1099 __FILE__, __LINE__);
1100 return(TNG_CRITICAL);
1103 tng_data->input_file = tng_data->output_file;
1105 tng_block_init(&block);
1107 output_file_pos = ftell(tng_data->output_file);
1108 fseek(tng_data->output_file, 0, SEEK_SET);
1110 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1112 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
1113 __FILE__, __LINE__);
1114 tng_data->input_file = temp;
1115 tng_block_destroy(&block);
1116 return(TNG_CRITICAL);
1119 contents_start_pos = ftell(tng_data->output_file);
1121 fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
1122 sizeof(int64_t), SEEK_CUR);
1124 tng_data->input_file = temp;
1126 pos = tng_data->first_trajectory_frame_set_output_file_pos;
1128 if(tng_data->input_endianness_swap_func_64)
1130 if(tng_data->input_endianness_swap_func_64(tng_data,
1134 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1135 __FILE__, __LINE__);
1139 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1141 tng_block_destroy(&block);
1142 return(TNG_CRITICAL);
1145 pos = tng_data->last_trajectory_frame_set_output_file_pos;
1147 if(tng_data->input_endianness_swap_func_64)
1149 if(tng_data->input_endianness_swap_func_64(tng_data,
1153 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1154 __FILE__, __LINE__);
1159 sizeof(int64_t), 1, tng_data->output_file) != 1)
1161 tng_block_destroy(&block);
1162 return(TNG_CRITICAL);
1165 if(hash_mode == TNG_USE_HASH)
1167 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
1170 tng_block_destroy(&block);
1172 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1174 return(TNG_SUCCESS);
1177 /** Update the frame set pointers in the current frame set block, already
1178 * written to disk. It also updates the pointers of the blocks pointing to
1179 * the current frame set block.
1180 * @param tng_data is a trajectory data container.
1181 * @param hash_mode specifies whether to update the block md5 hash when
1182 * updating the pointers.
1183 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1184 * error has occured.
1186 static tng_function_status tng_frame_set_pointers_update
1187 (tng_trajectory_t tng_data, const char hash_mode)
1189 tng_gen_block_t block;
1190 tng_trajectory_frame_set_t frame_set;
1191 FILE *temp = tng_data->input_file;
1192 int64_t pos, output_file_pos, contents_start_pos;
1194 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1196 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1197 __FILE__, __LINE__);
1198 return(TNG_CRITICAL);
1201 tng_block_init(&block);
1202 output_file_pos = ftell(tng_data->output_file);
1204 tng_data->input_file = tng_data->output_file;
1206 frame_set = &tng_data->current_trajectory_frame_set;
1208 pos = tng_data->current_trajectory_frame_set_output_file_pos;
1210 /* Update next frame set */
1211 if(frame_set->next_frame_set_file_pos > 0)
1213 fseek(tng_data->output_file, (long)frame_set->next_frame_set_file_pos,
1216 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1218 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1219 __FILE__, __LINE__);
1220 tng_data->input_file = temp;
1221 tng_block_destroy(&block);
1222 return(TNG_CRITICAL);
1225 contents_start_pos = ftell(tng_data->output_file);
1227 fseek(tng_data->output_file, (long)block->block_contents_size - (5 *
1228 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1230 if(tng_data->input_endianness_swap_func_64)
1232 if(tng_data->input_endianness_swap_func_64(tng_data,
1236 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1237 __FILE__, __LINE__);
1241 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1243 tng_data->input_file = temp;
1244 tng_block_destroy(&block);
1245 return(TNG_CRITICAL);
1248 if(hash_mode == TNG_USE_HASH)
1250 tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
1251 contents_start_pos);
1253 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1255 /* Update previous frame set */
1256 if(frame_set->prev_frame_set_file_pos > 0)
1258 fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
1261 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1263 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1264 __FILE__, __LINE__);
1265 tng_data->input_file = temp;
1266 tng_block_destroy(&block);
1267 return(TNG_CRITICAL);
1270 contents_start_pos = ftell(tng_data->output_file);
1272 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
1273 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1275 if(tng_data->input_endianness_swap_func_64)
1277 if(tng_data->input_endianness_swap_func_64(tng_data,
1281 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1282 __FILE__, __LINE__);
1286 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1288 tng_data->input_file = temp;
1289 tng_block_destroy(&block);
1290 return(TNG_CRITICAL);
1293 if(hash_mode == TNG_USE_HASH)
1295 tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
1296 contents_start_pos);
1298 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1301 /* Update the frame set one medium stride step after */
1302 if(frame_set->medium_stride_next_frame_set_file_pos > 0)
1304 fseek(tng_data->output_file,
1305 (long)frame_set->medium_stride_next_frame_set_file_pos,
1308 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1310 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1311 __FILE__, __LINE__);
1312 tng_data->input_file = temp;
1313 tng_block_destroy(&block);
1314 return(TNG_CRITICAL);
1317 contents_start_pos = ftell(tng_data->output_file);
1319 fseek(tng_data->output_file, (long)block->block_contents_size - (3 *
1320 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1322 if(tng_data->input_endianness_swap_func_64)
1324 if(tng_data->input_endianness_swap_func_64(tng_data,
1328 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1329 __FILE__, __LINE__);
1333 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1335 tng_data->input_file = temp;
1336 tng_block_destroy(&block);
1337 return(TNG_CRITICAL);
1340 if(hash_mode == TNG_USE_HASH)
1342 tng_md5_hash_update(tng_data, block,
1343 frame_set->medium_stride_next_frame_set_file_pos,
1344 contents_start_pos);
1347 /* Update the frame set one medium stride step before */
1348 if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
1350 fseek(tng_data->output_file,
1351 (long)frame_set->medium_stride_prev_frame_set_file_pos,
1354 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1356 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1357 __FILE__, __LINE__);
1358 tng_data->input_file = temp;
1359 tng_block_destroy(&block);
1360 return(TNG_CRITICAL);
1363 contents_start_pos = ftell(tng_data->output_file);
1365 fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
1366 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1368 if(tng_data->input_endianness_swap_func_64)
1370 if(tng_data->input_endianness_swap_func_64(tng_data,
1374 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1375 __FILE__, __LINE__);
1379 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1381 tng_data->input_file = temp;
1382 tng_block_destroy(&block);
1383 return(TNG_CRITICAL);
1386 if(hash_mode == TNG_USE_HASH)
1388 tng_md5_hash_update(tng_data, block,
1389 frame_set->medium_stride_prev_frame_set_file_pos,
1390 contents_start_pos);
1394 /* Update the frame set one long stride step after */
1395 if(frame_set->long_stride_next_frame_set_file_pos > 0)
1397 fseek(tng_data->output_file,
1398 (long)frame_set->long_stride_next_frame_set_file_pos,
1401 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1403 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1404 __FILE__, __LINE__);
1405 tng_data->input_file = temp;
1406 tng_block_destroy(&block);
1407 return(TNG_CRITICAL);
1410 contents_start_pos = ftell(tng_data->output_file);
1412 fseek(tng_data->output_file, (long)block->block_contents_size - (1 *
1413 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1415 if(tng_data->input_endianness_swap_func_64)
1417 if(tng_data->input_endianness_swap_func_64(tng_data,
1421 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1422 __FILE__, __LINE__);
1426 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1428 tng_data->input_file = temp;
1429 tng_block_destroy(&block);
1430 return(TNG_CRITICAL);
1433 if(hash_mode == TNG_USE_HASH)
1435 tng_md5_hash_update(tng_data, block,
1436 frame_set->long_stride_next_frame_set_file_pos,
1437 contents_start_pos);
1440 /* Update the frame set one long stride step before */
1441 if(frame_set->long_stride_prev_frame_set_file_pos > 0)
1443 fseek(tng_data->output_file,
1444 (long)frame_set->long_stride_prev_frame_set_file_pos,
1447 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1449 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1450 __FILE__, __LINE__);
1451 tng_data->input_file = temp;
1452 tng_block_destroy(&block);
1453 return(TNG_CRITICAL);
1456 contents_start_pos = ftell(tng_data->output_file);
1458 fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
1459 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1461 if(tng_data->input_endianness_swap_func_64)
1463 if(tng_data->input_endianness_swap_func_64(tng_data,
1467 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1468 __FILE__, __LINE__);
1472 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1474 tng_data->input_file = temp;
1475 tng_block_destroy(&block);
1476 return(TNG_CRITICAL);
1479 if(hash_mode == TNG_USE_HASH)
1481 tng_md5_hash_update(tng_data, block,
1482 frame_set->long_stride_prev_frame_set_file_pos,
1483 contents_start_pos);
1487 fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
1489 tng_data->input_file = temp;
1491 tng_block_destroy(&block);
1493 return(TNG_SUCCESS);
1496 static tng_function_status tng_reread_frame_set_at_file_pos
1497 (tng_trajectory_t tng_data,
1500 tng_gen_block_t block;
1501 tng_function_status stat;
1503 tng_block_init(&block);
1505 fseek(tng_data->input_file, pos, SEEK_SET);
1508 stat = tng_block_header_read(tng_data, block);
1509 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1511 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
1512 __FILE__, __LINE__);
1513 tng_block_destroy(&block);
1514 return(TNG_FAILURE);
1517 if(tng_block_read_next(tng_data, block,
1518 TNG_SKIP_HASH) != TNG_SUCCESS)
1520 tng_block_destroy(&block);
1521 return(TNG_CRITICAL);
1525 tng_block_destroy(&block);
1527 return(TNG_SUCCESS);
1530 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1531 (tng_trajectory_t tng_data,
1534 int64_t orig_pos, curr_frame_set_pos;
1535 tng_gen_block_t block;
1536 tng_function_status stat;
1537 tng_trajectory_frame_set_t frame_set =
1538 &tng_data->current_trajectory_frame_set;
1540 orig_pos = ftell(tng_data->input_file);
1541 curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
1543 *pos = tng_data->first_trajectory_frame_set_input_file_pos;
1547 return(TNG_SUCCESS);
1550 fseek(tng_data->input_file, *pos, SEEK_SET);
1552 tng_block_init(&block);
1553 /* Read block headers first to see that a frame set block is found. */
1554 stat = tng_block_header_read(tng_data, block);
1555 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1557 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1558 __FILE__, __LINE__);
1559 tng_block_destroy(&block);
1560 return(TNG_FAILURE);
1563 if(tng_block_read_next(tng_data, block,
1564 TNG_SKIP_HASH) != TNG_SUCCESS)
1566 tng_block_destroy(&block);
1567 return(TNG_CRITICAL);
1570 /* Read all frame set blocks (not the blocks between them) */
1571 while(frame_set->next_frame_set_file_pos > 0)
1573 fseek(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1574 stat = tng_block_header_read(tng_data, block);
1575 if(stat == TNG_CRITICAL)
1577 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1578 __FILE__, __LINE__);
1579 tng_block_destroy(&block);
1580 return(TNG_CRITICAL);
1582 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1584 return(TNG_FAILURE);
1587 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
1588 if(stat != TNG_SUCCESS)
1590 tng_block_destroy(&block);
1593 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1594 if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
1595 tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
1597 *pos = tng_data->current_trajectory_frame_set_input_file_pos;
1601 /* Re-read the frame set that used to be the current one */
1602 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1604 fseek(tng_data->input_file, orig_pos, SEEK_SET);
1606 tng_block_destroy(&block);
1608 return(TNG_SUCCESS);
1611 static tng_function_status tng_frame_set_complete_migrate
1612 (tng_trajectory_t tng_data,
1613 int64_t block_start_pos,
1618 tng_bool updated = TNG_FALSE;
1622 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1624 return(TNG_CRITICAL);
1627 fseek(tng_data->input_file, block_start_pos, SEEK_SET);
1629 contents = malloc(block_len);
1632 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1633 block_len, __FILE__, __LINE__);
1634 return(TNG_CRITICAL);
1637 if(fread(contents, block_len, 1, tng_data->input_file) == 0)
1639 fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1640 __FILE__, __LINE__);
1642 return(TNG_CRITICAL);
1644 fseek(tng_data->output_file, new_pos, SEEK_SET);
1646 if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
1648 fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1649 __FILE__, __LINE__);
1651 return(TNG_CRITICAL);
1654 tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
1656 tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
1658 /* Update the general info block if needed */
1659 if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
1661 tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
1664 if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
1666 tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
1671 tng_header_pointers_update(tng_data, TNG_USE_HASH);
1674 /* Fill the block with NULL to avoid confusion. */
1675 for(i = 0; i < block_len; i++)
1679 fseek(tng_data->output_file, block_start_pos, SEEK_SET);
1681 /* FIXME: casting block_len to size_t is dangerous */
1682 fwrite(contents, 1, block_len, tng_data->output_file);
1686 return(TNG_SUCCESS);
1689 static tng_function_status tng_length_of_current_frame_set_contents_get
1690 (tng_trajectory_t tng_data,
1693 int64_t orig_pos, pos, curr_frame_set_pos;
1694 tng_gen_block_t block;
1695 tng_function_status stat;
1697 orig_pos = ftell(tng_data->input_file);
1698 curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
1702 fseek(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
1704 tng_block_init(&block);
1705 /* Read block headers first to see that a frame set block is found. */
1706 stat = tng_block_header_read(tng_data, block);
1707 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1709 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
1710 curr_frame_set_pos, __FILE__, __LINE__);
1711 tng_block_destroy(&block);
1712 return(TNG_FAILURE);
1715 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1716 while(stat == TNG_SUCCESS)
1718 fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
1719 *len += block->header_contents_size + block->block_contents_size;
1720 pos += block->header_contents_size + block->block_contents_size;
1721 if(pos >= tng_data->input_file_len)
1725 stat = tng_block_header_read(tng_data, block);
1726 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1732 /* Re-read the frame set that used to be the current one */
1733 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1735 fseek(tng_data->input_file, orig_pos, SEEK_SET);
1737 tng_block_destroy(&block);
1739 return(TNG_SUCCESS);
1742 /** Migrate blocks in the file to make room for new data in a block. This
1743 * is required e.g. when adding data to a block or extending strings in a
1745 * @param tng_data is a trajectory data container.
1746 * @param start_pos is the position from which to start moving data, usually
1747 * the byte after the end of the block to which data was added.
1748 * @param offset is the number of bytes that were inserted.
1749 * @details Trajectory blocks (frame sets and their related blocks) are moved
1750 * to the end of the file (if needed) in order to make room for non-trajectory
1753 static tng_function_status tng_migrate_data_in_file
1754 (tng_trajectory_t tng_data,
1758 int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
1759 tng_gen_block_t block;
1760 tng_function_status stat;
1765 return(TNG_SUCCESS);
1768 temp = tng_data->input_file;
1770 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1771 if(stat != TNG_SUCCESS)
1773 tng_data->input_file = temp;
1777 tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
1779 empty_space = traj_start_pos - (start_pos - 1);
1781 if(empty_space >= offset)
1783 return(TNG_SUCCESS);
1786 orig_file_pos = ftell(tng_data->input_file);
1787 tng_block_init(&block);
1789 while(empty_space < offset)
1791 fseek(tng_data->input_file, traj_start_pos, SEEK_SET);
1792 stat = tng_block_header_read(tng_data, block);
1793 if(stat == TNG_CRITICAL)
1795 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
1796 __FILE__, __LINE__);
1797 tng_block_destroy(&block);
1798 tng_data->input_file = temp;
1799 return(TNG_CRITICAL);
1801 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1803 tng_data->input_file = temp;
1804 tng_block_destroy(&block);
1805 return(TNG_FAILURE);
1807 stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
1808 if(stat != TNG_SUCCESS)
1810 tng_data->input_file = temp;
1811 tng_block_destroy(&block);
1814 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1815 frame_set_length, tng_data->input_file_len);
1816 if(stat != TNG_SUCCESS)
1818 tng_data->input_file = temp;
1819 tng_block_destroy(&block);
1823 empty_space += frame_set_length;
1825 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
1826 tng_block_destroy(&block);
1828 return(TNG_SUCCESS);
1831 static tng_function_status tng_block_header_len_calculate
1832 (const tng_trajectory_t tng_data,
1833 tng_gen_block_t block,
1839 /* If the string is unallocated allocate memory for just string
1843 block->name = malloc(1);
1846 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1847 __FILE__, __LINE__);
1848 return(TNG_CRITICAL);
1853 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1855 /* Calculate the size of the header to write */
1856 *len = sizeof(block->header_contents_size) +
1857 sizeof(block->block_contents_size) +
1859 sizeof(block->block_version) +
1863 return (TNG_SUCCESS);
1866 /** Write the header of a data block, regardless of its type
1867 * @param tng_data is a trajectory data container.
1868 * @param block is a general block container.
1869 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1870 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1871 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1872 * error has occured.
1874 static tng_function_status tng_block_header_write
1875 (tng_trajectory_t tng_data,
1876 tng_gen_block_t block,
1877 const char hash_mode)
1879 int name_len, offset = 0;
1881 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1883 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1885 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1886 __FILE__, __LINE__);
1887 return(TNG_CRITICAL);
1890 if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
1893 fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
1894 __FILE__, __LINE__);
1895 return(TNG_CRITICAL);
1898 if(hash_mode == TNG_USE_HASH)
1900 tng_block_md5_hash_generate(block);
1903 if(block->header_contents)
1905 free(block->header_contents);
1908 block->header_contents = malloc(block->header_contents_size);
1909 if(!block->header_contents)
1911 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1912 block->header_contents_size, __FILE__, __LINE__);
1913 return(TNG_CRITICAL);
1916 name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
1918 /* First copy all data into the header_contents block and finally write
1919 * the whole block at once. */
1920 memcpy(block->header_contents, &block->header_contents_size,
1921 sizeof(block->header_contents_size));
1922 if(tng_data->output_endianness_swap_func_64)
1924 if(tng_data->output_endianness_swap_func_64(tng_data,
1925 (int64_t *)block->header_contents+offset)
1928 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1929 __FILE__, __LINE__);
1932 offset += sizeof(block->header_contents_size);
1934 memcpy(block->header_contents+offset, &block->block_contents_size,
1935 sizeof(block->block_contents_size));
1936 if(tng_data->output_endianness_swap_func_64)
1938 if(tng_data->output_endianness_swap_func_64(tng_data,
1939 (int64_t *)block->header_contents+offset)
1942 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1943 __FILE__, __LINE__);
1946 offset += sizeof(block->block_contents_size);
1948 memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
1949 if(tng_data->output_endianness_swap_func_64)
1951 if(tng_data->output_endianness_swap_func_64(tng_data,
1952 (int64_t *)block->header_contents+offset)
1955 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1956 __FILE__, __LINE__);
1959 offset += sizeof(block->id);
1961 memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
1962 offset += TNG_MD5_HASH_LEN;
1964 strncpy(block->header_contents+offset, block->name, name_len);
1967 memcpy(block->header_contents+offset, &block->block_version,
1968 sizeof(block->block_version));
1969 if(tng_data->output_endianness_swap_func_64)
1971 if(tng_data->output_endianness_swap_func_64(tng_data,
1972 (int64_t *)block->header_contents+offset)
1975 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1976 __FILE__, __LINE__);
1980 if(fwrite(block->header_contents, block->header_contents_size,
1981 1, tng_data->output_file) != 1)
1983 fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
1984 return(TNG_CRITICAL);
1986 return(TNG_SUCCESS);
1989 static tng_function_status tng_general_info_block_len_calculate
1990 (tng_trajectory_t tng_data,
1993 int first_program_name_len, first_user_name_len;
1994 int first_computer_name_len, first_pgp_signature_len;
1995 int last_program_name_len, last_user_name_len;
1996 int last_computer_name_len, last_pgp_signature_len;
1997 int forcefield_name_len;
1999 /* If the strings are unallocated allocate memory for just string
2001 if(!tng_data->first_program_name)
2003 tng_data->first_program_name = malloc(1);
2004 if(!tng_data->first_program_name)
2006 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2007 __FILE__, __LINE__);
2008 return(TNG_CRITICAL);
2010 tng_data->first_program_name[0] = 0;
2012 if(!tng_data->last_program_name)
2014 tng_data->last_program_name = malloc(1);
2015 if(!tng_data->last_program_name)
2017 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2018 __FILE__, __LINE__);
2019 return(TNG_CRITICAL);
2021 tng_data->last_program_name[0] = 0;
2023 if(!tng_data->first_user_name)
2025 tng_data->first_user_name = malloc(1);
2026 if(!tng_data->first_user_name)
2028 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2029 __FILE__, __LINE__);
2030 return(TNG_CRITICAL);
2032 tng_data->first_user_name[0] = 0;
2034 if(!tng_data->last_user_name)
2036 tng_data->last_user_name = malloc(1);
2037 if(!tng_data->last_user_name)
2039 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2040 __FILE__, __LINE__);
2041 return(TNG_CRITICAL);
2043 tng_data->last_user_name[0] = 0;
2045 if(!tng_data->first_computer_name)
2047 tng_data->first_computer_name = malloc(1);
2048 if(!tng_data->first_computer_name)
2050 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2051 __FILE__, __LINE__);
2052 return(TNG_CRITICAL);
2054 tng_data->first_computer_name[0] = 0;
2056 if(!tng_data->last_computer_name)
2058 tng_data->last_computer_name = malloc(1);
2059 if(!tng_data->last_computer_name)
2061 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2062 __FILE__, __LINE__);
2063 return(TNG_CRITICAL);
2065 tng_data->last_computer_name[0] = 0;
2067 if(!tng_data->first_pgp_signature)
2069 tng_data->first_pgp_signature = malloc(1);
2070 if(!tng_data->first_pgp_signature)
2072 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2073 __FILE__, __LINE__);
2074 return(TNG_CRITICAL);
2076 tng_data->first_pgp_signature[0] = 0;
2078 if(!tng_data->last_pgp_signature)
2080 tng_data->last_pgp_signature = malloc(1);
2081 if(!tng_data->last_pgp_signature)
2083 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2084 __FILE__, __LINE__);
2085 return(TNG_CRITICAL);
2087 tng_data->last_pgp_signature[0] = 0;
2089 if(!tng_data->forcefield_name)
2091 tng_data->forcefield_name = malloc(1);
2092 if(!tng_data->forcefield_name)
2094 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2095 __FILE__, __LINE__);
2096 return(TNG_CRITICAL);
2098 tng_data->forcefield_name[0] = 0;
2101 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2103 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2105 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2107 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2109 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2111 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2113 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2115 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2117 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2120 *len = sizeof(tng_data->time) +
2121 sizeof(tng_data->var_num_atoms_flag) +
2122 sizeof(tng_data->frame_set_n_frames) +
2123 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
2124 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
2125 sizeof(tng_data->medium_stride_length) +
2126 sizeof(tng_data->long_stride_length) +
2127 sizeof(tng_data->distance_unit_exponential) +
2128 first_program_name_len +
2129 last_program_name_len +
2130 first_user_name_len +
2131 last_user_name_len +
2132 first_computer_name_len +
2133 last_computer_name_len +
2134 first_pgp_signature_len +
2135 last_pgp_signature_len +
2136 forcefield_name_len;
2138 return(TNG_SUCCESS);
2141 /** Read a general info block. This is the first block of a TNG file.
2142 * Populate the fields in tng_data.
2143 * @param tng_data is a trajectory data container.
2144 * @param block is a general block container.
2145 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2146 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2147 * compared to the md5 hash of the read contents to ensure valid data.
2148 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2149 * error has occured.
2151 static tng_function_status tng_general_info_block_read
2152 (tng_trajectory_t tng_data, tng_gen_block_t block,
2153 const char hash_mode)
2155 int len, offset = 0;
2160 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2162 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2164 return(TNG_CRITICAL);
2167 temp = realloc(block->block_contents, block->block_contents_size);
2170 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2171 block->block_contents_size, __FILE__, __LINE__);
2172 free(block->block_contents);
2173 block->block_contents = 0;
2174 return(TNG_CRITICAL);
2176 block->block_contents = temp;
2178 /* Read the whole block into block_contents to be able to write it to disk
2179 * even if it cannot be interpreted. */
2180 if(fread(block->block_contents, block->block_contents_size, 1,
2181 tng_data->input_file) == 0)
2183 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
2184 return(TNG_CRITICAL);
2187 /* FIXME: Does not check if the size of the contents matches the expected
2188 * size or if the contents can be read. */
2190 if(hash_mode == TNG_USE_HASH)
2192 tng_md5_hash_match_verify(block, &same_hash);
2193 if(same_hash != TNG_TRUE)
2195 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
2197 __FILE__, __LINE__);
2198 /* return(TNG_FAILURE); */
2202 len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
2203 temp = realloc(tng_data->first_program_name, len);
2206 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2207 __FILE__, __LINE__);
2208 free(tng_data->first_program_name);
2209 tng_data->first_program_name = 0;
2210 return(TNG_CRITICAL);
2212 tng_data->first_program_name = temp;
2213 strncpy(tng_data->first_program_name, block->block_contents, len);
2216 len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
2217 temp = realloc(tng_data->last_program_name, len);
2220 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2221 __FILE__, __LINE__);
2222 free(tng_data->last_program_name);
2223 tng_data->last_program_name = 0;
2224 return(TNG_CRITICAL);
2226 tng_data->last_program_name = temp;
2227 strncpy(tng_data->last_program_name, block->block_contents + offset, len);
2230 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2231 temp = realloc(tng_data->first_user_name, len);
2234 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2235 __FILE__, __LINE__);
2236 free(tng_data->first_user_name);
2237 tng_data->first_user_name = 0;
2238 return(TNG_CRITICAL);
2240 tng_data->first_user_name = temp;
2241 strncpy(tng_data->first_user_name, block->block_contents+offset, len);
2244 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2245 temp = realloc(tng_data->last_user_name, len);
2248 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2249 __FILE__, __LINE__);
2250 free(tng_data->last_user_name);
2251 tng_data->last_user_name = 0;
2252 return(TNG_CRITICAL);
2254 tng_data->last_user_name = temp;
2255 strncpy(tng_data->last_user_name, block->block_contents+offset, len);
2258 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2259 temp = realloc(tng_data->first_computer_name, len);
2262 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2263 __FILE__, __LINE__);
2264 free(tng_data->first_computer_name);
2265 tng_data->first_computer_name = 0;
2266 return(TNG_CRITICAL);
2268 tng_data->first_computer_name = temp;
2269 strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
2272 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2273 temp = realloc(tng_data->last_computer_name, len);
2276 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2277 __FILE__, __LINE__);
2278 free(tng_data->last_computer_name);
2279 tng_data->last_computer_name = 0;
2280 return(TNG_CRITICAL);
2282 tng_data->last_computer_name = temp;
2283 strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
2286 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2287 temp = realloc(tng_data->first_pgp_signature, len);
2290 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2291 __FILE__, __LINE__);
2292 free(tng_data->first_pgp_signature);
2293 tng_data->first_pgp_signature = 0;
2294 return(TNG_CRITICAL);
2296 tng_data->first_pgp_signature = temp;
2297 strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
2300 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2301 temp = realloc(tng_data->last_pgp_signature, len);
2304 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2305 __FILE__, __LINE__);
2306 free(tng_data->last_pgp_signature);
2307 tng_data->last_pgp_signature = 0;
2308 return(TNG_CRITICAL);
2310 tng_data->last_pgp_signature = temp;
2311 strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
2314 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
2315 temp = realloc(tng_data->forcefield_name, len);
2318 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
2319 __FILE__, __LINE__);
2320 free(tng_data->forcefield_name);
2321 tng_data->forcefield_name = 0;
2322 return(TNG_CRITICAL);
2324 tng_data->forcefield_name = temp;
2325 strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
2328 memcpy(&tng_data->time, block->block_contents+offset,
2329 sizeof(tng_data->time));
2330 if(tng_data->input_endianness_swap_func_64)
2332 if(tng_data->input_endianness_swap_func_64(tng_data,
2336 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2337 __FILE__, __LINE__);
2340 offset += sizeof(tng_data->time);
2342 memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
2343 sizeof(tng_data->var_num_atoms_flag));
2344 offset += sizeof(tng_data->var_num_atoms_flag);
2346 memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
2347 sizeof(tng_data->frame_set_n_frames));
2348 if(tng_data->input_endianness_swap_func_64)
2350 if(tng_data->input_endianness_swap_func_64(tng_data,
2351 &tng_data->frame_set_n_frames)
2354 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2355 __FILE__, __LINE__);
2358 offset += sizeof(tng_data->frame_set_n_frames);
2360 memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
2361 block->block_contents+offset,
2362 sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
2363 if(tng_data->input_endianness_swap_func_64)
2365 if(tng_data->input_endianness_swap_func_64(tng_data,
2366 &tng_data->first_trajectory_frame_set_input_file_pos)
2369 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2370 __FILE__, __LINE__);
2373 offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
2375 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
2376 tng_data->first_trajectory_frame_set_input_file_pos;
2379 memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
2380 block->block_contents+offset,
2381 sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
2382 if(tng_data->input_endianness_swap_func_64)
2384 if(tng_data->input_endianness_swap_func_64(tng_data,
2385 &tng_data->last_trajectory_frame_set_input_file_pos)
2388 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2389 __FILE__, __LINE__);
2392 offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
2394 memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
2395 sizeof(tng_data->medium_stride_length));
2396 if(tng_data->input_endianness_swap_func_64)
2398 if(tng_data->input_endianness_swap_func_64(tng_data,
2399 &tng_data->medium_stride_length)
2402 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2403 __FILE__, __LINE__);
2406 offset += sizeof(tng_data->medium_stride_length);
2408 memcpy(&tng_data->long_stride_length, block->block_contents+offset,
2409 sizeof(tng_data->long_stride_length));
2410 if(tng_data->input_endianness_swap_func_64)
2412 if(tng_data->input_endianness_swap_func_64(tng_data,
2413 &tng_data->long_stride_length)
2416 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2417 __FILE__, __LINE__);
2420 offset += sizeof(tng_data->long_stride_length);
2422 if(block->block_version >= 3)
2424 memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
2425 sizeof(tng_data->distance_unit_exponential));
2426 if(tng_data->input_endianness_swap_func_64)
2428 if(tng_data->input_endianness_swap_func_64(tng_data,
2429 &tng_data->distance_unit_exponential)
2432 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2433 __FILE__, __LINE__);
2438 return(TNG_SUCCESS);
2441 /** Write a general info block. This is the first block of a TNG file.
2442 * @param tng_data is a trajectory data container.
2443 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2444 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2445 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2446 * error has occured.
2448 static tng_function_status tng_general_info_block_write
2449 (tng_trajectory_t tng_data,
2450 const char hash_mode)
2452 int first_program_name_len, first_user_name_len;
2453 int first_computer_name_len, first_pgp_signature_len;
2454 int last_program_name_len, last_user_name_len;
2455 int last_computer_name_len, last_pgp_signature_len;
2456 int forcefield_name_len, name_len;
2458 tng_gen_block_t block;
2460 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2462 return(TNG_CRITICAL);
2465 fseek(tng_data->output_file, 0, SEEK_SET);
2467 tng_block_init(&block);
2469 name_len = (int)strlen("GENERAL INFO");
2471 block->name = malloc(name_len + 1);
2474 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2475 name_len+1, __FILE__, __LINE__);
2476 tng_block_destroy(&block);
2477 return(TNG_CRITICAL);
2480 strcpy(block->name, "GENERAL INFO");
2481 block->id = TNG_GENERAL_INFO;
2483 if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
2486 fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2487 __FILE__, __LINE__);
2488 tng_block_destroy(&block);
2489 return(TNG_CRITICAL);
2492 first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
2494 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2496 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2498 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2500 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2502 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2504 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2506 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2508 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2511 if(block->block_contents)
2513 free(block->block_contents);
2515 block->block_contents = malloc(block->block_contents_size);
2516 if(!block->block_contents)
2518 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
2519 block->block_contents_size, __FILE__, __LINE__);
2520 tng_block_destroy(&block);
2521 return(TNG_CRITICAL);
2524 strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
2525 offset += first_program_name_len;
2527 strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
2528 offset += last_program_name_len;
2530 strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
2531 offset += first_user_name_len;
2533 strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
2534 offset += last_user_name_len;
2536 strncpy(block->block_contents+offset, tng_data->first_computer_name,
2537 first_computer_name_len);
2538 offset += first_computer_name_len;
2540 strncpy(block->block_contents+offset, tng_data->last_computer_name,
2541 last_computer_name_len);
2542 offset += last_computer_name_len;
2544 strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
2545 first_pgp_signature_len);
2546 offset += first_pgp_signature_len;
2548 strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
2549 last_pgp_signature_len);
2550 offset += last_pgp_signature_len;
2552 strncpy(block->block_contents+offset, tng_data->forcefield_name,
2553 forcefield_name_len);
2554 offset += forcefield_name_len;
2556 memcpy(block->block_contents+offset, &tng_data->time,
2557 sizeof(tng_data->time));
2558 if(tng_data->output_endianness_swap_func_64)
2560 if(tng_data->output_endianness_swap_func_64(tng_data,
2561 (int64_t *)block->header_contents+offset)
2564 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2565 __FILE__, __LINE__);
2568 offset += sizeof(tng_data->time);
2570 memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
2571 sizeof(tng_data->var_num_atoms_flag));
2572 offset += sizeof(tng_data->var_num_atoms_flag);
2574 memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
2575 sizeof(tng_data->frame_set_n_frames));
2576 if(tng_data->output_endianness_swap_func_64)
2578 if(tng_data->output_endianness_swap_func_64(tng_data,
2579 (int64_t *)block->header_contents+offset)
2582 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2583 __FILE__, __LINE__);
2586 offset += sizeof(tng_data->frame_set_n_frames);
2588 memcpy(block->block_contents+offset,
2589 &tng_data->first_trajectory_frame_set_output_file_pos,
2590 sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
2591 if(tng_data->output_endianness_swap_func_64)
2593 if(tng_data->output_endianness_swap_func_64(tng_data,
2594 (int64_t *)block->header_contents+offset)
2597 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2598 __FILE__, __LINE__);
2601 offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
2603 memcpy(block->block_contents+offset,
2604 &tng_data->last_trajectory_frame_set_output_file_pos,
2605 sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
2606 if(tng_data->output_endianness_swap_func_64)
2608 if(tng_data->output_endianness_swap_func_64(tng_data,
2609 (int64_t *)block->header_contents+offset)
2612 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2613 __FILE__, __LINE__);
2616 offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
2618 memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
2619 sizeof(tng_data->medium_stride_length));
2620 if(tng_data->output_endianness_swap_func_64)
2622 if(tng_data->output_endianness_swap_func_64(tng_data,
2623 (int64_t *)block->header_contents+offset)
2626 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2627 __FILE__, __LINE__);
2630 offset += sizeof(tng_data->medium_stride_length);
2632 memcpy(block->block_contents+offset, &tng_data->long_stride_length,
2633 sizeof(tng_data->long_stride_length));
2634 if(tng_data->output_endianness_swap_func_64)
2636 if(tng_data->output_endianness_swap_func_64(tng_data,
2637 (int64_t *)block->header_contents+offset)
2640 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2641 __FILE__, __LINE__);
2644 offset += sizeof(tng_data->long_stride_length);
2646 memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
2647 sizeof(tng_data->distance_unit_exponential));
2648 if(tng_data->output_endianness_swap_func_64)
2650 if(tng_data->output_endianness_swap_func_64(tng_data,
2651 (int64_t *)block->header_contents+offset)
2654 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2655 __FILE__, __LINE__);
2659 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
2661 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2662 tng_data->output_file_path, __FILE__, __LINE__);
2663 tng_block_destroy(&block);
2664 return(TNG_CRITICAL);
2667 if(fwrite(block->block_contents, block->block_contents_size, 1,
2668 tng_data->output_file) != 1)
2670 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
2671 tng_block_destroy(&block);
2672 return(TNG_CRITICAL);
2675 tng_block_destroy(&block);
2677 return(TNG_SUCCESS);
2680 /** Read the chain data of a molecules block.
2681 * @param tng_data is a trajectory data container.
2682 * @param block is a general block container.
2683 * @param chain is the chain data container.
2684 * @param offset is the offset of the block input and is updated when reading.
2685 * @return TNG_SUCCESS(0) is successful.
2687 static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
2688 tng_gen_block_t block,
2694 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2696 memcpy(&chain->id, block->block_contents+*offset,
2698 if(tng_data->input_endianness_swap_func_64)
2700 if(tng_data->input_endianness_swap_func_64(tng_data,
2704 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2705 __FILE__, __LINE__);
2708 *offset += sizeof(chain->id);
2710 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2712 chain->name = malloc(len);
2713 strncpy(chain->name,
2714 block->block_contents+*offset, len);
2717 memcpy(&chain->n_residues, block->block_contents+*offset,
2718 sizeof(chain->n_residues));
2719 if(tng_data->input_endianness_swap_func_64)
2721 if(tng_data->input_endianness_swap_func_64(tng_data,
2725 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2726 __FILE__, __LINE__);
2729 *offset += sizeof(chain->n_residues);
2731 return(TNG_SUCCESS);
2734 /** Write the chain data of a molecules block.
2735 * @param tng_data is a trajectory data container.
2736 * @param block is a general block container.
2737 * @param chain is the chain data container.
2738 * @param offset is the offset of the block output and is updated when writing.
2739 * @return TNG_SUCCESS(0) is successful.
2741 static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
2742 tng_gen_block_t block,
2748 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2750 memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
2751 if(tng_data->output_endianness_swap_func_64)
2753 if(tng_data->output_endianness_swap_func_64(tng_data,
2754 (int64_t *)block->header_contents+*offset)
2757 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2758 __FILE__, __LINE__);
2761 *offset += sizeof(chain->id);
2763 len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2764 strncpy(block->block_contents + *offset, chain->name, len);
2767 memcpy(block->block_contents+*offset, &chain->n_residues,
2768 sizeof(chain->n_residues));
2769 if(tng_data->output_endianness_swap_func_64)
2771 if(tng_data->output_endianness_swap_func_64(tng_data,
2772 (int64_t *)block->header_contents+*offset)
2775 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2776 __FILE__, __LINE__);
2779 *offset += sizeof(chain->n_residues);
2781 return(TNG_SUCCESS);
2784 /** Read the residue data of a molecules block.
2785 * @param tng_data is a trajectory data container.
2786 * @param block is a general block container.
2787 * @param residue is the residue data container.
2788 * @param offset is the offset of the block input and is updated when reading.
2789 * @return TNG_SUCCESS(0) is successful.
2791 static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
2792 tng_gen_block_t block,
2793 tng_residue_t residue,
2798 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2800 memcpy(&residue->id, block->block_contents+*offset,
2801 sizeof(residue->id));
2802 if(tng_data->input_endianness_swap_func_64)
2804 if(tng_data->input_endianness_swap_func_64(tng_data,
2808 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2809 __FILE__, __LINE__);
2812 *offset += sizeof(residue->id);
2814 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2816 residue->name = malloc(len);
2817 strncpy(residue->name,
2818 block->block_contents+*offset, len);
2821 memcpy(&residue->n_atoms, block->block_contents+*offset,
2822 sizeof(residue->n_atoms));
2823 if(tng_data->input_endianness_swap_func_64)
2825 if(tng_data->input_endianness_swap_func_64(tng_data,
2829 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2830 __FILE__, __LINE__);
2833 *offset += sizeof(residue->n_atoms);
2835 return(TNG_SUCCESS);
2838 /** Write the residue data of a molecules block.
2839 * @param tng_data is a trajectory data container.
2840 * @param block is a general block container.
2841 * @param residue is the residue data container.
2842 * @param offset is the offset of the block output and is updated when writing.
2843 * @return TNG_SUCCESS(0) is successful.
2845 static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
2846 tng_gen_block_t block,
2847 tng_residue_t residue,
2852 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2854 memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
2855 if(tng_data->output_endianness_swap_func_64)
2857 if(tng_data->output_endianness_swap_func_64(tng_data,
2858 (int64_t *)block->header_contents+*offset)
2861 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2862 __FILE__, __LINE__);
2865 *offset += sizeof(residue->id);
2867 len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2868 strncpy(block->block_contents + *offset, residue->name, len);
2871 memcpy(block->block_contents+*offset, &residue->n_atoms,
2872 sizeof(residue->n_atoms));
2873 if(tng_data->output_endianness_swap_func_64)
2875 if(tng_data->output_endianness_swap_func_64(tng_data,
2876 (int64_t *)block->header_contents+*offset)
2879 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2880 __FILE__, __LINE__);
2883 *offset += sizeof(residue->n_atoms);
2885 return(TNG_SUCCESS);
2888 /** Read the atom data of a molecules block.
2889 * @param tng_data is a trajectory data container.
2890 * @param block is a general block container.
2891 * @param atom is the atom data container.
2892 * @param offset is the offset of the block input and is updated when reading.
2893 * @return TNG_SUCCESS(0) is successful.
2895 static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
2896 tng_gen_block_t block,
2902 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2904 memcpy(&atom->id, block->block_contents+*offset,
2906 if(tng_data->input_endianness_swap_func_64)
2908 if(tng_data->input_endianness_swap_func_64(tng_data,
2912 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2913 __FILE__, __LINE__);
2916 *offset += sizeof(atom->id);
2918 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2920 atom->name = malloc(len);
2922 block->block_contents+*offset, len);
2925 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2927 atom->atom_type = malloc(len);
2928 strncpy(atom->atom_type,
2929 block->block_contents+*offset, len);
2932 return(TNG_SUCCESS);
2935 /** Write the atom data of a molecules block.
2936 * @param tng_data is a trajectory data container.
2937 * @param block is a general block container.
2938 * @param atom is the atom data container.
2939 * @param offset is the offset of the block output and is updated when writing.
2940 * @return TNG_SUCCESS(0) is successful.
2942 static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
2943 tng_gen_block_t block,
2949 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2951 memcpy(block->block_contents+*offset, &atom->id,
2953 if(tng_data->output_endianness_swap_func_64)
2955 if(tng_data->output_endianness_swap_func_64(tng_data,
2956 (int64_t *)block->header_contents+*offset)
2959 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
2960 __FILE__, __LINE__);
2963 *offset += sizeof(atom->id);
2965 len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2966 strncpy(block->block_contents + *offset, atom->name, len);
2969 len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2970 strncpy(block->block_contents + *offset, atom->atom_type, len);
2973 return(TNG_SUCCESS);
2976 static tng_function_status tng_molecules_block_len_calculate
2977 (const tng_trajectory_t tng_data,
2981 tng_molecule_t molecule;
2983 tng_residue_t residue;
2989 for(i = 0; i < tng_data->n_molecules; i++)
2991 molecule = &tng_data->molecules[i];
2994 molecule->name = malloc(1);
2997 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2998 __FILE__, __LINE__);
2999 return(TNG_CRITICAL);
3001 molecule->name[0] = 0;
3003 *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3005 chain = molecule->chains;
3006 for(j = 0; j < molecule->n_chains; j++)
3008 *len += sizeof(chain->id);
3012 chain->name = malloc(1);
3015 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3016 __FILE__, __LINE__);
3017 return(TNG_CRITICAL);
3021 *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
3023 *len += sizeof(chain->n_residues);
3028 residue = molecule->residues;
3029 for(j = 0; j < molecule->n_residues; j++)
3031 *len += sizeof(residue->id);
3035 residue->name = malloc(1);
3038 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3039 __FILE__, __LINE__);
3040 return(TNG_CRITICAL);
3042 residue->name[0] = 0;
3044 *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
3046 *len += sizeof(residue->n_atoms);
3051 atom = molecule->atoms;
3052 for(j = 0; j < molecule->n_atoms; j++)
3054 *len += sizeof(atom->id);
3057 atom->name = malloc(1);
3060 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3061 __FILE__, __LINE__);
3062 return(TNG_CRITICAL);
3066 *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
3068 if(!atom->atom_type)
3070 atom->atom_type = malloc(1);
3071 if(!atom->atom_type)
3073 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3074 __FILE__, __LINE__);
3075 return(TNG_CRITICAL);
3077 atom->atom_type[0] = 0;
3079 *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
3084 for(j = 0; j < molecule->n_bonds; j++)
3086 *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
3089 *len += sizeof(tng_data->n_molecules) +
3090 (sizeof(molecule->id) +
3091 sizeof(molecule->quaternary_str) +
3092 sizeof(molecule->n_chains) +
3093 sizeof(molecule->n_residues) +
3094 sizeof(molecule->n_atoms) +
3095 sizeof(molecule->n_bonds)) *
3096 tng_data->n_molecules;
3098 if(!tng_data->var_num_atoms_flag)
3100 *len += tng_data->n_molecules * sizeof(int64_t);
3103 return(TNG_SUCCESS);
3106 /** Read a molecules block. Contains chain, residue and atom data
3107 * @param tng_data is a trajectory data container.
3108 * @param block is a general block container.
3109 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3110 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3111 * compared to the md5 hash of the read contents to ensure valid data.
3112 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3113 * error has occured.
3115 static tng_function_status tng_molecules_block_read
3116 (tng_trajectory_t tng_data,
3117 tng_gen_block_t block,
3118 const char hash_mode)
3121 int len, offset = 0;
3122 tng_molecule_t molecule;
3124 tng_residue_t residue;
3129 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3131 return(TNG_CRITICAL);
3134 if(block->block_contents)
3136 free(block->block_contents);
3139 block->block_contents = malloc(block->block_contents_size);
3140 if(!block->block_contents)
3142 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3143 block->block_contents_size, __FILE__, __LINE__);
3144 return(TNG_CRITICAL);
3147 /* Read the whole block into block_contents to be able to write it to disk
3148 * even if it cannot be interpreted. */
3149 if(fread(block->block_contents, block->block_contents_size, 1,
3150 tng_data->input_file) == 0)
3152 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3155 /* FIXME: Does not check if the size of the contents matches the expected
3156 * size or if the contents can be read. */
3158 if(hash_mode == TNG_USE_HASH)
3160 tng_md5_hash_match_verify(block, &same_hash);
3161 if(same_hash != TNG_TRUE)
3163 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3165 __FILE__, __LINE__);
3169 if(tng_data->molecules)
3171 for(i=0; i<tng_data->n_molecules; i++)
3173 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
3175 free(tng_data->molecules);
3176 tng_data->molecules = 0;
3177 tng_data->n_molecules = 0;
3180 memcpy(&tng_data->n_molecules, block->block_contents,
3181 sizeof(tng_data->n_molecules));
3182 if(tng_data->input_endianness_swap_func_64)
3184 if(tng_data->input_endianness_swap_func_64(tng_data,
3185 &tng_data->n_molecules)
3188 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3189 __FILE__, __LINE__);
3192 offset += sizeof(tng_data->n_molecules);
3194 if(tng_data->molecules)
3196 free(tng_data->molecules);
3199 tng_data->n_particles = 0;
3201 tng_data->molecules = malloc(tng_data->n_molecules *
3202 sizeof(struct tng_molecule));
3203 if(!tng_data->molecules)
3205 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3206 tng_data->n_molecules * sizeof(struct tng_molecule),
3207 __FILE__, __LINE__);
3208 return(TNG_CRITICAL);
3211 if(!tng_data->var_num_atoms_flag)
3213 if(tng_data->molecule_cnt_list)
3215 free(tng_data->molecule_cnt_list);
3217 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
3218 tng_data->n_molecules);
3219 if(!tng_data->molecule_cnt_list)
3221 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3222 tng_data->n_molecules * sizeof(struct tng_molecule),
3223 __FILE__, __LINE__);
3224 return(TNG_CRITICAL);
3228 /* Read each molecule from file */
3229 for(i=0; i < tng_data->n_molecules; i++)
3231 molecule = &tng_data->molecules[i];
3233 memcpy(&molecule->id, block->block_contents+offset,
3234 sizeof(molecule->id));
3235 if(tng_data->input_endianness_swap_func_64)
3237 if(tng_data->input_endianness_swap_func_64(tng_data,
3241 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3242 __FILE__, __LINE__);
3245 offset += sizeof(molecule->id);
3247 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
3248 len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
3249 molecule->name = malloc(len);
3250 strncpy(molecule->name, block->block_contents+offset, len);
3253 memcpy(&molecule->quaternary_str, block->block_contents+offset,
3254 sizeof(molecule->quaternary_str));
3255 if(tng_data->input_endianness_swap_func_64)
3257 if(tng_data->input_endianness_swap_func_64(tng_data,
3258 &molecule->quaternary_str)
3261 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3262 __FILE__, __LINE__);
3265 offset += sizeof(molecule->quaternary_str);
3267 if(!tng_data->var_num_atoms_flag)
3269 memcpy(&tng_data->molecule_cnt_list[i],
3270 block->block_contents+offset,
3272 if(tng_data->input_endianness_swap_func_64)
3274 if(tng_data->input_endianness_swap_func_64(tng_data,
3275 &tng_data->molecule_cnt_list[i])
3278 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3279 __FILE__, __LINE__);
3282 offset += sizeof(int64_t);
3286 memcpy(&molecule->n_chains, block->block_contents+offset,
3287 sizeof(molecule->n_chains));
3288 if(tng_data->input_endianness_swap_func_64)
3290 if(tng_data->input_endianness_swap_func_64(tng_data,
3291 &molecule->n_chains)
3294 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3295 __FILE__, __LINE__);
3298 offset += sizeof(molecule->n_chains);
3300 memcpy(&molecule->n_residues, block->block_contents+offset,
3301 sizeof(molecule->n_residues));
3302 if(tng_data->input_endianness_swap_func_64)
3304 if(tng_data->input_endianness_swap_func_64(tng_data,
3305 &molecule->n_residues)
3308 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3309 __FILE__, __LINE__);
3312 offset += sizeof(molecule->n_residues);
3314 memcpy(&molecule->n_atoms, block->block_contents+offset,
3315 sizeof(molecule->n_atoms));
3316 if(tng_data->input_endianness_swap_func_64)
3318 if(tng_data->input_endianness_swap_func_64(tng_data,
3322 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3323 __FILE__, __LINE__);
3326 offset += sizeof(molecule->n_atoms);
3328 tng_data->n_particles += molecule->n_atoms *
3329 tng_data->molecule_cnt_list[i];
3331 if(molecule->n_chains > 0)
3333 molecule->chains = malloc(molecule->n_chains *
3334 sizeof(struct tng_chain));
3335 if(!molecule->chains)
3337 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3338 molecule->n_chains * sizeof(struct tng_chain),
3339 __FILE__, __LINE__);
3340 return(TNG_CRITICAL);
3343 chain = molecule->chains;
3350 if(molecule->n_residues > 0)
3352 molecule->residues = malloc(molecule->n_residues *
3353 sizeof(struct tng_residue));
3354 if(!molecule->residues)
3356 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3357 molecule->n_residues * sizeof(struct tng_residue),
3358 __FILE__, __LINE__);
3359 if(molecule->chains)
3361 free(molecule->chains);
3362 molecule->chains = 0;
3364 return(TNG_CRITICAL);
3367 residue = molecule->residues;
3374 molecule->atoms = malloc(molecule->n_atoms *
3375 sizeof(struct tng_atom));
3376 if(!molecule->atoms)
3378 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3379 molecule->n_atoms * sizeof(struct tng_atom),
3380 __FILE__, __LINE__);
3381 if(molecule->chains)
3383 free(molecule->chains);
3384 molecule->chains = 0;
3386 if(molecule->residues)
3388 free(molecule->residues);
3389 molecule->residues = 0;
3391 return(TNG_CRITICAL);
3394 atom = molecule->atoms;
3396 if(molecule->n_chains > 0)
3398 /* Read the chains of the molecule */
3399 for(j=0; j<molecule->n_chains; j++)
3401 chain->molecule = molecule;
3403 tng_chain_data_read(tng_data, block, chain, &offset);
3405 chain->residues = molecule->residues;
3406 residue = chain->residues;
3408 /* Read the residues of the chain */
3409 for(k=0; k<chain->n_residues; k++)
3411 residue->chain = chain;
3413 tng_residue_data_read(tng_data, block, residue, &offset);
3415 residue->atoms_offset = atom - molecule->atoms;
3416 /* Read the atoms of the residue */
3417 for(l=0; l<residue->n_atoms; l++)
3419 atom->residue = residue;
3421 tng_atom_data_read(tng_data, block, atom, &offset);
3432 if(molecule->n_residues > 0)
3434 for(k=0; k<molecule->n_residues; k++)
3438 tng_residue_data_read(tng_data, block, residue, &offset);
3440 residue->atoms_offset = atom - molecule->atoms;
3441 /* Read the atoms of the residue */
3442 for(l=0; l<residue->n_atoms; l++)
3444 atom->residue = residue;
3446 tng_atom_data_read(tng_data, block, atom, &offset);
3455 for(l=0; l<molecule->n_atoms; l++)
3459 tng_atom_data_read(tng_data, block, atom, &offset);
3466 memcpy(&molecule->n_bonds, block->block_contents+offset,
3467 sizeof(molecule->n_bonds));
3468 if(tng_data->input_endianness_swap_func_64)
3470 if(tng_data->input_endianness_swap_func_64(tng_data,
3474 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3475 __FILE__, __LINE__);
3478 offset += sizeof(molecule->n_bonds);
3480 if(molecule->n_bonds > 0)
3482 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
3483 sizeof(struct tng_bond));
3484 if(!molecule->bonds)
3486 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3487 molecule->n_bonds * sizeof(struct tng_bond),
3488 __FILE__, __LINE__);
3489 if(molecule->chains)
3491 free(molecule->chains);
3492 molecule->chains = 0;
3494 if(molecule->residues)
3496 free(molecule->residues);
3497 molecule->residues = 0;
3501 free(molecule->atoms);
3502 molecule->atoms = 0;
3504 return(TNG_CRITICAL);
3507 bond = molecule->bonds;
3509 for(j=0; j<molecule->n_bonds; j++)
3511 memcpy(&bond->from_atom_id, block->block_contents+offset,
3512 sizeof(bond->from_atom_id));
3513 if(tng_data->input_endianness_swap_func_64)
3515 if(tng_data->input_endianness_swap_func_64(tng_data,
3516 &bond->from_atom_id)
3519 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3520 __FILE__, __LINE__);
3523 offset += sizeof(bond->from_atom_id);
3525 memcpy(&bond->to_atom_id, block->block_contents+offset,
3526 sizeof(bond->to_atom_id));
3527 if(tng_data->input_endianness_swap_func_64)
3529 if(tng_data->input_endianness_swap_func_64(tng_data,
3533 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3534 __FILE__, __LINE__);
3537 offset += sizeof(bond->to_atom_id);
3544 molecule->bonds = 0;
3548 return(TNG_SUCCESS);
3551 /** Write a molecules block.
3552 * @param tng_data is a trajectory data container.
3553 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3554 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3555 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3556 * error has occured.
3558 static tng_function_status tng_molecules_block_write
3559 (tng_trajectory_t tng_data,
3560 const char hash_mode)
3562 int len = 0, name_len, offset = 0;
3564 tng_molecule_t molecule;
3566 tng_residue_t residue;
3569 tng_gen_block_t block;
3571 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3573 return(TNG_CRITICAL);
3576 tng_block_init(&block);
3578 name_len = (int)strlen("MOLECULES");
3580 block->name = malloc(name_len + 1);
3583 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3584 name_len+1, __FILE__, __LINE__);
3585 tng_block_destroy(&block);
3586 return(TNG_CRITICAL);
3589 strcpy(block->name, "MOLECULES");
3590 block->id = TNG_MOLECULES;
3592 if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
3595 fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3596 __FILE__, __LINE__);
3597 tng_block_destroy(&block);
3598 return(TNG_CRITICAL);
3601 block->block_contents = malloc(block->block_contents_size);
3602 if(!block->block_contents)
3604 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3605 block->block_contents_size, __FILE__, __LINE__);
3606 tng_block_destroy(&block);
3607 return(TNG_CRITICAL);
3610 memcpy(block->block_contents+offset, &tng_data->n_molecules,
3611 sizeof(tng_data->n_molecules));
3612 if(tng_data->output_endianness_swap_func_64)
3614 if(tng_data->output_endianness_swap_func_64(tng_data,
3615 (int64_t *)block->header_contents+offset)
3618 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3619 __FILE__, __LINE__);
3622 offset += sizeof(tng_data->n_molecules);
3624 for(i = 0; i < tng_data->n_molecules; i++)
3626 molecule = &tng_data->molecules[i];
3627 memcpy(block->block_contents+offset, &molecule->id,
3628 sizeof(molecule->id));
3629 if(tng_data->output_endianness_swap_func_64)
3631 if(tng_data->output_endianness_swap_func_64(tng_data,
3632 (int64_t *)block->header_contents+offset)
3635 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3636 __FILE__, __LINE__);
3639 offset += sizeof(molecule->id);
3641 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
3642 len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
3643 strncpy(block->block_contents + offset, molecule->name, len);
3646 memcpy(block->block_contents+offset, &molecule->quaternary_str,
3647 sizeof(molecule->quaternary_str));
3648 if(tng_data->output_endianness_swap_func_64)
3650 if(tng_data->output_endianness_swap_func_64(tng_data,
3651 (int64_t *)block->header_contents+offset)
3654 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3655 __FILE__, __LINE__);
3658 offset += sizeof(molecule->quaternary_str);
3660 if(!tng_data->var_num_atoms_flag)
3662 memcpy(block->block_contents+offset,
3663 &tng_data->molecule_cnt_list[i], sizeof(int64_t));
3664 if(tng_data->output_endianness_swap_func_64)
3666 if(tng_data->output_endianness_swap_func_64(tng_data,
3667 (int64_t *)block->header_contents+offset)
3670 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3671 __FILE__, __LINE__);
3674 offset += sizeof(int64_t);
3677 memcpy(block->block_contents+offset, &molecule->n_chains,
3678 sizeof(molecule->n_chains));
3679 if(tng_data->output_endianness_swap_func_64)
3681 if(tng_data->output_endianness_swap_func_64(tng_data,
3682 (int64_t *)block->header_contents+offset)
3685 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3686 __FILE__, __LINE__);
3689 offset += sizeof(molecule->n_chains);
3691 memcpy(block->block_contents+offset, &molecule->n_residues,
3692 sizeof(molecule->n_residues));
3693 if(tng_data->output_endianness_swap_func_64)
3695 if(tng_data->output_endianness_swap_func_64(tng_data,
3696 (int64_t *)block->header_contents+offset)
3699 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3700 __FILE__, __LINE__);
3703 offset += sizeof(molecule->n_residues);
3705 memcpy(block->block_contents+offset, &molecule->n_atoms,
3706 sizeof(molecule->n_atoms));
3707 if(tng_data->output_endianness_swap_func_64)
3709 if(tng_data->output_endianness_swap_func_64(tng_data,
3710 (int64_t *)block->header_contents+offset)
3713 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3714 __FILE__, __LINE__);
3717 offset += sizeof(molecule->n_atoms);
3719 if(molecule->n_chains > 0)
3721 chain = molecule->chains;
3722 for(j = 0; j < molecule->n_chains; j++)
3724 tng_chain_data_write(tng_data, block, chain, &offset);
3726 residue = chain->residues;
3727 for(k = 0; k < chain->n_residues; k++)
3729 tng_residue_data_write(tng_data, block, residue, &offset);
3731 atom = molecule->atoms + residue->atoms_offset;
3732 for(l = 0; l < residue->n_atoms; l++)
3734 tng_atom_data_write(tng_data, block, atom, &offset);
3745 if(molecule->n_residues > 0)
3747 residue = molecule->residues;
3748 for(k = 0; k < molecule->n_residues; k++)
3750 tng_residue_data_write(tng_data, block, residue, &offset);
3752 atom = molecule->atoms + residue->atoms_offset;
3753 for(l = 0; l < residue->n_atoms; l++)
3755 tng_atom_data_write(tng_data, block, atom, &offset);
3764 atom = molecule->atoms;
3765 for(l = 0; l < molecule->n_atoms; l++)
3767 tng_atom_data_write(tng_data, block, atom, &offset);
3774 memcpy(block->block_contents+offset, &molecule->n_bonds,
3775 sizeof(molecule->n_bonds));
3776 if(tng_data->output_endianness_swap_func_64)
3778 if(tng_data->output_endianness_swap_func_64(tng_data,
3779 (int64_t *)block->header_contents+offset)
3782 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3783 __FILE__, __LINE__);
3786 offset += sizeof(molecule->n_bonds);
3788 bond = molecule->bonds;
3789 for(j = 0; j < molecule->n_bonds; j++)
3791 memcpy(block->block_contents+offset, &bond->from_atom_id,
3792 sizeof(bond->from_atom_id));
3793 if(tng_data->output_endianness_swap_func_64)
3795 if(tng_data->output_endianness_swap_func_64(tng_data,
3796 (int64_t *)block->header_contents+offset)
3799 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3800 __FILE__, __LINE__);
3803 offset += sizeof(bond->from_atom_id);
3805 memcpy(block->block_contents+offset, &bond->to_atom_id,
3806 sizeof(bond->to_atom_id));
3807 if(tng_data->output_endianness_swap_func_64)
3809 if(tng_data->output_endianness_swap_func_64(tng_data,
3810 (int64_t *)block->header_contents+offset)
3813 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3814 __FILE__, __LINE__);
3817 offset += sizeof(bond->to_atom_id);
3823 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
3825 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3826 tng_data->output_file_path, __FILE__, __LINE__);
3827 tng_block_destroy(&block);
3828 return(TNG_CRITICAL);
3831 if(fwrite(block->block_contents, block->block_contents_size, 1,
3832 tng_data->output_file) != 1)
3834 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
3835 __FILE__, __LINE__);
3836 tng_block_destroy(&block);
3837 return(TNG_CRITICAL);
3840 tng_block_destroy(&block);
3842 return(TNG_SUCCESS);
3845 static tng_function_status tng_frame_set_block_len_calculate
3846 (const tng_trajectory_t tng_data,
3849 *len = sizeof(int64_t) * 8;
3850 *len += sizeof(double) * 2;
3852 if(tng_data->var_num_atoms_flag)
3854 *len += sizeof(int64_t) * tng_data->n_molecules;
3856 return(TNG_SUCCESS);
3859 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
3860 * @param tng_data is a trajectory data container.
3861 * @param block is a general block container.
3862 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3863 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3864 * compared to the md5 hash of the read contents to ensure valid data.
3865 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3866 * error has occured.
3868 static tng_function_status tng_frame_set_block_read
3869 (tng_trajectory_t tng_data,
3870 tng_gen_block_t block,
3871 const char hash_mode)
3875 int64_t i, prev_n_particles;
3877 tng_trajectory_frame_set_t frame_set =
3878 &tng_data->current_trajectory_frame_set;
3880 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3882 return(TNG_CRITICAL);
3885 if(block->block_contents)
3887 free(block->block_contents);
3890 block->block_contents = malloc(block->block_contents_size);
3891 if(!block->block_contents)
3893 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3894 block->block_contents_size, __FILE__, __LINE__);
3895 return(TNG_CRITICAL);
3898 /* Read the whole block into block_contents to be able to write it to
3899 * disk even if it cannot be interpreted. */
3900 if(fread(block->block_contents, block->block_contents_size, 1,
3901 tng_data->input_file) == 0)
3903 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3904 return(TNG_CRITICAL);
3907 /* FIXME: Does not check if the size of the contents matches the expected
3908 * size or if the contents can be read. */
3910 file_pos = (int64_t)ftell(tng_data->input_file) -
3911 (long)(block->block_contents_size + block->header_contents_size);
3913 if(hash_mode == TNG_USE_HASH)
3915 tng_md5_hash_match_verify(block, &same_hash);
3916 if(same_hash != TNG_TRUE)
3918 fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %ld Hashes do not match. "
3920 file_pos, __FILE__, __LINE__);
3921 /* return(TNG_FAILURE); */
3925 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3927 tng_frame_set_particle_mapping_free(tng_data);
3929 if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
3931 tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
3933 /* FIXME: Should check the frame number instead of the file_pos, in case
3934 * frame sets are not in order */
3935 if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
3937 tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
3940 memcpy(&frame_set->first_frame, block->block_contents,
3941 sizeof(frame_set->first_frame));
3942 if(tng_data->input_endianness_swap_func_64)
3944 if(tng_data->input_endianness_swap_func_64(tng_data,
3945 &frame_set->first_frame)
3948 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3949 __FILE__, __LINE__);
3952 offset += sizeof(frame_set->first_frame);
3954 memcpy(&frame_set->n_frames, block->block_contents + offset,
3955 sizeof(frame_set->n_frames));
3956 if(tng_data->input_endianness_swap_func_64)
3958 if(tng_data->input_endianness_swap_func_64(tng_data,
3959 &frame_set->n_frames)
3962 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3963 __FILE__, __LINE__);
3966 offset += sizeof(frame_set->n_frames);
3968 if(tng_data->var_num_atoms_flag)
3970 prev_n_particles = frame_set->n_particles;
3971 frame_set->n_particles = 0;
3972 /* If the list of molecule counts has already been created assume that
3973 * it is of correct size. */
3974 if(!frame_set->molecule_cnt_list)
3976 frame_set->molecule_cnt_list =
3977 malloc(sizeof(int64_t) * tng_data->n_molecules);
3979 if(!frame_set->molecule_cnt_list)
3981 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3982 sizeof(int64_t) * tng_data->n_molecules,
3983 __FILE__, __LINE__);
3984 return(TNG_CRITICAL);
3987 for(i = 0; i < tng_data->n_molecules; i++)
3989 memcpy(&frame_set->molecule_cnt_list[i],
3990 block->block_contents + offset,
3992 if(tng_data->input_endianness_swap_func_64)
3994 if(tng_data->input_endianness_swap_func_64(tng_data,
3995 &frame_set->molecule_cnt_list[i])
3998 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3999 __FILE__, __LINE__);
4002 offset += sizeof(int64_t);
4003 frame_set->n_particles += tng_data->molecules[i].n_atoms *
4004 frame_set->molecule_cnt_list[i];
4006 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
4008 /* FIXME: Particle dependent data memory management */
4012 memcpy(&frame_set->next_frame_set_file_pos,
4013 block->block_contents + offset,
4014 sizeof(frame_set->next_frame_set_file_pos));
4015 if(tng_data->input_endianness_swap_func_64)
4017 if(tng_data->input_endianness_swap_func_64(tng_data,
4018 &frame_set->next_frame_set_file_pos)
4021 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4022 __FILE__, __LINE__);
4025 offset += sizeof(frame_set->next_frame_set_file_pos);
4027 memcpy(&frame_set->prev_frame_set_file_pos,
4028 block->block_contents + offset,
4029 sizeof(frame_set->prev_frame_set_file_pos));
4030 if(tng_data->input_endianness_swap_func_64)
4032 if(tng_data->input_endianness_swap_func_64(tng_data,
4033 &frame_set->prev_frame_set_file_pos)
4036 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4037 __FILE__, __LINE__);
4040 offset += sizeof(frame_set->prev_frame_set_file_pos);
4042 memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
4043 block->block_contents + offset,
4044 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4045 if(tng_data->input_endianness_swap_func_64)
4047 if(tng_data->input_endianness_swap_func_64(tng_data,
4048 &frame_set->medium_stride_next_frame_set_file_pos)
4051 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4052 __FILE__, __LINE__);
4055 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4057 memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
4058 block->block_contents + offset,
4059 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4060 if(tng_data->input_endianness_swap_func_64)
4062 if(tng_data->input_endianness_swap_func_64(tng_data,
4063 &frame_set->medium_stride_prev_frame_set_file_pos)
4066 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4067 __FILE__, __LINE__);
4070 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4072 memcpy(&frame_set->long_stride_next_frame_set_file_pos,
4073 block->block_contents + offset,
4074 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4075 if(tng_data->input_endianness_swap_func_64)
4077 if(tng_data->input_endianness_swap_func_64(tng_data,
4078 &frame_set->long_stride_next_frame_set_file_pos)
4081 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4082 __FILE__, __LINE__);
4085 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4087 memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
4088 block->block_contents + offset,
4089 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4090 if(tng_data->input_endianness_swap_func_64)
4092 if(tng_data->input_endianness_swap_func_64(tng_data,
4093 &frame_set->long_stride_prev_frame_set_file_pos)
4096 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4097 __FILE__, __LINE__);
4100 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4102 if(block->block_version >= 3)
4104 memcpy(&frame_set->first_frame_time,
4105 block->block_contents + offset,
4106 sizeof(frame_set->first_frame_time));
4107 if(tng_data->input_endianness_swap_func_64)
4109 if(tng_data->input_endianness_swap_func_64(tng_data,
4110 (int64_t *)&frame_set->first_frame_time)
4113 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4114 __FILE__, __LINE__);
4117 offset += sizeof(frame_set->first_frame_time);
4119 memcpy(&tng_data->time_per_frame,
4120 block->block_contents + offset,
4121 sizeof(tng_data->time_per_frame));
4122 if(tng_data->input_endianness_swap_func_64)
4124 if(tng_data->input_endianness_swap_func_64(tng_data,
4125 (int64_t *)&tng_data->time_per_frame)
4128 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4129 __FILE__, __LINE__);
4135 frame_set->first_frame_time = -1;
4136 tng_data->time_per_frame = -1;
4139 /* If the output file and the input files are the same the number of
4140 * frames in the file are the same number as has just been read.
4141 * This is updated here to later on see if there have been new frames
4142 * added and thereby the frame set needs to be rewritten. */
4143 if(tng_data->output_file == tng_data->input_file)
4145 frame_set->n_written_frames = frame_set->n_frames;
4148 return(TNG_SUCCESS);
4151 /** Write tng_data->current_trajectory_frame_set to file
4152 * @param tng_data is a trajectory data container.
4153 * @param block is a general block container.
4154 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4155 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4156 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4157 * error has occured.
4159 static tng_function_status tng_frame_set_block_write
4160 (tng_trajectory_t tng_data,
4161 tng_gen_block_t block,
4162 const char hash_mode)
4167 unsigned int name_len;
4168 tng_trajectory_frame_set_t frame_set =
4169 &tng_data->current_trajectory_frame_set;
4171 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4173 return(TNG_CRITICAL);
4176 name_len = (int)strlen("TRAJECTORY FRAME SET");
4178 if(!block->name || strlen(block->name) < name_len)
4180 temp_name = realloc(block->name, name_len + 1);
4183 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4184 name_len+1, __FILE__, __LINE__);
4187 return(TNG_CRITICAL);
4189 block->name = temp_name;
4191 strcpy(block->name, "TRAJECTORY FRAME SET");
4192 block->id = TNG_TRAJECTORY_FRAME_SET;
4194 if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
4197 fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
4198 __FILE__, __LINE__);
4199 return(TNG_CRITICAL);
4202 if(block->block_contents)
4204 free(block->block_contents);
4206 block->block_contents = malloc(block->block_contents_size);
4207 if(!block->block_contents)
4209 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4210 block->block_contents_size, __FILE__, __LINE__);
4211 return(TNG_CRITICAL);
4214 memcpy(block->block_contents, &frame_set->first_frame,
4215 sizeof(frame_set->first_frame));
4216 if(tng_data->output_endianness_swap_func_64)
4218 if(tng_data->output_endianness_swap_func_64(tng_data,
4219 (int64_t *)block->header_contents+offset)
4222 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4223 __FILE__, __LINE__);
4226 offset += sizeof(frame_set->first_frame);
4228 memcpy(block->block_contents+offset, &frame_set->n_frames,
4229 sizeof(frame_set->n_frames));
4230 if(tng_data->output_endianness_swap_func_64)
4232 if(tng_data->output_endianness_swap_func_64(tng_data,
4233 (int64_t *)block->header_contents+offset)
4236 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4237 __FILE__, __LINE__);
4240 offset += sizeof(frame_set->n_frames);
4242 if(tng_data->var_num_atoms_flag)
4244 for(i = 0; i < tng_data->n_molecules; i++)
4246 memcpy(block->block_contents+offset,
4247 &frame_set->molecule_cnt_list[i],
4249 if(tng_data->output_endianness_swap_func_64)
4251 if(tng_data->output_endianness_swap_func_64(tng_data,
4252 (int64_t *)block->header_contents+offset)
4255 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4256 __FILE__, __LINE__);
4259 offset += sizeof(int64_t);
4264 memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
4265 sizeof(frame_set->next_frame_set_file_pos));
4266 if(tng_data->output_endianness_swap_func_64)
4268 if(tng_data->output_endianness_swap_func_64(tng_data,
4269 (int64_t *)block->header_contents+offset)
4272 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4273 __FILE__, __LINE__);
4276 offset += sizeof(frame_set->next_frame_set_file_pos);
4278 memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
4279 sizeof(frame_set->prev_frame_set_file_pos));
4280 if(tng_data->output_endianness_swap_func_64)
4282 if(tng_data->output_endianness_swap_func_64(tng_data,
4283 (int64_t *)block->header_contents+offset)
4286 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4287 __FILE__, __LINE__);
4290 offset += sizeof(frame_set->prev_frame_set_file_pos);
4292 memcpy(block->block_contents+offset,
4293 &frame_set->medium_stride_next_frame_set_file_pos,
4294 sizeof(frame_set->medium_stride_next_frame_set_file_pos));
4295 if(tng_data->output_endianness_swap_func_64)
4297 if(tng_data->output_endianness_swap_func_64(tng_data,
4298 (int64_t *)block->header_contents+offset)
4301 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4302 __FILE__, __LINE__);
4305 offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
4307 memcpy(block->block_contents+offset,
4308 &frame_set->medium_stride_prev_frame_set_file_pos,
4309 sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
4310 if(tng_data->output_endianness_swap_func_64)
4312 if(tng_data->output_endianness_swap_func_64(tng_data,
4313 (int64_t *)block->header_contents+offset)
4316 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4317 __FILE__, __LINE__);
4320 offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
4322 memcpy(block->block_contents+offset,
4323 &frame_set->long_stride_next_frame_set_file_pos,
4324 sizeof(frame_set->long_stride_next_frame_set_file_pos));
4325 if(tng_data->output_endianness_swap_func_64)
4327 if(tng_data->output_endianness_swap_func_64(tng_data,
4328 (int64_t *)block->header_contents+offset)
4331 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4332 __FILE__, __LINE__);
4335 offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
4337 memcpy(block->block_contents+offset,
4338 &frame_set->long_stride_prev_frame_set_file_pos,
4339 sizeof(frame_set->long_stride_prev_frame_set_file_pos));
4340 if(tng_data->output_endianness_swap_func_64)
4342 if(tng_data->output_endianness_swap_func_64(tng_data,
4343 (int64_t *)block->header_contents+offset)
4346 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4347 __FILE__, __LINE__);
4350 offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
4352 memcpy(block->block_contents+offset,
4353 &frame_set->first_frame_time,
4354 sizeof(frame_set->first_frame_time));
4355 if(tng_data->output_endianness_swap_func_64)
4357 if(tng_data->output_endianness_swap_func_64(tng_data,
4358 (int64_t *)block->header_contents+offset)
4361 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4362 __FILE__, __LINE__);
4365 offset += sizeof(frame_set->first_frame_time);
4367 memcpy(block->block_contents+offset,
4368 &tng_data->time_per_frame,
4369 sizeof(tng_data->time_per_frame));
4370 if(tng_data->output_endianness_swap_func_64)
4372 if(tng_data->output_endianness_swap_func_64(tng_data,
4373 (int64_t *)block->header_contents+offset)
4376 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4377 __FILE__, __LINE__);
4381 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4383 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4384 tng_data->output_file_path, __FILE__, __LINE__);
4385 return(TNG_CRITICAL);
4388 if(fwrite(block->block_contents, block->block_contents_size, 1,
4389 tng_data->output_file) != 1)
4391 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4392 return(TNG_CRITICAL);
4395 return(TNG_SUCCESS);
4398 static tng_function_status tng_trajectory_mapping_block_len_calculate
4399 (const tng_trajectory_t tng_data,
4400 const int64_t n_particles,
4404 *len = sizeof(int64_t) * (2 + n_particles);
4406 return(TNG_SUCCESS);
4409 /** Read an atom mappings block (translating between real atom indexes and how
4410 * the atom info is written in this frame set).
4411 * @param tng_data is a trajectory data container.
4412 * @param block is a general block container.
4413 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4414 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
4415 * compared to the md5 hash of the read contents to ensure valid data.
4416 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4417 * error has occured.
4419 static tng_function_status tng_trajectory_mapping_block_read
4420 (tng_trajectory_t tng_data,
4421 tng_gen_block_t block,
4422 const char hash_mode)
4427 tng_trajectory_frame_set_t frame_set =
4428 &tng_data->current_trajectory_frame_set;
4430 tng_particle_mapping_t mapping, mappings;
4432 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
4434 return(TNG_CRITICAL);
4437 if(block->block_contents)
4439 free(block->block_contents);
4442 block->block_contents = malloc(block->block_contents_size);
4443 if(!block->block_contents)
4445 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4446 block->block_contents_size, __FILE__, __LINE__);
4447 return(TNG_CRITICAL);
4450 /* Read the whole block into block_contents to be able to write it to disk
4451 * even if it cannot be interpreted. */
4452 if(fread(block->block_contents, block->block_contents_size, 1,
4453 tng_data->input_file) == 0)
4455 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
4456 return(TNG_CRITICAL);
4459 /* FIXME: Does not check if the size of the contents matches the expected
4460 * size or if the contents can be read. */
4462 if(hash_mode == TNG_USE_HASH)
4464 tng_md5_hash_match_verify(block, &same_hash);
4465 if(same_hash != TNG_TRUE)
4467 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4469 __FILE__, __LINE__);
4470 /* return(TNG_FAILURE); */
4474 frame_set->n_mapping_blocks++;
4475 mappings = realloc(frame_set->mappings,
4476 sizeof(struct tng_particle_mapping) *
4477 frame_set->n_mapping_blocks);
4480 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4481 block->block_contents_size, __FILE__, __LINE__);
4482 free(frame_set->mappings);
4483 frame_set->mappings = 0;
4484 return(TNG_CRITICAL);
4486 frame_set->mappings = mappings;
4487 mapping = &mappings[frame_set->n_mapping_blocks - 1];
4490 memcpy(&mapping->num_first_particle, block->block_contents+offset,
4491 sizeof(mapping->num_first_particle));
4492 if(tng_data->input_endianness_swap_func_64)
4494 if(tng_data->input_endianness_swap_func_64(tng_data,
4495 &mapping->num_first_particle)
4498 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4499 __FILE__, __LINE__);
4502 offset += sizeof(mapping->num_first_particle);
4504 memcpy(&mapping->n_particles, block->block_contents+offset,
4505 sizeof(mapping->n_particles));
4506 if(tng_data->input_endianness_swap_func_64)
4508 if(tng_data->input_endianness_swap_func_64(tng_data,
4509 &mapping->n_particles)
4512 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4513 __FILE__, __LINE__);
4516 offset += sizeof(mapping->n_particles);
4518 mapping->real_particle_numbers = malloc(mapping->n_particles *
4520 if(!mapping->real_particle_numbers)
4522 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4523 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
4524 return(TNG_CRITICAL);
4527 /* If the byte order needs to be swapped the data must be read one value at
4528 * a time and swapped */
4529 if(tng_data->input_endianness_swap_func_64)
4531 for(i = 0; i < mapping->n_particles; i++)
4533 memcpy(&mapping->real_particle_numbers[i],
4534 block->block_contents + offset,
4536 if(tng_data->input_endianness_swap_func_64(tng_data,
4537 &mapping->real_particle_numbers[i])
4540 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4541 __FILE__, __LINE__);
4543 offset += sizeof(int64_t);
4546 /* Otherwise the data can be read all at once */
4549 memcpy(mapping->real_particle_numbers, block->block_contents + offset,
4550 mapping->n_particles * sizeof(int64_t));
4554 return(TNG_SUCCESS);
4557 /** Write the atom mappings of the current trajectory frame set
4558 * @param tng_data is a trajectory data container.
4559 * @param block is a general block container.
4560 * @param mapping_block_nr is the index of the mapping block to write.
4561 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4562 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4563 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4564 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4566 static tng_function_status tng_trajectory_mapping_block_write
4567 (tng_trajectory_t tng_data,
4568 tng_gen_block_t block,
4569 int mapping_block_nr,
4570 const char hash_mode)
4574 unsigned int name_len;
4575 tng_particle_mapping_t mapping =
4576 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
4578 if(mapping_block_nr >=
4579 tng_data->current_trajectory_frame_set.n_mapping_blocks)
4581 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
4582 __FILE__, __LINE__);
4583 return(TNG_FAILURE);
4586 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4588 return(TNG_CRITICAL);
4591 name_len = (int)strlen("PARTICLE MAPPING");
4593 if(!block->name || strlen(block->name) < name_len)
4595 temp_name = realloc(block->name, name_len + 1);
4598 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4599 name_len+1, __FILE__, __LINE__);
4602 return(TNG_CRITICAL);
4604 block->name = temp_name;
4606 strcpy(block->name, "PARTICLE MAPPING");
4607 block->id = TNG_PARTICLE_MAPPING;
4609 if(tng_trajectory_mapping_block_len_calculate(tng_data,
4610 mapping->n_particles,
4611 &block->block_contents_size) !=
4614 fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4615 __FILE__, __LINE__);
4616 return(TNG_CRITICAL);
4619 if(block->block_contents)
4621 free(block->block_contents);
4623 block->block_contents = malloc(block->block_contents_size);
4624 if(!block->block_contents)
4626 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4627 block->block_contents_size, __FILE__, __LINE__);
4628 return(TNG_CRITICAL);
4631 memcpy(block->block_contents, &mapping->num_first_particle,
4632 sizeof(mapping->num_first_particle));
4633 if(tng_data->output_endianness_swap_func_64)
4635 if(tng_data->output_endianness_swap_func_64(tng_data,
4636 (int64_t *)block->header_contents+offset)
4639 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4640 __FILE__, __LINE__);
4643 offset += sizeof(mapping->num_first_particle);
4645 memcpy(block->block_contents+offset, &mapping->n_particles,
4646 sizeof(mapping->n_particles));
4647 if(tng_data->output_endianness_swap_func_64)
4649 if(tng_data->output_endianness_swap_func_64(tng_data,
4650 (int64_t *)block->header_contents+offset)
4653 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4654 __FILE__, __LINE__);
4657 offset += sizeof(mapping->n_particles);
4659 if(tng_data->output_endianness_swap_func_64)
4661 for(i = 0; i < mapping->n_particles; i++)
4663 memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
4665 if(tng_data->output_endianness_swap_func_64(tng_data,
4666 (int64_t *)block->header_contents+offset)
4669 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4670 __FILE__, __LINE__);
4672 offset += sizeof(int64_t);
4677 memcpy(block->block_contents+offset, mapping->real_particle_numbers,
4678 mapping->n_particles * sizeof(int64_t));
4682 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
4684 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4685 tng_data->output_file_path, __FILE__, __LINE__);
4686 return(TNG_CRITICAL);
4689 if(fwrite(block->block_contents, block->block_contents_size, 1,
4690 tng_data->output_file) != 1)
4692 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
4693 return(TNG_CRITICAL);
4696 return(TNG_SUCCESS);
4699 /** Prepare a block for storing particle data
4700 * @param tng_data is a trajectory data container.
4701 * @param block_type_flag specifies if this is a trajectory block or a
4702 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4703 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4704 * error has occured.
4706 static tng_function_status tng_particle_data_block_create
4707 (tng_trajectory_t tng_data,
4708 const char block_type_flag)
4710 tng_trajectory_frame_set_t frame_set =
4711 &tng_data->current_trajectory_frame_set;
4713 tng_particle_data_t data;
4715 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4717 frame_set->n_particle_data_blocks++;
4718 data = realloc(frame_set->tr_particle_data,
4719 sizeof(struct tng_particle_data) *
4720 frame_set->n_particle_data_blocks);
4723 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4724 sizeof(struct tng_particle_data) *
4725 frame_set->n_particle_data_blocks,
4726 __FILE__, __LINE__);
4727 free(frame_set->tr_particle_data);
4728 frame_set->tr_particle_data = 0;
4729 return(TNG_CRITICAL);
4731 frame_set->tr_particle_data = data;
4735 tng_data->n_particle_data_blocks++;
4736 data = realloc(tng_data->non_tr_particle_data,
4737 sizeof(struct tng_particle_data) *
4738 tng_data->n_particle_data_blocks);
4741 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4742 sizeof(struct tng_particle_data) *
4743 tng_data->n_particle_data_blocks,
4744 __FILE__, __LINE__);
4745 free(tng_data->non_tr_particle_data);
4746 tng_data->non_tr_particle_data = 0;
4747 return(TNG_CRITICAL);
4749 tng_data->non_tr_particle_data = data;
4752 return(TNG_SUCCESS);
4755 static tng_function_status tng_compress(tng_trajectory_t tng_data,
4756 tng_gen_block_t block,
4757 const int64_t n_frames,
4758 const int64_t n_particles,
4765 char *dest, *temp, *temp_data_contents;
4766 int64_t algo_find_n_frames, compressed_len;
4767 unsigned long offset;
4771 if(block->id != TNG_TRAJ_POSITIONS &&
4772 block->id != TNG_TRAJ_VELOCITIES)
4774 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
4775 "TNG method. %s: %d\n", __FILE__, __LINE__);
4776 return(TNG_FAILURE);
4778 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4780 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
4781 return(TNG_FAILURE);
4784 if(n_frames <= 0 || n_particles <= 0)
4786 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
4787 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
4788 return(TNG_FAILURE);
4791 f_precision = 1/(float)tng_data->compression_precision;
4792 d_precision = 1/tng_data->compression_precision;
4794 compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
4795 temp_data_contents = malloc(compressed_len);
4796 if(!temp_data_contents)
4798 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4799 compressed_len, __FILE__, __LINE__);
4800 return(TNG_CRITICAL);
4803 memcpy(temp_data_contents, (char *)start_pos, compressed_len);
4805 if(block->id == TNG_TRAJ_POSITIONS)
4807 /* If there is only one frame in this frame set and there might be more
4808 * do not store the algorithm as the compression algorithm, but find
4809 * the best one without storing it */
4810 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4812 nalgo = tng_compress_nalgo();
4813 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4814 if(type == TNG_FLOAT_DATA)
4816 dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
4825 dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
4832 else if(!tng_data->compress_algo_pos)
4836 algo_find_n_frames = 5;
4840 algo_find_n_frames = n_frames;
4843 nalgo = tng_compress_nalgo();
4844 tng_data->compress_algo_pos=malloc(nalgo *
4845 sizeof *tng_data->compress_algo_pos);
4846 if(type == TNG_FLOAT_DATA)
4848 dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
4849 (int)algo_find_n_frames,
4855 if(algo_find_n_frames < n_frames)
4857 dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
4860 0, tng_data->compress_algo_pos,
4866 dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
4867 (int)algo_find_n_frames,
4873 if(algo_find_n_frames < n_frames)
4875 dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
4878 tng_data->compress_algo_pos,
4885 if(type == TNG_FLOAT_DATA)
4887 dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
4890 tng_data->compress_algo_pos, &new_len);
4894 dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
4897 tng_data->compress_algo_pos,
4902 else if(block->id == TNG_TRAJ_VELOCITIES)
4904 /* If there is only one frame in this frame set and there might be more
4905 * do not store the algorithm as the compression algorithm, but find
4906 * the best one without storing it */
4907 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4909 nalgo = tng_compress_nalgo();
4910 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4911 if(type == TNG_FLOAT_DATA)
4913 dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
4922 dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
4929 else if(!tng_data->compress_algo_vel)
4933 algo_find_n_frames = 5;
4937 algo_find_n_frames = n_frames;
4940 nalgo = tng_compress_nalgo();
4941 tng_data->compress_algo_vel=malloc(nalgo *
4942 sizeof *tng_data->compress_algo_vel);
4944 if(type == TNG_FLOAT_DATA)
4946 dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
4947 (int)algo_find_n_frames,
4952 if(algo_find_n_frames < n_frames)
4954 dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
4957 0, tng_data->compress_algo_vel,
4963 dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
4964 (int)algo_find_n_frames,
4969 if(algo_find_n_frames < n_frames)
4971 dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
4974 0, tng_data->compress_algo_vel,
4981 if(type == TNG_FLOAT_DATA)
4983 dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
4992 dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
5003 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
5004 free(temp_data_contents);
5005 return(TNG_FAILURE);
5008 offset = (unsigned long)((char *)start_pos - block->block_contents);
5015 block->block_contents_size = new_len + offset;
5017 free(temp_data_contents);
5019 temp = realloc(block->block_contents, block->block_contents_size);
5022 free(block->block_contents);
5023 block->block_contents = 0;
5024 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5025 block->block_contents_size, __FILE__, __LINE__);
5026 return(TNG_CRITICAL);
5028 block->block_contents = temp;
5031 memcpy(temp + offset, dest, new_len);
5036 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
5037 return(TNG_FAILURE);
5040 return(TNG_SUCCESS);
5043 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
5044 tng_gen_block_t block,
5047 const unsigned long uncompressed_len)
5049 char *temp, *temp_data_contents;
5052 unsigned long offset;
5056 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
5058 if(block->id != TNG_TRAJ_POSITIONS &&
5059 block->id != TNG_TRAJ_VELOCITIES)
5061 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
5063 return(TNG_FAILURE);
5065 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
5067 fprintf(stderr, "TNG library: Data type not supported.\n");
5068 return(TNG_FAILURE);
5071 temp_data_contents = malloc(uncompressed_len);
5072 if(!temp_data_contents)
5074 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5075 uncompressed_len, __FILE__, __LINE__);
5076 return(TNG_CRITICAL);
5079 memcpy(temp_data_contents, (char *)start_pos, uncompressed_len);
5081 if(type == TNG_FLOAT_DATA)
5083 f_dest = malloc(uncompressed_len);
5086 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5087 uncompressed_len, __FILE__, __LINE__);
5088 free(temp_data_contents);
5089 return(TNG_CRITICAL);
5091 result = tng_compress_uncompress_float(temp_data_contents, f_dest);
5095 d_dest = malloc(uncompressed_len);
5098 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5099 uncompressed_len, __FILE__, __LINE__);
5100 free(temp_data_contents);
5101 return(TNG_CRITICAL);
5103 result = tng_compress_uncompress(temp_data_contents, d_dest);
5108 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
5109 free(temp_data_contents);
5110 return(TNG_FAILURE);
5113 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
5115 block->block_contents_size = (int64_t)(uncompressed_len + offset);
5117 temp = realloc(block->block_contents, uncompressed_len + offset);
5120 free(block->block_contents);
5121 block->block_contents = 0;
5130 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5131 block->block_contents_size, __FILE__, __LINE__);
5132 free(temp_data_contents);
5133 return(TNG_CRITICAL);
5136 if(type == TNG_FLOAT_DATA)
5138 memcpy(temp + offset, f_dest, uncompressed_len);
5142 memcpy(temp + offset, d_dest, uncompressed_len);
5145 block->block_contents = temp;
5147 free(temp_data_contents);
5156 return(TNG_SUCCESS);
5160 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
5161 tng_gen_block_t block,
5162 void *start_pos, const int len)
5166 unsigned long max_len, stat, offset;
5169 max_len = compressBound(len);
5170 dest = malloc(max_len);
5173 fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
5174 max_len, __FILE__, __LINE__);
5175 return(TNG_CRITICAL);
5178 stat = compress(dest, &max_len, start_pos, len);
5179 if(stat != (unsigned long)Z_OK)
5182 if(stat == (unsigned long)Z_MEM_ERROR)
5184 fprintf(stderr, "TNG library: Not enough memory. ");
5186 else if(stat == (unsigned long)Z_BUF_ERROR)
5188 fprintf(stderr, "TNG library: Destination buffer too small. ");
5190 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
5191 return(TNG_FAILURE);
5194 offset = (char *)start_pos - block->block_contents;
5196 block->block_contents_size = max_len + offset;
5198 temp = realloc(block->block_contents, block->block_contents_size);
5201 free(block->block_contents);
5203 block->block_contents = 0;
5204 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5205 block->block_contents_size, __FILE__, __LINE__);
5206 return(TNG_CRITICAL);
5209 block->block_contents = temp;
5211 memcpy(temp + offset, dest, max_len);
5215 return(TNG_SUCCESS);
5218 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5219 tng_gen_block_t block,
5221 unsigned long uncompressed_len)
5229 offset = (char *)start_pos - (char *)block->block_contents;
5231 dest = malloc(uncompressed_len);
5234 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5235 uncompressed_len, __FILE__, __LINE__);
5236 return(TNG_CRITICAL);
5239 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
5240 block->block_contents_size - offset);
5245 if(stat == (unsigned long)Z_MEM_ERROR)
5247 fprintf(stderr, "TNG library: Not enough memory. ");
5249 else if(stat == (unsigned long)Z_BUF_ERROR)
5251 fprintf(stderr, "TNG library: Destination buffer too small. ");
5253 else if(stat == (unsigned long)Z_DATA_ERROR)
5255 fprintf(stderr, "TNG library: Data corrupt. ");
5257 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
5259 return(TNG_FAILURE);
5263 block->block_contents_size = uncompressed_len + offset;
5265 temp = realloc(block->block_contents, uncompressed_len + offset);
5268 free(block->block_contents);
5269 block->block_contents = 0;
5271 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5272 block->block_contents_size, __FILE__, __LINE__);
5273 return(TNG_CRITICAL);
5276 memcpy(temp + offset, dest, uncompressed_len);
5278 block->block_contents = temp;
5281 return(TNG_SUCCESS);
5285 /** Allocate memory for storing particle data.
5286 * The allocated block will be refered to by data->values.
5287 * @param tng_data is a trajectory data container.
5288 * @param data is the data struct, which will contain the allocated memory in
5290 * @param n_frames is the number of frames of data to store.
5291 * @param n_particles is the number of particles with data.
5292 * @param n_values_per_frame is the number of data values per particle and
5294 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5295 * error has occured.
5297 static tng_function_status tng_allocate_particle_data_mem
5298 (tng_trajectory_t tng_data,
5299 tng_particle_data_t data,
5301 int64_t stride_length,
5302 const int64_t n_particles,
5303 const int64_t n_values_per_frame)
5306 int64_t i, j, k, size, frame_alloc;
5309 if(n_particles == 0 || n_values_per_frame == 0)
5311 return(TNG_FAILURE);
5314 if(data->strings && data->datatype == TNG_CHAR_DATA)
5316 for(i = 0; i < data->n_frames; i++)
5318 for(j = 0; j < n_particles; j++)
5320 for(k = 0; k < data->n_values_per_frame; k++)
5322 if(data->strings[i][j][k])
5324 free(data->strings[i][j][k]);
5327 free(data->strings[i][j]);
5329 free(data->strings[i]);
5331 free(data->strings);
5333 data->n_frames = n_frames;
5334 n_frames = tng_max_i64(1, n_frames);
5335 data->stride_length = tng_max_i64(1, stride_length);
5336 data->n_values_per_frame = n_values_per_frame;
5337 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5339 if(data->datatype == TNG_CHAR_DATA)
5341 data->strings = malloc(sizeof(char ***) * frame_alloc);
5342 for(i = 0; i < frame_alloc; i++)
5344 data->strings[i] = malloc(sizeof(char **) *
5346 if(!data->strings[i])
5348 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5349 sizeof(union data_values *) * n_particles,
5350 __FILE__, __LINE__);
5351 return(TNG_CRITICAL);
5353 for(j = 0; j < n_particles; j++)
5355 data->strings[i][j] = malloc(sizeof(char *) *
5356 n_values_per_frame);
5357 if(!data->strings[i][j])
5359 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5360 sizeof(union data_values) * n_values_per_frame,
5361 __FILE__, __LINE__);
5362 return(TNG_CRITICAL);
5364 for(k = 0; k < n_values_per_frame; k++)
5366 data->strings[i][j][k] = 0;
5373 switch(data->datatype)
5376 size = sizeof(int64_t);
5378 case TNG_FLOAT_DATA:
5379 size = sizeof(float);
5381 case TNG_DOUBLE_DATA:
5383 size = sizeof(double);
5386 values = realloc(data->values,
5387 size * frame_alloc *
5388 n_particles * n_values_per_frame);
5391 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5392 size * frame_alloc *
5393 n_particles * n_values_per_frame,
5394 __FILE__, __LINE__);
5397 return(TNG_CRITICAL);
5399 data->values = values;
5401 return(TNG_SUCCESS);
5404 static tng_function_status tng_particle_data_find
5405 (tng_trajectory_t tng_data,
5407 tng_particle_data_t *data)
5409 int64_t block_index, i;
5410 tng_trajectory_frame_set_t frame_set = &tng_data->
5411 current_trajectory_frame_set;
5412 char block_type_flag;
5414 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5415 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5417 block_type_flag = TNG_TRAJECTORY_BLOCK;
5421 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5425 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5427 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
5429 *data = &frame_set->tr_particle_data[i];
5430 if((*data)->block_id == id)
5439 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
5441 *data = &tng_data->non_tr_particle_data[i];
5442 if((*data)->block_id == id)
5449 if(block_index == -1)
5451 return(TNG_FAILURE);
5453 return(TNG_SUCCESS);
5456 static tng_function_status tng_data_find
5457 (tng_trajectory_t tng_data,
5459 tng_non_particle_data_t *data)
5461 int64_t block_index, i;
5462 tng_trajectory_frame_set_t frame_set = &tng_data->
5463 current_trajectory_frame_set;
5464 char block_type_flag;
5466 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5467 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5469 block_type_flag = TNG_TRAJECTORY_BLOCK;
5473 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5477 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5479 for(i = 0; i < frame_set->n_data_blocks; i++)
5481 *data = &frame_set->tr_data[i];
5482 if((*data)->block_id == id)
5488 if(block_index == -1)
5490 for(i = 0; i < tng_data->n_data_blocks; i++)
5492 *data = &tng_data->non_tr_data[i];
5493 if((*data)->block_id == id)
5503 for(i = 0; i < tng_data->n_data_blocks; i++)
5505 *data = &tng_data->non_tr_data[i];
5506 if((*data)->block_id == id)
5513 if(block_index == -1)
5515 return(TNG_FAILURE);
5517 return(TNG_SUCCESS);
5520 static tng_function_status tng_data_block_len_calculate
5521 (const tng_trajectory_t tng_data,
5522 const tng_particle_data_t data,
5523 const tng_bool is_particle_data,
5524 const int64_t n_frames,
5525 const int64_t frame_step,
5526 const int64_t stride_length,
5527 const int64_t num_first_particle,
5528 const int64_t n_particles,
5529 const char dependency,
5530 int64_t *data_start_pos,
5535 char ***first_dim_values, **second_dim_values;
5540 return(TNG_SUCCESS);
5543 switch(data->datatype)
5549 size = sizeof(int64_t);
5551 case TNG_FLOAT_DATA:
5552 size = sizeof(float);
5554 case TNG_DOUBLE_DATA:
5556 size = sizeof(double);
5559 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5560 sizeof(data->codec_id);
5561 if(is_particle_data)
5563 *len += sizeof(num_first_particle) + sizeof(n_particles);
5566 if(stride_length > 1)
5568 *len += sizeof(data->first_frame_with_data) +
5569 sizeof(data->stride_length);
5572 if(data->codec_id != TNG_UNCOMPRESSED)
5574 *len += sizeof(data->compression_multiplier);
5577 if(dependency & TNG_FRAME_DEPENDENT)
5579 *len += sizeof(char);
5582 *data_start_pos = *len;
5584 if(data->datatype == TNG_CHAR_DATA)
5586 if(is_particle_data)
5588 for(i = 0; i < n_frames; i++)
5590 first_dim_values = data->strings[i];
5591 for(j = num_first_particle; j < num_first_particle + n_particles;
5594 second_dim_values = first_dim_values[j];
5595 for(k = 0; k < data->n_values_per_frame; k++)
5597 *len += strlen(second_dim_values[k]) + 1;
5604 for(i = 0; i < n_frames; i++)
5606 second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
5607 for(j = 0; j < data->n_values_per_frame; j++)
5609 *len += strlen(second_dim_values[j]) + 1;
5616 *len += size * frame_step * n_particles * data->n_values_per_frame;
5619 return(TNG_SUCCESS);
5622 /** Read the values of a particle data block
5623 * @param tng_data is a trajectory data container.
5624 * @param block is the block to store the data (should already contain
5625 * the block headers and the block contents).
5626 * @param offset is the reading offset to point at the place where the actual
5627 * values are stored, starting from the beginning of the block_contents. The
5628 * offset is changed during the reading.
5629 * @param datatype is the type of data of the data block (char, int, float or
5631 * @param num_first_particle is the number of the first particle in the data
5632 * block. This should be the same as in the corresponding particle mapping
5634 * @param n_particles is the number of particles in the data block. This should
5635 * be the same as in the corresponding particle mapping block.
5636 * @param first_frame_with_data is the frame number of the first frame with data
5637 * in this data block.
5638 * @param stride_length is the number of frames between each data entry.
5639 * @param n_frames is the number of frames in this data block.
5640 * @param n_values is the number of values per particle and frame stored in this
5642 * @param codec_id is the ID of the codec to compress the data.
5643 * @param multiplier is the multiplication factor applied to each data value
5644 * before compression. This factor is applied since some compression algorithms
5645 * work only on integers.
5646 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5647 * error has occured.
5649 static tng_function_status tng_particle_data_read
5650 (tng_trajectory_t tng_data,
5651 tng_gen_block_t block,
5653 const char datatype,
5654 const int64_t num_first_particle,
5655 const int64_t n_particles,
5656 const int64_t first_frame_with_data,
5657 const int64_t stride_length,
5659 const int64_t n_values,
5660 const int64_t codec_id,
5661 const double multiplier)
5663 int64_t i, j, k, tot_n_particles, n_frames_div;
5665 unsigned long data_size;
5666 char ***first_dim_values, **second_dim_values;
5667 tng_particle_data_t data;
5668 tng_trajectory_frame_set_t frame_set =
5669 &tng_data->current_trajectory_frame_set;
5670 char block_type_flag;
5672 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5680 size = sizeof(int64_t);
5682 case TNG_FLOAT_DATA:
5683 size = sizeof(float);
5685 case TNG_DOUBLE_DATA:
5687 size = sizeof(double);
5690 /* If the block does not exist, create it */
5691 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5693 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5695 block_type_flag = TNG_TRAJECTORY_BLOCK;
5699 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5702 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5705 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5706 __FILE__, __LINE__);
5707 return(TNG_CRITICAL);
5709 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5711 data = &frame_set->tr_particle_data[frame_set->
5712 n_particle_data_blocks - 1];
5716 data = &tng_data->non_tr_particle_data[tng_data->
5717 n_particle_data_blocks - 1];
5719 data->block_id = block->id;
5721 data->block_name = malloc(strlen(block->name) + 1);
5722 if(!data->block_name)
5724 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5725 (int)strlen(block->name)+1, __FILE__, __LINE__);
5726 return(TNG_CRITICAL);
5728 strcpy(data->block_name, block->name);
5730 data->datatype = datatype;
5733 /* FIXME: Memory leak from strings. */
5736 data->codec_id = codec_id;
5737 data->compression_multiplier = multiplier;
5738 data->last_retrieved_frame = -1;
5741 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5742 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5743 tng_data->var_num_atoms_flag)
5745 tot_n_particles = frame_set->n_particles;
5749 tot_n_particles = tng_data->n_particles;
5752 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5754 if(codec_id != TNG_UNCOMPRESSED)
5756 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5759 case TNG_XTC_COMPRESSION:
5760 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5762 case TNG_TNG_COMPRESSION:
5763 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5764 if(tng_uncompress(tng_data, block, datatype,
5765 block->block_contents + *offset,
5766 data_size) != TNG_SUCCESS)
5768 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5769 __FILE__, __LINE__);
5770 return(TNG_CRITICAL);
5772 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5775 case TNG_GZIP_COMPRESSION:
5776 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5777 if(tng_gzip_uncompress(tng_data, block,
5778 block->block_contents + *offset,
5779 data_size) != TNG_SUCCESS)
5781 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5783 return(TNG_CRITICAL);
5785 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5790 /* Allocate memory */
5791 if(!data->values || data->n_frames != n_frames ||
5792 data->n_values_per_frame != n_values)
5794 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5796 tot_n_particles, n_values) !=
5799 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5800 __FILE__, __LINE__);
5801 return(TNG_CRITICAL);
5805 data->first_frame_with_data = first_frame_with_data;
5807 if(datatype == TNG_CHAR_DATA)
5809 for(i = 0; i < n_frames_div; i++)
5811 first_dim_values = data->strings[i];
5812 for(j = num_first_particle; j < num_first_particle + n_particles;
5815 second_dim_values = first_dim_values[j];
5816 for(k = 0; k < n_values; k++)
5818 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5820 if(second_dim_values[k])
5822 free(second_dim_values[k]);
5824 second_dim_values[k] = malloc(len);
5825 if(!second_dim_values[k])
5827 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5828 len, __FILE__, __LINE__);
5829 return(TNG_CRITICAL);
5831 strncpy(second_dim_values[k],
5832 block->block_contents+*offset, len);
5840 memcpy((char *)data->values + n_frames_div * size * n_values *
5842 block->block_contents + *offset,
5843 block->block_contents_size - *offset);
5846 case TNG_FLOAT_DATA:
5847 if(tng_data->input_endianness_swap_func_32)
5849 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5851 if(tng_data->input_endianness_swap_func_32(tng_data,
5852 (int32_t *)((char *)data->values + i))
5855 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5856 __FILE__, __LINE__);
5862 case TNG_DOUBLE_DATA:
5863 if(tng_data->input_endianness_swap_func_64)
5865 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5867 if(tng_data->input_endianness_swap_func_64(tng_data,
5868 (int64_t *)((char *)data->values + i))
5871 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5872 __FILE__, __LINE__);
5881 return(TNG_SUCCESS);
5884 /** Write a particle data block
5885 * @param tng_data is a trajectory data container.
5886 * @param block is the block to store the data (should already contain
5887 * the block headers and the block contents).
5888 * @param block_index is the index number of the data block in the frame set.
5889 * @param mapping is the particle mapping that is relevant for the data block.
5890 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5891 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5892 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5893 * error has occured.
5895 static tng_function_status tng_particle_data_block_write
5896 (tng_trajectory_t tng_data,
5897 tng_gen_block_t block,
5898 const int64_t block_index,
5899 const tng_particle_mapping_t mapping,
5900 const char hash_mode)
5902 int64_t n_particles, num_first_particle, n_frames, stride_length;
5903 int64_t frame_step, data_start_pos;
5906 size_t len, offset = 0;
5907 char dependency, temp, *temp_name;
5909 char ***first_dim_values, **second_dim_values;
5910 tng_trajectory_frame_set_t frame_set;
5911 tng_function_status stat;
5913 tng_particle_data_t data;
5914 char block_type_flag;
5916 frame_set = &tng_data->current_trajectory_frame_set;
5918 /* If we have already started writing frame sets it is too late to write
5919 * non-trajectory data blocks */
5920 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5922 block_type_flag = TNG_TRAJECTORY_BLOCK;
5926 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5929 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5931 return(TNG_CRITICAL);
5934 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5936 data = &frame_set->tr_particle_data[block_index];
5938 /* If this data block has not had any data added in this frame set
5939 * do not write it. */
5940 if(data->first_frame_with_data < frame_set->first_frame)
5942 return(TNG_SUCCESS);
5945 stride_length = tng_max_i64(1, data->stride_length);
5949 data = &tng_data->non_tr_particle_data[block_index];
5953 switch(data->datatype)
5959 size = sizeof(int64_t);
5961 case TNG_FLOAT_DATA:
5962 size = sizeof(float);
5964 case TNG_DOUBLE_DATA:
5966 size = sizeof(double);
5969 len = strlen(data->block_name) + 1;
5971 if(!block->name || strlen(block->name) < len)
5973 temp_name = realloc(block->name, len);
5976 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5977 __FILE__, __LINE__);
5980 return(TNG_CRITICAL);
5982 block->name = temp_name;
5984 strncpy(block->name, data->block_name, len);
5985 block->id = data->block_id;
5987 /* If writing frame independent data data->n_frames is 0, but n_frames
5988 is used for the loop writing the data (and reserving memory) and needs
5990 n_frames = tng_max_i64(1, data->n_frames);
5992 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5994 /* If the frame set is finished before writing the full number of frames
5995 make sure the data block is not longer than the frame set. */
5996 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5998 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6001 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6002 n_frames / stride_length;
6004 /* TNG compression will use compression precision to get integers from
6005 * floating point data. The compression multiplier stores that information
6006 * to be able to return the precision of the compressed data. */
6007 if(data->codec_id == TNG_TNG_COMPRESSION)
6009 data->compression_multiplier = tng_data->compression_precision;
6011 /* Uncompressed data blocks do not use compression multipliers at all.
6012 * GZip compression does not need it either. */
6013 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6015 data->compression_multiplier = 1.0;
6018 if(mapping && mapping->n_particles != 0)
6020 n_particles = mapping->n_particles;
6021 num_first_particle = mapping->num_first_particle;
6025 num_first_particle = 0;
6026 if(tng_data->var_num_atoms_flag)
6028 n_particles = frame_set->n_particles;
6032 n_particles = tng_data->n_particles;
6036 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6038 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6042 dependency = TNG_PARTICLE_DEPENDENT;
6045 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6046 frame_step, stride_length, num_first_particle,
6047 n_particles, dependency, &data_start_pos,
6048 &block->block_contents_size) != TNG_SUCCESS)
6050 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6051 __FILE__, __LINE__);
6052 return(TNG_CRITICAL);
6055 if(block->block_contents)
6057 free(block->block_contents);
6059 block->block_contents = malloc(block->block_contents_size);
6060 if(!block->block_contents)
6062 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6063 block->block_contents_size, __FILE__, __LINE__);
6064 return(TNG_CRITICAL);
6068 memcpy(block->block_contents, &data->datatype, sizeof(char));
6069 offset += sizeof(char);
6071 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6072 offset += sizeof(char);
6074 if(dependency & TNG_FRAME_DEPENDENT)
6076 if(stride_length > 1)
6084 memcpy(block->block_contents+offset, &temp, sizeof(char));
6085 offset += sizeof(char);
6088 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6089 sizeof(data->n_values_per_frame));
6090 if(tng_data->output_endianness_swap_func_64)
6092 if(tng_data->output_endianness_swap_func_64(tng_data,
6093 (int64_t *)block->header_contents+offset)
6096 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6097 __FILE__, __LINE__);
6100 offset += sizeof(data->n_values_per_frame);
6102 memcpy(block->block_contents+offset, &data->codec_id,
6103 sizeof(data->codec_id));
6104 if(tng_data->output_endianness_swap_func_64)
6106 if(tng_data->output_endianness_swap_func_64(tng_data,
6107 (int64_t *)block->header_contents+offset)
6110 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6111 __FILE__, __LINE__);
6114 offset += sizeof(data->codec_id);
6116 if(data->codec_id != TNG_UNCOMPRESSED)
6118 memcpy(block->block_contents+offset, &data->compression_multiplier,
6119 sizeof(data->compression_multiplier));
6120 if(tng_data->output_endianness_swap_func_64)
6122 if(tng_data->output_endianness_swap_func_64(tng_data,
6123 (int64_t *)block->header_contents+offset)
6126 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6127 __FILE__, __LINE__);
6130 offset += sizeof(data->compression_multiplier);
6133 if(data->n_frames > 0 && stride_length > 1)
6135 /* FIXME: first_frame_with_data is not reliably set */
6136 if(data->first_frame_with_data == 0)
6138 data->first_frame_with_data = frame_set->first_frame;
6140 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6141 sizeof(data->first_frame_with_data));
6142 if(tng_data->output_endianness_swap_func_64)
6144 if(tng_data->output_endianness_swap_func_64(tng_data,
6145 (int64_t *)block->header_contents+offset)
6148 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6149 __FILE__, __LINE__);
6152 offset += sizeof(data->first_frame_with_data);
6154 memcpy(block->block_contents+offset, &stride_length,
6155 sizeof(stride_length));
6156 if(tng_data->output_endianness_swap_func_64)
6158 if(tng_data->output_endianness_swap_func_64(tng_data,
6159 (int64_t *)block->header_contents+offset)
6162 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6163 __FILE__, __LINE__);
6166 offset += sizeof(stride_length);
6170 memcpy(block->block_contents+offset, &num_first_particle,
6171 sizeof(num_first_particle));
6172 if(tng_data->output_endianness_swap_func_64)
6174 if(tng_data->output_endianness_swap_func_64(tng_data,
6175 (int64_t *)block->header_contents+offset)
6178 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6179 __FILE__, __LINE__);
6182 offset += sizeof(num_first_particle);
6184 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
6185 if(tng_data->output_endianness_swap_func_64)
6187 if(tng_data->output_endianness_swap_func_64(tng_data,
6188 (int64_t *)block->header_contents+offset)
6191 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6192 __FILE__, __LINE__);
6195 offset += sizeof(n_particles);
6197 if(data->datatype == TNG_CHAR_DATA)
6201 for(i = 0; i < frame_step; i++)
6203 first_dim_values = data->strings[i];
6204 for(j = num_first_particle; j < num_first_particle + n_particles;
6207 second_dim_values = first_dim_values[j];
6208 for(k = 0; k < data->n_values_per_frame; k++)
6210 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6211 strncpy(block->block_contents+offset,
6212 second_dim_values[k], len);
6219 else if(data->values)
6221 memcpy(block->block_contents + offset, data->values,
6222 block->block_contents_size - offset);
6224 switch(data->datatype)
6226 case TNG_FLOAT_DATA:
6227 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6228 data->codec_id == TNG_TNG_COMPRESSION)
6230 if(tng_data->input_endianness_swap_func_32)
6232 for(i = offset; i < block->block_contents_size; i+=size)
6234 if(tng_data->input_endianness_swap_func_32(tng_data,
6235 (int32_t *)(block->block_contents + i))
6238 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6239 __FILE__, __LINE__);
6246 multiplier = data->compression_multiplier;
6247 if(fabs(multiplier - 1.0) > 0.00001 ||
6248 tng_data->input_endianness_swap_func_32)
6250 for(i = offset; i < block->block_contents_size; i+=size)
6252 *(float *)(block->block_contents + i) *= (float)multiplier;
6253 if(tng_data->input_endianness_swap_func_32 &&
6254 tng_data->input_endianness_swap_func_32(tng_data,
6255 (int32_t *)(block->block_contents + i))
6258 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6259 __FILE__, __LINE__);
6266 if(tng_data->input_endianness_swap_func_64)
6268 for(i = offset; i < block->block_contents_size; i+=size)
6270 if(tng_data->input_endianness_swap_func_64(tng_data,
6271 (int64_t *)(block->block_contents + i))
6274 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6275 __FILE__, __LINE__);
6280 case TNG_DOUBLE_DATA:
6281 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6282 data->codec_id == TNG_TNG_COMPRESSION)
6284 if(tng_data->input_endianness_swap_func_64)
6286 for(i = offset; i < block->block_contents_size; i+=size)
6288 if(tng_data->input_endianness_swap_func_64(tng_data,
6289 (int64_t *)(block->block_contents + i))
6292 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6293 __FILE__, __LINE__);
6300 multiplier = data->compression_multiplier;
6301 if(fabs(multiplier - 1.0) > 0.00001 ||
6302 tng_data->input_endianness_swap_func_64)
6304 for(i = offset; i < block->block_contents_size; i+=size)
6306 *(double *)(block->block_contents + i) *= multiplier;
6307 if(tng_data->input_endianness_swap_func_64 &&
6308 tng_data->input_endianness_swap_func_64(tng_data,
6309 (int64_t *)(block->block_contents + i))
6312 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6313 __FILE__, __LINE__);
6325 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6328 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6329 frame_set->n_unwritten_frames = 0;
6331 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6333 switch(data->codec_id)
6335 case TNG_XTC_COMPRESSION:
6336 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6337 data->codec_id = TNG_UNCOMPRESSED;
6339 case TNG_TNG_COMPRESSION:
6340 stat = tng_compress(tng_data, block, frame_step,
6341 n_particles, data->datatype,
6342 block->block_contents + data_start_pos);
6343 if(stat != TNG_SUCCESS)
6345 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6346 __FILE__, __LINE__);
6347 if(stat == TNG_CRITICAL)
6349 return(TNG_CRITICAL);
6351 /* Set the data again, but with no compression (to write only
6352 * the relevant data) */
6353 data->codec_id = TNG_UNCOMPRESSED;
6354 stat = tng_particle_data_block_write(tng_data, block,
6355 block_index, mapping,
6361 case TNG_GZIP_COMPRESSION:
6362 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6363 stat = tng_gzip_compress(tng_data, block,
6364 block->block_contents + data_start_pos,
6365 block->block_contents_size - data_start_pos);
6366 if(stat != TNG_SUCCESS)
6368 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6370 if(stat == TNG_CRITICAL)
6372 return(TNG_CRITICAL);
6374 /* Set the data again, but with no compression (to write only
6375 * the relevant data) */
6376 data->codec_id = TNG_UNCOMPRESSED;
6377 stat = tng_particle_data_block_write(tng_data, block,
6378 block_index, mapping,
6382 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6388 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6390 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6391 tng_data->output_file_path, __FILE__, __LINE__);
6392 return(TNG_CRITICAL);
6395 if(fwrite(block->block_contents, block->block_contents_size, 1,
6396 tng_data->output_file) != 1)
6398 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6400 return(TNG_CRITICAL);
6403 return(TNG_SUCCESS);
6407 /** Create a non-particle data block
6408 * @param tng_data is a trajectory data container.
6409 * @param block_type_flag specifies if this is a trajectory block or a
6410 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6411 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6412 * error has occured.
6414 static tng_function_status tng_data_block_create
6415 (tng_trajectory_t tng_data,
6416 const char block_type_flag)
6418 tng_trajectory_frame_set_t frame_set =
6419 &tng_data->current_trajectory_frame_set;
6421 tng_non_particle_data_t data;
6423 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6425 frame_set->n_data_blocks++;
6426 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6427 frame_set->n_data_blocks);
6430 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6431 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6432 __FILE__, __LINE__);
6433 free(frame_set->tr_data);
6434 frame_set->tr_data = 0;
6435 return(TNG_CRITICAL);
6437 frame_set->tr_data = data;
6441 tng_data->n_data_blocks++;
6442 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6443 tng_data->n_data_blocks);
6446 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6447 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6448 __FILE__, __LINE__);
6449 free(tng_data->non_tr_data);
6450 tng_data->non_tr_data = 0;
6451 return(TNG_CRITICAL);
6453 tng_data->non_tr_data = data;
6456 return(TNG_SUCCESS);
6460 /** Allocate memory for storing non-particle data.
6461 * The allocated block will be refered to by data->values.
6462 * @param tng_data is a trajectory data container.
6463 * @param data is the data struct, which will contain the allocated memory in
6465 * @param n_frames is the number of frames of data to store.
6466 * @param n_values_per_frame is the number of data values per frame.
6467 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6468 * error has occured.
6470 static tng_function_status tng_allocate_data_mem
6471 (tng_trajectory_t tng_data,
6472 tng_non_particle_data_t data,
6474 int64_t stride_length,
6475 const int64_t n_values_per_frame)
6478 int64_t i, j, size, frame_alloc;
6481 if(n_values_per_frame == 0)
6483 return(TNG_FAILURE);
6486 if(data->strings && data->datatype == TNG_CHAR_DATA)
6488 for(i = 0; i < data->n_frames; i++)
6490 for(j = 0; j < data->n_values_per_frame; j++)
6492 if(data->strings[i][j])
6494 free(data->strings[i][j]);
6495 data->strings[i][j] = 0;
6498 free(data->strings[i]);
6499 data->strings[i] = 0;
6501 free(data->strings);
6503 data->n_frames = n_frames;
6504 data->stride_length = tng_max_i64(1, stride_length);
6505 n_frames = tng_max_i64(1, n_frames);
6506 data->n_values_per_frame = n_values_per_frame;
6507 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6509 if(data->datatype == TNG_CHAR_DATA)
6511 data->strings = malloc(sizeof(char **) * frame_alloc);
6512 for(i = 0; i < frame_alloc; i++)
6514 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6515 if(!data->strings[i])
6517 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6519 __FILE__, __LINE__);
6520 return(TNG_CRITICAL);
6522 for(j = 0; j < n_values_per_frame; j++)
6524 data->strings[i][j] = 0;
6530 switch(data->datatype)
6533 size = sizeof(int64_t);
6535 case TNG_FLOAT_DATA:
6536 size = sizeof(float);
6538 case TNG_DOUBLE_DATA:
6540 size = sizeof(double);
6543 values = realloc(data->values,
6544 size * frame_alloc *
6545 n_values_per_frame);
6548 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6549 size * frame_alloc *
6551 __FILE__, __LINE__);
6554 return(TNG_CRITICAL);
6556 data->values = values;
6559 return(TNG_SUCCESS);
6562 /** Read the values of a non-particle data block
6563 * @param tng_data is a trajectory data container.
6564 * @param block is the block to store the data (should already contain
6565 * the block headers and the block contents).
6566 * @param offset is the reading offset to point at the place where the actual
6567 * values are stored, starting from the beginning of the block_contents. The
6568 * offset is changed during the reading.
6569 * @param datatype is the type of data of the data block (char, int, float or
6571 * @param first_frame_with_data is the frame number of the first frame with data
6572 * in this data block.
6573 * @param stride_length is the number of frames between each data entry.
6574 * @param n_frames is the number of frames in this data block.
6575 * @param n_values is the number of values per frame stored in this data block.
6576 * @param codec_id is the ID of the codec to compress the data.
6577 * @param multiplier is the multiplication factor applied to each data value
6578 * before compression. This factor is applied since some compression algorithms
6579 * work only on integers.
6580 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6581 * error has occured.
6583 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6584 tng_gen_block_t block,
6586 const char datatype,
6587 const int64_t first_frame_with_data,
6588 const int64_t stride_length,
6590 const int64_t n_values,
6591 const int64_t codec_id,
6592 const double multiplier)
6594 int64_t i, j, n_frames_div;
6597 unsigned long data_size;
6599 tng_non_particle_data_t data;
6600 tng_trajectory_frame_set_t frame_set =
6601 &tng_data->current_trajectory_frame_set;
6602 char block_type_flag;
6604 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6606 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6614 size = sizeof(int64_t);
6616 case TNG_FLOAT_DATA:
6617 size = sizeof(float);
6619 case TNG_DOUBLE_DATA:
6621 size = sizeof(double);
6624 /* If the block does not exist, create it */
6625 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6627 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6629 block_type_flag = TNG_TRAJECTORY_BLOCK;
6633 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6636 if(tng_data_block_create(tng_data, block_type_flag) !=
6639 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6640 __FILE__, __LINE__);
6641 return(TNG_CRITICAL);
6643 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6645 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6649 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6651 data->block_id = block->id;
6653 data->block_name = malloc(strlen(block->name) + 1);
6654 if(!data->block_name)
6656 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6657 (int)strlen(block->name)+1, __FILE__, __LINE__);
6658 return(TNG_CRITICAL);
6660 strcpy(data->block_name, block->name);
6662 data->datatype = datatype;
6665 /* FIXME: Memory leak from strings. */
6668 data->codec_id = codec_id;
6669 data->compression_multiplier = multiplier;
6670 data->last_retrieved_frame = -1;
6673 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6675 if(codec_id != TNG_UNCOMPRESSED)
6680 case TNG_GZIP_COMPRESSION:
6681 data_size = n_frames_div * size * n_values;
6682 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6683 if(tng_gzip_uncompress(tng_data, block,
6684 block->block_contents + *offset,
6685 data_size) != TNG_SUCCESS)
6687 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6689 return(TNG_CRITICAL);
6691 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6697 /* Allocate memory */
6698 if(!data->values || data->n_frames != n_frames ||
6699 data->n_values_per_frame != n_values)
6701 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6705 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6706 __FILE__, __LINE__);
6707 return(TNG_CRITICAL);
6711 data->first_frame_with_data = first_frame_with_data;
6713 if(datatype == TNG_CHAR_DATA)
6715 for(i = 0; i < n_frames_div; i++)
6717 for(j = 0; j < n_values; j++)
6719 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6721 if(data->strings[i][j])
6723 free(data->strings[i][j]);
6725 data->strings[i][j] = malloc(len);
6726 if(!data->strings[i][j])
6728 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6729 len, __FILE__, __LINE__);
6730 return(TNG_CRITICAL);
6732 strncpy(data->strings[i][j], block->block_contents+*offset,
6740 memcpy(data->values, block->block_contents + *offset,
6741 block->block_contents_size - *offset);
6744 case TNG_FLOAT_DATA:
6745 if(tng_data->input_endianness_swap_func_32)
6747 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6749 if(tng_data->input_endianness_swap_func_32(tng_data,
6750 (int32_t *)((char *)data->values + i))
6753 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6754 __FILE__, __LINE__);
6760 case TNG_DOUBLE_DATA:
6761 if(tng_data->input_endianness_swap_func_64)
6763 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6765 if(tng_data->input_endianness_swap_func_64(tng_data,
6766 (int64_t *)((char *)data->values + i))
6769 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6770 __FILE__, __LINE__);
6779 return(TNG_SUCCESS);
6782 /** Write a non-particle data block
6783 * @param tng_data is a trajectory data container.
6784 * @param block is the block to store the data (should already contain
6785 * the block headers and the block contents).
6786 * @param block_index is the index number of the data block in the frame set.
6787 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6788 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6789 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6790 * error has occured.
6792 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6793 tng_gen_block_t block,
6794 const int64_t block_index,
6795 const char hash_mode)
6797 int64_t n_frames, stride_length, frame_step, data_start_pos;
6799 int offset = 0, size;
6802 tng_function_status stat;
6804 char temp, dependency, *temp_name;
6806 tng_trajectory_frame_set_t frame_set =
6807 &tng_data->current_trajectory_frame_set;
6809 tng_non_particle_data_t data;
6810 char block_type_flag;
6812 /* If we have already started writing frame sets it is too late to write
6813 * non-trajectory data blocks */
6814 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6816 block_type_flag = TNG_TRAJECTORY_BLOCK;
6820 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6823 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6825 return(TNG_CRITICAL);
6828 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6830 data = &frame_set->tr_data[block_index];
6832 /* If this data block has not had any data added in this frame set
6833 * do not write it. */
6834 if(data->first_frame_with_data < frame_set->first_frame)
6836 return(TNG_SUCCESS);
6839 stride_length = tng_max_i64(1, data->stride_length);
6843 data = &tng_data->non_tr_data[block_index];
6847 switch(data->datatype)
6853 size = sizeof(int64_t);
6855 case TNG_FLOAT_DATA:
6856 size = sizeof(float);
6858 case TNG_DOUBLE_DATA:
6860 size = sizeof(double);
6863 len = (unsigned int)strlen(data->block_name) + 1;
6865 if(!block->name || strlen(block->name) < len)
6867 temp_name = realloc(block->name, len);
6870 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6871 __FILE__, __LINE__);
6874 return(TNG_CRITICAL);
6876 block->name = temp_name;
6878 strncpy(block->name, data->block_name, len);
6879 block->id = data->block_id;
6881 /* If writing frame independent data data->n_frames is 0, but n_frames
6882 is used for the loop writing the data (and reserving memory) and needs
6884 n_frames = tng_max_i64(1, data->n_frames);
6886 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6888 /* If the frame set is finished before writing the full number of frames
6889 make sure the data block is not longer than the frame set. */
6890 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6892 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6895 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6896 n_frames / stride_length;
6898 /* TNG compression will use compression precision to get integers from
6899 * floating point data. The compression multiplier stores that information
6900 * to be able to return the precision of the compressed data. */
6901 if(data->codec_id == TNG_TNG_COMPRESSION)
6903 data->compression_multiplier = tng_data->compression_precision;
6905 /* Uncompressed data blocks do not use compression multipliers at all.
6906 * GZip compression does not need it either. */
6907 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6909 data->compression_multiplier = 1.0;
6912 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6914 dependency = TNG_FRAME_DEPENDENT;
6921 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6922 frame_step, stride_length, 0,
6923 1, dependency, &data_start_pos,
6924 &block->block_contents_size) != TNG_SUCCESS)
6926 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6927 __FILE__, __LINE__);
6928 return(TNG_CRITICAL);
6931 if(block->block_contents)
6933 free(block->block_contents);
6935 block->block_contents = malloc(block->block_contents_size);
6936 if(!block->block_contents)
6938 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6939 block->block_contents_size, __FILE__, __LINE__);
6940 return(TNG_CRITICAL);
6944 memcpy(block->block_contents, &data->datatype, sizeof(char));
6945 offset += sizeof(char);
6947 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6948 offset += sizeof(char);
6950 if(dependency & TNG_FRAME_DEPENDENT)
6952 if(stride_length > 1)
6960 memcpy(block->block_contents+offset, &temp, sizeof(char));
6961 offset += sizeof(char);
6964 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6965 sizeof(data->n_values_per_frame));
6966 if(tng_data->output_endianness_swap_func_64)
6968 if(tng_data->output_endianness_swap_func_64(tng_data,
6969 (int64_t *)block->header_contents+offset)
6972 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6973 __FILE__, __LINE__);
6976 offset += sizeof(data->n_values_per_frame);
6978 memcpy(block->block_contents+offset, &data->codec_id,
6979 sizeof(data->codec_id));
6980 if(tng_data->output_endianness_swap_func_64)
6982 if(tng_data->output_endianness_swap_func_64(tng_data,
6983 (int64_t *)block->header_contents+offset)
6986 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6987 __FILE__, __LINE__);
6990 offset += sizeof(data->codec_id);
6992 if(data->codec_id != TNG_UNCOMPRESSED)
6994 memcpy(block->block_contents+offset, &data->compression_multiplier,
6995 sizeof(data->compression_multiplier));
6996 if(tng_data->output_endianness_swap_func_64)
6998 if(tng_data->output_endianness_swap_func_64(tng_data,
6999 (int64_t *)block->header_contents+offset)
7002 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7003 __FILE__, __LINE__);
7006 offset += sizeof(data->compression_multiplier);
7009 if(data->n_frames > 0 && stride_length > 1)
7011 /* FIXME: first_frame_with_data is not reliably set */
7012 if(data->first_frame_with_data == 0)
7014 data->first_frame_with_data = frame_set->first_frame;
7016 memcpy(block->block_contents+offset, &data->first_frame_with_data,
7017 sizeof(data->first_frame_with_data));
7018 if(tng_data->output_endianness_swap_func_64)
7020 if(tng_data->output_endianness_swap_func_64(tng_data,
7021 (int64_t *)block->header_contents+offset)
7024 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7025 __FILE__, __LINE__);
7028 offset += sizeof(data->first_frame_with_data);
7030 memcpy(block->block_contents+offset, &stride_length,
7031 sizeof(data->stride_length));
7032 if(tng_data->output_endianness_swap_func_64)
7034 if(tng_data->output_endianness_swap_func_64(tng_data,
7035 (int64_t *)block->header_contents+offset)
7038 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7039 __FILE__, __LINE__);
7042 offset += sizeof(data->stride_length);
7045 if(data->datatype == TNG_CHAR_DATA)
7049 for(i = 0; i < frame_step; i++)
7051 for(j = 0; j < data->n_values_per_frame; j++)
7053 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7054 strncpy(block->block_contents+offset, data->strings[i][j],
7061 else if(data->values)
7063 memcpy(block->block_contents + offset, data->values,
7064 block->block_contents_size - offset);
7065 switch(data->datatype)
7067 case TNG_FLOAT_DATA:
7068 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7069 data->codec_id == TNG_TNG_COMPRESSION)
7071 if(tng_data->input_endianness_swap_func_32)
7073 for(i = offset; i < block->block_contents_size; i+=size)
7075 if(tng_data->input_endianness_swap_func_32(tng_data,
7076 (int32_t *)(block->block_contents + i))
7079 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7080 __FILE__, __LINE__);
7087 multiplier = data->compression_multiplier;
7088 if(fabs(multiplier - 1.0) > 0.00001 ||
7089 tng_data->input_endianness_swap_func_32)
7091 for(i = offset; block->block_contents_size; i+=size)
7093 *(float *)(block->block_contents + i) *= (float)multiplier;
7094 if(tng_data->input_endianness_swap_func_32 &&
7095 tng_data->input_endianness_swap_func_32(tng_data,
7096 (int32_t *)(block->block_contents + i))
7099 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7100 __FILE__, __LINE__);
7107 if(tng_data->input_endianness_swap_func_64)
7109 for(i = offset; i < block->block_contents_size; i+=size)
7111 if(tng_data->input_endianness_swap_func_64(tng_data,
7112 (int64_t *)(block->block_contents + i))
7115 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7116 __FILE__, __LINE__);
7121 case TNG_DOUBLE_DATA:
7122 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7123 data->codec_id == TNG_TNG_COMPRESSION)
7125 if(tng_data->input_endianness_swap_func_64)
7127 for(i = offset; i < block->block_contents_size; i+=size)
7129 if(tng_data->input_endianness_swap_func_64(tng_data,
7130 (int64_t *)(block->block_contents + i))
7133 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7134 __FILE__, __LINE__);
7141 multiplier = data->compression_multiplier;
7142 if(fabs(multiplier - 1.0) > 0.00001 ||
7143 tng_data->input_endianness_swap_func_64)
7145 for(i = offset; i < block->block_contents_size; i+=size)
7147 *(double *)(block->block_contents + i) *= multiplier;
7148 if(tng_data->input_endianness_swap_func_64 &&
7149 tng_data->input_endianness_swap_func_64(tng_data,
7150 (int64_t *)(block->block_contents + i))
7153 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7154 __FILE__, __LINE__);
7166 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7169 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7170 frame_set->n_unwritten_frames = 0;
7172 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7174 switch(data->codec_id)
7177 case TNG_GZIP_COMPRESSION:
7178 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7179 stat = tng_gzip_compress(tng_data, block,
7180 block->block_contents + data_start_pos,
7181 block->block_contents_size - data_start_pos);
7182 if(stat != TNG_SUCCESS)
7184 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7186 if(stat == TNG_CRITICAL)
7188 return(TNG_CRITICAL);
7190 data->codec_id = TNG_UNCOMPRESSED;
7192 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7198 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7200 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7201 tng_data->output_file_path, __FILE__, __LINE__);
7202 return(TNG_CRITICAL);
7205 if(fwrite(block->block_contents, block->block_contents_size, 1,
7206 tng_data->output_file) != 1)
7208 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7209 __FILE__, __LINE__);
7210 return(TNG_CRITICAL);
7213 return(TNG_SUCCESS);
7216 /** Read the meta information of a data block (particle or non-particle data).
7217 * @param tng_data is a trajectory data container.
7218 * @param block is the block to store the data (should already contain
7219 * the block headers).
7220 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7221 * error has occured.
7223 static tng_function_status tng_data_block_meta_information_read
7224 (tng_trajectory_t tng_data,
7225 tng_gen_block_t block,
7232 int64_t *first_frame_with_data,
7233 int64_t *stride_length,
7235 int64_t *num_first_particle,
7236 int64_t *block_n_particles,
7242 if(block->block_contents)
7244 contents = block->block_contents;
7248 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7249 contents = malloc(meta_size);
7252 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7253 meta_size, __FILE__, __LINE__);
7256 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7258 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7260 return(TNG_CRITICAL);
7264 memcpy(datatype, contents+*offset,
7266 *offset += sizeof(*datatype);
7268 memcpy(dependency, contents+*offset,
7269 sizeof(*dependency));
7270 *offset += sizeof(*dependency);
7272 if(*dependency & TNG_FRAME_DEPENDENT)
7274 memcpy(sparse_data, contents+*offset,
7275 sizeof(*sparse_data));
7276 *offset += sizeof(*sparse_data);
7279 memcpy(n_values, contents+*offset,
7281 if(tng_data->input_endianness_swap_func_64)
7283 if(tng_data->input_endianness_swap_func_64(tng_data,
7287 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7288 __FILE__, __LINE__);
7291 *offset += sizeof(*n_values);
7293 memcpy(codec_id, contents+*offset,
7295 if(tng_data->input_endianness_swap_func_64)
7297 if(tng_data->input_endianness_swap_func_64(tng_data,
7301 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7302 __FILE__, __LINE__);
7305 *offset += sizeof(*codec_id);
7307 if(*codec_id != TNG_UNCOMPRESSED)
7309 memcpy(multiplier, contents+*offset,
7310 sizeof(*multiplier));
7311 if(tng_data->input_endianness_swap_func_64)
7313 if(tng_data->input_endianness_swap_func_64(tng_data,
7314 (int64_t *) multiplier)
7317 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7318 __FILE__, __LINE__);
7321 *offset += sizeof(*multiplier);
7328 if(*dependency & TNG_FRAME_DEPENDENT)
7332 memcpy(first_frame_with_data, contents+*offset,
7333 sizeof(*first_frame_with_data));
7334 if(tng_data->input_endianness_swap_func_64)
7336 if(tng_data->input_endianness_swap_func_64(tng_data,
7337 first_frame_with_data)
7340 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7341 __FILE__, __LINE__);
7344 *offset += sizeof(*first_frame_with_data);
7346 memcpy(stride_length, contents+*offset,
7347 sizeof(*stride_length));
7348 if(tng_data->input_endianness_swap_func_64)
7350 if(tng_data->input_endianness_swap_func_64(tng_data,
7354 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7355 __FILE__, __LINE__);
7358 *offset += sizeof(*stride_length);
7359 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7360 (*first_frame_with_data -
7361 tng_data->current_trajectory_frame_set.first_frame);
7365 *first_frame_with_data = 0;
7367 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7372 *first_frame_with_data = 0;
7377 if (*dependency & TNG_PARTICLE_DEPENDENT)
7379 memcpy(num_first_particle, contents+*offset,
7380 sizeof(*num_first_particle));
7381 if(tng_data->input_endianness_swap_func_64)
7383 if(tng_data->input_endianness_swap_func_64(tng_data,
7387 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7388 __FILE__, __LINE__);
7391 *offset += sizeof(*num_first_particle);
7393 memcpy(block_n_particles, contents+*offset,
7394 sizeof(*block_n_particles));
7395 if(tng_data->input_endianness_swap_func_64)
7397 if(tng_data->input_endianness_swap_func_64(tng_data,
7401 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7402 __FILE__, __LINE__);
7405 *offset += sizeof(*block_n_particles);
7408 if(!block->block_contents)
7412 return(TNG_SUCCESS);
7415 /** Read the contents of a data block (particle or non-particle data).
7416 * @param tng_data is a trajectory data container.
7417 * @param block is the block to store the data (should already contain
7418 * the block headers).
7419 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7420 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7421 * compared to the md5 hash of the read contents to ensure valid data.
7422 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7423 * error has occured.
7425 static tng_function_status tng_data_block_contents_read
7426 (tng_trajectory_t tng_data,
7427 tng_gen_block_t block,
7428 const char hash_mode)
7430 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7431 int64_t stride_length, block_n_particles, num_first_particle;
7433 char datatype, dependency, sparse_data;
7437 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7439 return(TNG_CRITICAL);
7442 if(block->block_contents)
7444 free(block->block_contents);
7447 block->block_contents = malloc(block->block_contents_size);
7448 if(!block->block_contents)
7450 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7451 block->block_contents_size, __FILE__, __LINE__);
7452 return(TNG_CRITICAL);
7455 /* Read the whole block into block_contents to be able to write it to
7456 * disk even if it cannot be interpreted. */
7457 if(fread(block->block_contents, block->block_contents_size, 1,
7458 tng_data->input_file) == 0)
7460 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7461 return(TNG_CRITICAL);
7464 /* FIXME: Does not check if the size of the contents matches the expected
7465 * size or if the contents can be read. */
7467 if(hash_mode == TNG_USE_HASH)
7469 tng_md5_hash_match_verify(block, &same_hash);
7470 if(same_hash != TNG_TRUE)
7472 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7473 block->name, __FILE__, __LINE__);
7474 /* return(TNG_FAILURE); */
7478 if(tng_data_block_meta_information_read(tng_data, block,
7480 &dependency, &sparse_data,
7481 &n_values, &codec_id,
7482 &first_frame_with_data,
7483 &stride_length, &n_frames,
7484 &num_first_particle,
7486 &multiplier) == TNG_CRITICAL)
7488 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7489 block->name, __FILE__, __LINE__);
7490 return(TNG_CRITICAL);
7493 if (dependency & TNG_PARTICLE_DEPENDENT)
7495 return(tng_particle_data_read(tng_data, block,
7499 first_frame_with_data,
7502 codec_id, multiplier));
7506 return(tng_data_read(tng_data, block,
7508 first_frame_with_data,
7511 codec_id, multiplier));
7516 // ** Move the blocks in a frame set so that there is no unused space between
7517 // * them. This can only be done on the last frame set in the file and should
7518 // * be done e.g. if the last frame set in the file has fewer frames than
7519 // * default or after compressing data blocks in a frame set.
7520 // * @param tng_data is a trajectory data container.
7521 // * @details the current_trajectory_frame_set is the one that will be modified.
7522 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7523 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7524 // * FIXME: This function is not finished!!!
7526 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7528 // tng_gen_block_t block;
7529 // tng_trajectory_frame_set_t frame_set;
7530 // FILE *temp = tng_data->input_file;
7531 // int64_t pos, contents_start_pos, output_file_len;
7533 // frame_set = &tng_data->current_trajectory_frame_set;
7535 // if(frame_set->n_written_frames == frame_set->n_frames)
7537 // return(TNG_SUCCESS);
7540 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7541 // tng_data->last_trajectory_frame_set_output_file_pos)
7545 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7547 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7548 // __FILE__, __LINE__);
7549 // return(TNG_CRITICAL);
7552 // tng_block_init(&block);
7553 // // output_file_pos = ftell(tng_data->output_file);
7555 // tng_data->input_file = tng_data->output_file;
7557 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7559 // fseek(tng_data->output_file, pos, SEEK_SET);
7560 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7562 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7563 // __FILE__, __LINE__);
7564 // tng_data->input_file = temp;
7565 // tng_block_destroy(&block);
7566 // return(TNG_CRITICAL);
7569 // contents_start_pos = ftell(tng_data->output_file);
7571 // fseek(tng_data->output_file, 0, SEEK_END);
7572 // output_file_len = ftell(tng_data->output_file);
7573 // pos = contents_start_pos + block->block_contents_size;
7574 // fseek(tng_data->output_file, pos,
7577 // while(pos < output_file_len)
7579 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7581 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7582 // __FILE__, __LINE__);
7583 // tng_data->input_file = temp;
7584 // tng_block_destroy(&block);
7585 // return(TNG_CRITICAL);
7587 // pos += block->header_contents_size + block->block_contents_size;
7588 // fseek(tng_data->output_file, pos, SEEK_SET);
7591 // return(TNG_SUCCESS);
7594 /** Finish writing the current frame set. Update the number of frames
7595 * and the hashes of the frame set and all its data blocks (if hash_mode
7597 * @param tng_data is a trajectory data container.
7598 * @param hash_mode specifies whether to update the block md5 hash when
7599 * updating the pointers.
7600 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7601 * error has occured.
7603 static tng_function_status tng_frame_set_finalize
7604 (tng_trajectory_t tng_data, const char hash_mode)
7606 tng_gen_block_t block;
7607 tng_trajectory_frame_set_t frame_set;
7608 FILE *temp = tng_data->input_file;
7609 int64_t pos, contents_start_pos, output_file_len;
7611 frame_set = &tng_data->current_trajectory_frame_set;
7613 if(frame_set->n_written_frames == frame_set->n_frames)
7615 return(TNG_SUCCESS);
7618 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7620 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7621 __FILE__, __LINE__);
7622 return(TNG_CRITICAL);
7625 tng_block_init(&block);
7626 /* output_file_pos = ftell(tng_data->output_file); */
7628 tng_data->input_file = tng_data->output_file;
7630 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7632 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7634 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7636 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7637 __FILE__, __LINE__);
7638 tng_data->input_file = temp;
7639 tng_block_destroy(&block);
7640 return(TNG_CRITICAL);
7643 contents_start_pos = ftell(tng_data->output_file);
7645 fseek(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7646 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7647 1, tng_data->output_file) != 1)
7649 tng_data->input_file = temp;
7650 tng_block_destroy(&block);
7651 return(TNG_CRITICAL);
7655 if(hash_mode == TNG_USE_HASH)
7657 tng_md5_hash_update(tng_data, block, pos,
7658 pos + block->header_contents_size);
7661 fseek(tng_data->output_file, 0, SEEK_END);
7662 output_file_len = ftell(tng_data->output_file);
7663 pos = contents_start_pos + block->block_contents_size;
7664 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7666 while(pos < output_file_len)
7668 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7670 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7671 __FILE__, __LINE__);
7672 tng_data->input_file = temp;
7673 tng_block_destroy(&block);
7674 return(TNG_CRITICAL);
7677 if(hash_mode == TNG_USE_HASH)
7679 tng_md5_hash_update(tng_data, block, pos,
7680 pos + block->header_contents_size);
7682 pos += block->header_contents_size + block->block_contents_size;
7683 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7686 tng_data->input_file = temp;
7687 tng_block_destroy(&block);
7688 return(TNG_SUCCESS);
7692 // ** Sets the name of a file contents block
7693 // * @param tng_data is a trajectory data container.
7694 // * @param block is the block, of which to change names.
7695 // * @param new_name is the new name of the block.
7696 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7697 // * error has occured.
7699 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7700 // tng_gen_block_t block,
7701 // const char *new_name)
7705 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7707 // * If the currently stored string length is not enough to store the new
7708 // * string it is freed and reallocated. *
7709 // if(block->name && strlen(block->name) < len)
7711 // free(block->name);
7716 // block->name = malloc(len);
7719 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7720 // __FILE__, __LINE__);
7721 // return(TNG_CRITICAL);
7725 // strncpy(block->name, new_name, len);
7727 // return(TNG_SUCCESS);
7731 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7732 const tng_atom_t atom,
7733 tng_residue_t *residue)
7737 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7739 *residue = atom->residue;
7741 return(TNG_SUCCESS);
7744 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7745 const tng_atom_t atom,
7750 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7751 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7753 strncpy(name, atom->name, max_len - 1);
7754 name[max_len - 1] = 0;
7756 if(strlen(atom->name) > (unsigned int)max_len - 1)
7758 return(TNG_FAILURE);
7760 return(TNG_SUCCESS);
7763 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7765 const char *new_name)
7770 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7771 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7773 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7775 /* If the currently stored string length is not enough to store the new
7776 * string it is freed and reallocated. */
7777 if(atom->name && strlen(atom->name) < len)
7784 atom->name = malloc(len);
7787 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7788 __FILE__, __LINE__);
7789 return(TNG_CRITICAL);
7793 strncpy(atom->name, new_name, len);
7795 return(TNG_SUCCESS);
7798 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7799 const tng_atom_t atom,
7804 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7805 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7807 strncpy(type, atom->atom_type, max_len - 1);
7808 type[max_len - 1] = 0;
7810 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7812 return(TNG_FAILURE);
7814 return(TNG_SUCCESS);
7817 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7819 const char *new_type)
7824 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7825 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7827 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7829 /* If the currently stored string length is not enough to store the new
7830 * string it is freed and reallocated. */
7831 if(atom->atom_type && strlen(atom->atom_type) < len)
7833 free(atom->atom_type);
7834 atom->atom_type = 0;
7836 if(!atom->atom_type)
7838 atom->atom_type = malloc(len);
7839 if(!atom->atom_type)
7841 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7842 __FILE__, __LINE__);
7843 return(TNG_CRITICAL);
7847 strncpy(atom->atom_type, new_type, len);
7849 return(TNG_SUCCESS);
7852 /** Initialise an atom struct
7853 * @param atom is the atom to initialise.
7854 * @return TNG_SUCCESS (0) if successful.
7856 static tng_function_status tng_atom_init(tng_atom_t atom)
7859 atom->atom_type = 0;
7861 return(TNG_SUCCESS);
7864 /** Free the memory in an atom struct
7865 * @param atom is the atom to destroy.
7866 * @return TNG_SUCCESS (0) if successful.
7868 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7877 free(atom->atom_type);
7878 atom->atom_type = 0;
7881 return(TNG_SUCCESS);
7884 tng_function_status DECLSPECDLLEXPORT tng_version_major
7885 (const tng_trajectory_t tng_data,
7890 *version = TNG_VERSION_MAJOR;
7892 return(TNG_SUCCESS);
7895 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7896 (const tng_trajectory_t tng_data,
7901 *version = TNG_VERSION_MINOR;
7903 return(TNG_SUCCESS);
7906 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7907 (const tng_trajectory_t tng_data,
7912 *patch_level = TNG_VERSION_PATCHLEVEL;
7914 return(TNG_SUCCESS);
7917 tng_function_status DECLSPECDLLEXPORT tng_version
7918 (const tng_trajectory_t tng_data,
7923 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
7925 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
7927 return(TNG_SUCCESS);
7930 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7931 (tng_trajectory_t tng_data,
7933 tng_molecule_t *molecule)
7937 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7938 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7940 /* Set ID to the ID of the last molecule + 1 */
7941 if(tng_data->n_molecules)
7943 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7950 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7953 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7954 (tng_trajectory_t tng_data,
7957 tng_molecule_t *molecule)
7959 tng_molecule_t new_molecules;
7960 int64_t *new_molecule_cnt_list;
7961 tng_function_status stat = TNG_SUCCESS;
7963 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7964 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7966 new_molecules = realloc(tng_data->molecules,
7967 sizeof(struct tng_molecule) *
7968 (tng_data->n_molecules + 1));
7972 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7973 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7974 __FILE__, __LINE__);
7975 free(tng_data->molecules);
7976 tng_data->molecules = 0;
7977 return(TNG_CRITICAL);
7980 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7982 (tng_data->n_molecules + 1));
7984 if(!new_molecule_cnt_list)
7986 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7987 sizeof(int64_t) * (tng_data->n_molecules + 1),
7988 __FILE__, __LINE__);
7989 free(tng_data->molecule_cnt_list);
7990 tng_data->molecule_cnt_list = 0;
7991 free(new_molecules);
7992 return(TNG_CRITICAL);
7995 tng_data->molecules = new_molecules;
7996 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7998 *molecule = &new_molecules[tng_data->n_molecules];
8000 tng_molecule_init(tng_data, *molecule);
8001 tng_molecule_name_set(tng_data, *molecule, name);
8003 /* FIXME: Should this be a function argument instead? */
8004 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8006 (*molecule)->id = id;
8008 tng_data->n_molecules++;
8013 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
8014 (tng_trajectory_t tng_data,
8015 tng_molecule_t *molecule_p)
8017 int64_t *new_molecule_cnt_list, id;
8018 tng_molecule_t new_molecules, molecule;
8020 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8022 /* Set ID to the ID of the last molecule + 1 */
8023 if(tng_data->n_molecules)
8025 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
8032 new_molecules = realloc(tng_data->molecules,
8033 sizeof(struct tng_molecule) *
8034 (tng_data->n_molecules + 1));
8038 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8039 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
8040 __FILE__, __LINE__);
8041 free(tng_data->molecules);
8042 tng_data->molecules = 0;
8043 return(TNG_CRITICAL);
8046 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
8048 (tng_data->n_molecules + 1));
8050 if(!new_molecule_cnt_list)
8052 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8053 sizeof(int64_t) * (tng_data->n_molecules + 1),
8054 __FILE__, __LINE__);
8055 free(tng_data->molecule_cnt_list);
8056 tng_data->molecule_cnt_list = 0;
8057 free(new_molecules);
8058 return(TNG_CRITICAL);
8061 molecule = *molecule_p;
8063 tng_data->molecules = new_molecules;
8064 tng_data->molecule_cnt_list = new_molecule_cnt_list;
8066 new_molecules[tng_data->n_molecules] = *molecule;
8068 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
8072 molecule = &new_molecules[tng_data->n_molecules];
8074 *molecule_p = molecule;
8078 tng_data->n_molecules++;
8080 return(TNG_SUCCESS);
8083 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8084 const tng_molecule_t molecule,
8089 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8090 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8092 strncpy(name, molecule->name, max_len - 1);
8093 name[max_len - 1] = 0;
8095 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8097 return(TNG_FAILURE);
8099 return(TNG_SUCCESS);
8102 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8103 (tng_trajectory_t tng_data,
8104 tng_molecule_t molecule,
8105 const char *new_name)
8110 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8111 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8113 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8115 /* If the currently stored string length is not enough to store the new
8116 * string it is freed and reallocated. */
8117 if(molecule->name && strlen(molecule->name) < len)
8119 free(molecule->name);
8124 molecule->name = malloc(len);
8127 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8128 __FILE__, __LINE__);
8129 return(TNG_CRITICAL);
8133 strncpy(molecule->name, new_name, len);
8135 return(TNG_SUCCESS);
8138 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8139 (const tng_trajectory_t tng_data,
8140 const tng_molecule_t molecule,
8143 int64_t i, index = -1;
8145 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8146 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8148 for(i = 0; i < tng_data->n_molecules; i++)
8150 if(&tng_data->molecules[i] == molecule)
8158 return(TNG_FAILURE);
8160 *cnt = tng_data->molecule_cnt_list[index];
8162 return(TNG_SUCCESS);
8165 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8166 (tng_trajectory_t tng_data,
8167 tng_molecule_t molecule,
8170 int64_t i, old_cnt, index = -1;
8172 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8174 for(i = 0; i < tng_data->n_molecules; i++)
8176 if(&tng_data->molecules[i] == molecule)
8184 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8185 __FILE__, __LINE__);
8186 return(TNG_FAILURE);
8188 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8190 old_cnt = tng_data->molecule_cnt_list[index];
8191 tng_data->molecule_cnt_list[index] = cnt;
8193 tng_data->n_particles += (cnt-old_cnt) *
8194 tng_data->molecules[index].n_atoms;
8198 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8199 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8201 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8202 tng_data->molecules[index].n_atoms;
8205 return(TNG_SUCCESS);
8208 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8209 (tng_trajectory_t tng_data,
8212 tng_molecule_t *molecule)
8214 int64_t i, n_molecules;
8216 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8217 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8218 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8220 n_molecules = tng_data->n_molecules;
8222 for(i = n_molecules - 1; i >= 0; i--)
8224 *molecule = &tng_data->molecules[i];
8225 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8227 if(nr == -1 || nr == (*molecule)->id)
8229 return(TNG_SUCCESS);
8236 return(TNG_FAILURE);
8239 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8240 (tng_trajectory_t tng_data,
8242 tng_molecule_t *molecule)
8244 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8245 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8247 if(index >= tng_data->n_molecules)
8250 return(TNG_FAILURE);
8252 *molecule = &tng_data->molecules[index];
8253 return(TNG_SUCCESS);
8256 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8257 tng_trajectory_t tng_data_dest)
8259 tng_molecule_t molecule, molecule_temp;
8260 tng_chain_t chain, chain_temp;
8261 tng_residue_t residue, residue_temp;
8262 tng_atom_t atom, atom_temp;
8263 tng_bond_t bond_temp;
8264 tng_function_status stat;
8265 int64_t i, j, k, l, *list_temp;
8267 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8268 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8270 for(i = 0; i < tng_data_dest->n_molecules; i++)
8272 molecule = &tng_data_dest->molecules[i];
8273 tng_molecule_destroy(tng_data_dest, molecule);
8276 tng_data_dest->n_molecules = 0;
8277 tng_data_dest->n_particles = 0;
8279 molecule_temp = realloc(tng_data_dest->molecules,
8280 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8283 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8284 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8285 __FILE__, __LINE__);
8286 free(tng_data_dest->molecules);
8287 tng_data_dest->molecules = 0;
8288 return(TNG_CRITICAL);
8290 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8291 sizeof(int64_t) * tng_data_src->n_molecules);
8294 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8295 sizeof(int64_t) * tng_data_src->n_molecules,
8296 __FILE__, __LINE__);
8297 free(tng_data_dest->molecule_cnt_list);
8298 tng_data_dest->molecule_cnt_list = 0;
8299 free(molecule_temp);
8300 return(TNG_CRITICAL);
8303 tng_data_dest->molecules = molecule_temp;
8304 tng_data_dest->molecule_cnt_list = list_temp;
8306 for(i = 0; i < tng_data_src->n_molecules; i++)
8308 molecule = &tng_data_src->molecules[i];
8309 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8311 if(stat != TNG_SUCCESS)
8313 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8314 __FILE__, __LINE__);
8317 molecule_temp->quaternary_str = molecule->quaternary_str;
8318 for(j = 0; j < molecule->n_chains; j++)
8320 chain = &molecule->chains[j];
8321 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8322 chain->name, chain->id,
8324 if(stat != TNG_SUCCESS)
8326 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8327 __FILE__, __LINE__);
8330 for(k = 0; k < chain->n_residues; k++)
8332 residue = &chain->residues[k];
8333 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8334 residue->name, residue->id,
8336 if(stat != TNG_SUCCESS)
8338 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8339 __FILE__, __LINE__);
8342 for(l = 0; l < residue->n_atoms; l++)
8344 atom = &molecule->atoms[residue->atoms_offset + l];
8345 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8346 atom->name, atom->atom_type,
8347 atom->id, &atom_temp);
8348 if(stat != TNG_SUCCESS)
8350 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8351 __FILE__, __LINE__);
8357 molecule_temp->n_bonds = molecule->n_bonds;
8358 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8362 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8363 sizeof(struct tng_bond) * molecule->n_bonds,
8364 __FILE__, __LINE__);
8365 free(molecule_temp->bonds);
8366 molecule_temp->n_bonds = 0;
8367 return(TNG_CRITICAL);
8369 molecule_temp->bonds = bond_temp;
8370 for(j = 0; j < molecule->n_bonds; j++)
8372 molecule_temp->bonds[j] = molecule->bonds[j];
8374 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8375 tng_data_src->molecule_cnt_list[i]);
8376 if(stat != TNG_SUCCESS)
8378 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8379 __FILE__, __LINE__);
8383 return(TNG_SUCCESS);
8386 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8387 (const tng_trajectory_t tng_data,
8388 const tng_molecule_t molecule,
8392 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8393 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8395 *n = molecule->n_chains;
8397 return(TNG_SUCCESS);
8400 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8401 (tng_trajectory_t tng_data,
8402 tng_molecule_t molecule,
8407 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8408 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8410 if(index >= molecule->n_chains)
8413 return(TNG_FAILURE);
8415 *chain = &molecule->chains[index];
8416 return(TNG_SUCCESS);
8419 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8420 (const tng_trajectory_t tng_data,
8421 const tng_molecule_t molecule,
8425 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8426 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8428 *n = molecule->n_residues;
8430 return(TNG_SUCCESS);
8433 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8434 (const tng_trajectory_t tng_data,
8435 const tng_molecule_t molecule,
8436 const int64_t index,
8437 tng_residue_t *residue)
8440 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8441 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8443 if(index >= molecule->n_residues)
8446 return(TNG_FAILURE);
8448 *residue = &molecule->residues[index];
8449 return(TNG_SUCCESS);
8452 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8453 (const tng_trajectory_t tng_data,
8454 const tng_molecule_t molecule,
8458 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8459 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8461 *n = molecule->n_atoms;
8463 return(TNG_SUCCESS);
8466 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8467 (const tng_trajectory_t tng_data,
8468 const tng_molecule_t molecule,
8469 const int64_t index,
8473 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8474 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8476 if(index >= molecule->n_atoms)
8479 return(TNG_FAILURE);
8481 *atom = &molecule->atoms[index];
8482 return(TNG_SUCCESS);
8485 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8486 (tng_trajectory_t tng_data,
8487 tng_molecule_t molecule,
8492 int64_t i, n_chains;
8495 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8496 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8498 n_chains = molecule->n_chains;
8500 for(i = n_chains - 1; i >= 0; i--)
8502 *chain = &molecule->chains[i];
8503 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8505 if(nr == -1 || nr == (*chain)->id)
8507 return(TNG_SUCCESS);
8514 return(TNG_FAILURE);
8517 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8518 (tng_trajectory_t tng_data,
8519 tng_molecule_t molecule,
8525 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8526 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8528 /* Set ID to the ID of the last chain + 1 */
8529 if(molecule->n_chains)
8531 id = molecule->chains[molecule->n_chains-1].id + 1;
8538 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8542 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8543 (tng_trajectory_t tng_data,
8544 tng_molecule_t molecule,
8549 tng_chain_t new_chains;
8550 tng_function_status stat = TNG_SUCCESS;
8552 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8553 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8555 new_chains = realloc(molecule->chains,
8556 sizeof(struct tng_chain) *
8557 (molecule->n_chains + 1));
8561 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8562 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8563 __FILE__, __LINE__);
8564 free(molecule->chains);
8565 molecule->chains = 0;
8566 return(TNG_CRITICAL);
8569 molecule->chains = new_chains;
8571 *chain = &new_chains[molecule->n_chains];
8574 tng_chain_name_set(tng_data, *chain, name);
8576 (*chain)->molecule = molecule;
8577 (*chain)->n_residues = 0;
8579 molecule->n_chains++;
8586 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8587 (const tng_trajectory_t tng_data,
8588 tng_molecule_t molecule,
8589 const int64_t from_atom_id,
8590 const int64_t to_atom_id,
8593 tng_bond_t new_bonds;
8596 new_bonds = realloc(molecule->bonds,
8597 sizeof(struct tng_bond) *
8598 (molecule->n_bonds + 1));
8602 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8603 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8604 __FILE__, __LINE__);
8606 free(molecule->bonds);
8607 molecule->bonds = 0;
8608 return(TNG_CRITICAL);
8611 molecule->bonds = new_bonds;
8613 *bond = &new_bonds[molecule->n_bonds];
8615 (*bond)->from_atom_id = from_atom_id;
8616 (*bond)->to_atom_id = to_atom_id;
8618 molecule->n_bonds++;
8620 return(TNG_SUCCESS);
8623 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8624 (tng_trajectory_t tng_data,
8625 tng_molecule_t molecule,
8633 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8635 n_atoms = molecule->n_atoms;
8637 for(i = n_atoms - 1; i >= 0; i--)
8639 *atom = &molecule->atoms[i];
8640 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8642 if(id == -1 || id == (*atom)->id)
8644 return(TNG_SUCCESS);
8651 return(TNG_FAILURE);
8654 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8655 const tng_chain_t chain,
8660 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8661 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8663 strncpy(name, chain->name, max_len - 1);
8664 name[max_len - 1] = 0;
8666 if(strlen(chain->name) > (unsigned int)max_len - 1)
8668 return(TNG_FAILURE);
8670 return(TNG_SUCCESS);
8673 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8674 (tng_trajectory_t tng_data,
8676 const char *new_name)
8681 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8683 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8685 /* If the currently stored string length is not enough to store the new
8686 * string it is freed and reallocated. */
8687 if(chain->name && strlen(chain->name) < len)
8694 chain->name = malloc(len);
8697 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8698 __FILE__, __LINE__);
8699 return(TNG_CRITICAL);
8703 strncpy(chain->name, new_name, len);
8705 return(TNG_SUCCESS);
8708 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8709 (const tng_trajectory_t tng_data,
8710 const tng_chain_t chain,
8714 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8715 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8717 *n = chain->n_residues;
8719 return(TNG_SUCCESS);
8722 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8723 (const tng_trajectory_t tng_data,
8724 const tng_chain_t chain,
8725 const int64_t index,
8726 tng_residue_t *residue)
8729 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8730 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8732 if(index >= chain->n_residues)
8735 return(TNG_FAILURE);
8737 *residue = &chain->residues[index];
8738 return(TNG_SUCCESS);
8741 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8742 (tng_trajectory_t tng_data,
8746 tng_residue_t *residue)
8748 int64_t i, n_residues;
8751 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8753 n_residues = chain->n_residues;
8755 for(i = n_residues - 1; i >= 0; i--)
8757 *residue = &chain->residues[i];
8758 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8760 if(id == -1 || id == (*residue)->id)
8762 return(TNG_SUCCESS);
8769 return(TNG_FAILURE);
8772 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8773 (tng_trajectory_t tng_data,
8776 tng_residue_t *residue)
8780 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8781 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8783 /* Set ID to the ID of the last residue + 1 */
8784 if(chain->n_residues)
8786 id = chain->residues[chain->n_residues-1].id + 1;
8793 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8797 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8798 (tng_trajectory_t tng_data,
8802 tng_residue_t *residue)
8805 tng_residue_t new_residues, temp_residue, last_residue;
8806 tng_molecule_t molecule = chain->molecule;
8807 tng_function_status stat = TNG_SUCCESS;
8809 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8810 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8812 if(chain->n_residues)
8814 curr_index = chain->residues - molecule->residues;
8821 new_residues = realloc(molecule->residues,
8822 sizeof(struct tng_residue) *
8823 (molecule->n_residues + 1));
8827 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8828 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8829 __FILE__, __LINE__);
8830 free(molecule->residues);
8831 molecule->residues = 0;
8832 return(TNG_CRITICAL);
8835 molecule->residues = new_residues;
8837 if(curr_index != -1)
8839 chain->residues = new_residues + curr_index;
8840 if(molecule->n_residues)
8842 last_residue = &new_residues[molecule->n_residues - 1];
8844 temp_residue = chain->residues + (chain->n_residues - 1);
8845 /* Make space in list of residues to add the new residues together with the other
8846 * residues of this chain */
8847 if(temp_residue != last_residue)
8850 memmove(temp_residue + 1, temp_residue,
8851 last_residue - temp_residue);
8857 curr_index = molecule->n_residues;
8860 *residue = &molecule->residues[curr_index + chain->n_residues];
8862 if(!chain->n_residues)
8864 chain->residues = *residue;
8868 chain->residues = &molecule->residues[curr_index];
8871 (*residue)->name = 0;
8872 tng_residue_name_set(tng_data, *residue, name);
8874 (*residue)->chain = chain;
8875 (*residue)->n_atoms = 0;
8876 (*residue)->atoms_offset = 0;
8878 chain->n_residues++;
8879 molecule->n_residues++;
8881 (*residue)->id = id;
8886 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8887 const tng_residue_t residue,
8892 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8893 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8895 strncpy(name, residue->name, max_len - 1);
8896 name[max_len - 1] = 0;
8898 if(strlen(residue->name) > (unsigned int)max_len - 1)
8900 return(TNG_FAILURE);
8902 return(TNG_SUCCESS);
8905 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8906 tng_residue_t residue,
8907 const char *new_name)
8912 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8913 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8915 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8917 /* If the currently stored string length is not enough to store the new
8918 * string it is freed and reallocated. */
8919 if(residue->name && strlen(residue->name) < len)
8921 free(residue->name);
8926 residue->name = malloc(len);
8929 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8930 __FILE__, __LINE__);
8931 return(TNG_CRITICAL);
8935 strncpy(residue->name, new_name, len);
8937 return(TNG_SUCCESS);
8940 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8941 (const tng_trajectory_t tng_data,
8942 const tng_residue_t residue,
8946 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8947 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8949 *n = residue->n_atoms;
8951 return(TNG_SUCCESS);
8954 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8955 (const tng_trajectory_t tng_data,
8956 const tng_residue_t residue,
8957 const int64_t index,
8961 tng_molecule_t molecule;
8964 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8965 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8967 if(index >= residue->n_atoms)
8970 return(TNG_FAILURE);
8972 chain = residue->chain;
8973 molecule = chain->molecule;
8975 if(index + residue->atoms_offset >= molecule->n_atoms)
8978 return(TNG_FAILURE);
8981 *atom = &molecule->atoms[residue->atoms_offset + index];
8982 return(TNG_SUCCESS);
8985 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8986 (tng_trajectory_t tng_data,
8987 tng_residue_t residue,
8988 const char *atom_name,
8989 const char *atom_type,
8994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8995 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8996 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8998 /* Set ID to the ID of the last atom + 1 */
8999 if(residue->chain->molecule->n_atoms)
9001 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
9008 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
9012 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
9013 (tng_trajectory_t tng_data,
9014 tng_residue_t residue,
9015 const char *atom_name,
9016 const char *atom_type,
9020 tng_atom_t new_atoms;
9021 tng_molecule_t molecule = residue->chain->molecule;
9022 tng_function_status stat = TNG_SUCCESS;
9024 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9025 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
9026 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
9028 if(!residue->n_atoms)
9030 residue->atoms_offset = molecule->n_atoms;
9033 new_atoms = realloc(molecule->atoms,
9034 sizeof(struct tng_atom) *
9035 (molecule->n_atoms + 1));
9039 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9040 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
9041 __FILE__, __LINE__);
9042 free(molecule->atoms);
9043 molecule->atoms = 0;
9044 return(TNG_CRITICAL);
9047 molecule->atoms = new_atoms;
9049 *atom = &new_atoms[molecule->n_atoms];
9051 tng_atom_init(*atom);
9052 tng_atom_name_set(tng_data, *atom, atom_name);
9053 tng_atom_type_set(tng_data, *atom, atom_type);
9055 (*atom)->residue = residue;
9058 molecule->n_atoms++;
9065 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
9066 tng_molecule_t *molecule_p)
9068 *molecule_p = malloc(sizeof(struct tng_molecule));
9071 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9072 sizeof(struct tng_molecule), __FILE__, __LINE__);
9073 return(TNG_CRITICAL);
9076 tng_molecule_init(tng_data, *molecule_p);
9078 return(TNG_SUCCESS);
9081 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9082 tng_molecule_t *molecule_p)
9086 return(TNG_SUCCESS);
9089 tng_molecule_destroy(tng_data, *molecule_p);
9094 return(TNG_SUCCESS);
9097 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9098 tng_molecule_t molecule)
9101 molecule->quaternary_str = 1;
9103 molecule->n_chains = 0;
9104 molecule->chains = 0;
9105 molecule->n_residues = 0;
9106 molecule->residues = 0;
9107 molecule->n_atoms = 0;
9108 molecule->atoms = 0;
9109 molecule->n_bonds = 0;
9110 molecule->bonds = 0;
9112 return(TNG_SUCCESS);
9115 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9116 tng_molecule_t molecule)
9123 free(molecule->name);
9127 if(molecule->chains)
9129 for(i = 0; i < molecule->n_chains; i++)
9131 if(molecule->chains[i].name)
9133 free(molecule->chains[i].name);
9134 molecule->chains[i].name = 0;
9137 free(molecule->chains);
9138 molecule->chains = 0;
9140 molecule->n_chains = 0;
9142 if(molecule->residues)
9144 for(i = 0; i < molecule->n_residues; i++)
9146 if(molecule->residues[i].name)
9148 free(molecule->residues[i].name);
9149 molecule->residues[i].name = 0;
9152 free(molecule->residues);
9153 molecule->residues = 0;
9155 molecule->n_residues = 0;
9159 for(i = 0; i < molecule->n_atoms; i++)
9161 tng_atom_destroy(&molecule->atoms[i]);
9163 free(molecule->atoms);
9164 molecule->atoms = 0;
9166 molecule->n_atoms = 0;
9170 free(molecule->bonds);
9171 molecule->bonds = 0;
9173 molecule->n_bonds = 0;
9175 return(TNG_SUCCESS);
9178 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9179 (const tng_trajectory_t tng_data,
9184 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9186 tng_bool found = TNG_FALSE;
9188 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9189 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9191 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9193 if(!molecule_cnt_list)
9195 return(TNG_FAILURE);
9198 for(i = 0; i < tng_data->n_molecules; i++)
9200 mol = &tng_data->molecules[i];
9201 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9203 cnt += mol->n_atoms * molecule_cnt_list[i];
9211 return(TNG_FAILURE);
9214 strncpy(name, mol->name, max_len - 1);
9215 name[max_len - 1] = 0;
9217 if(strlen(mol->name) > (unsigned int)max_len - 1)
9219 return(TNG_FAILURE);
9221 return(TNG_SUCCESS);
9224 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9225 (const tng_trajectory_t tng_data,
9229 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9231 tng_bool found = TNG_FALSE;
9233 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9234 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9236 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9238 if(!molecule_cnt_list)
9240 return(TNG_FAILURE);
9243 for(i = 0; i < tng_data->n_molecules; i++)
9245 mol = &tng_data->molecules[i];
9246 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9248 cnt += mol->n_atoms * molecule_cnt_list[i];
9256 return(TNG_FAILURE);
9261 return(TNG_SUCCESS);
9264 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9265 (const tng_trajectory_t tng_data,
9267 int64_t **from_atoms,
9270 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9271 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9275 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9276 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9277 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9278 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9280 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9282 if(!molecule_cnt_list)
9284 return(TNG_FAILURE);
9288 /* First count the total number of bonds to allocate memory */
9289 for(i = 0; i < tng_data->n_molecules; i++)
9291 mol = &tng_data->molecules[i];
9292 mol_cnt = molecule_cnt_list[i];
9293 *n_bonds += mol_cnt * mol->n_bonds;
9297 return(TNG_SUCCESS);
9300 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9303 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9304 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9305 return(TNG_CRITICAL);
9307 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9310 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9311 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9314 return(TNG_CRITICAL);
9318 for(i = 0; i < tng_data->n_molecules; i++)
9320 mol = &tng_data->molecules[i];
9321 mol_cnt = molecule_cnt_list[i];
9322 for(j = 0; j < mol_cnt; j++)
9324 for(k = 0; k < mol->n_bonds; k++)
9326 bond = &mol->bonds[k];
9327 from_atom = atom_cnt + bond->from_atom_id;
9328 to_atom = atom_cnt + bond->to_atom_id;
9329 (*from_atoms)[cnt] = from_atom;
9330 (*to_atoms)[cnt++] = to_atom;
9332 atom_cnt += mol->n_atoms;
9336 return(TNG_SUCCESS);
9339 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9340 (const tng_trajectory_t tng_data,
9345 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9348 tng_bool found = TNG_FALSE;
9350 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9351 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9353 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9355 if(!molecule_cnt_list)
9357 return(TNG_FAILURE);
9360 for(i = 0; i < tng_data->n_molecules; i++)
9362 mol = &tng_data->molecules[i];
9363 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9365 cnt += mol->n_atoms * molecule_cnt_list[i];
9368 atom = &mol->atoms[nr % mol->n_atoms];
9374 return(TNG_FAILURE);
9376 if(!atom->residue || !atom->residue->chain)
9378 return(TNG_FAILURE);
9381 strncpy(name, atom->residue->chain->name, max_len - 1);
9382 name[max_len - 1] = 0;
9384 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9386 return(TNG_FAILURE);
9388 return(TNG_SUCCESS);
9391 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9392 (const tng_trajectory_t tng_data,
9397 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9400 tng_bool found = TNG_FALSE;
9402 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9403 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9405 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9407 if(!molecule_cnt_list)
9409 return(TNG_FAILURE);
9412 for(i = 0; i < tng_data->n_molecules; i++)
9414 mol = &tng_data->molecules[i];
9415 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9417 cnt += mol->n_atoms * molecule_cnt_list[i];
9420 atom = &mol->atoms[nr % mol->n_atoms];
9426 return(TNG_FAILURE);
9430 return(TNG_FAILURE);
9433 strncpy(name, atom->residue->name, max_len - 1);
9434 name[max_len - 1] = 0;
9436 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9438 return(TNG_FAILURE);
9440 return(TNG_SUCCESS);
9443 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9444 (const tng_trajectory_t tng_data,
9448 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9451 tng_bool found = TNG_FALSE;
9453 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9454 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9456 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9458 if(!molecule_cnt_list)
9460 return(TNG_FAILURE);
9463 for(i = 0; i < tng_data->n_molecules; i++)
9465 mol = &tng_data->molecules[i];
9466 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9468 cnt += mol->n_atoms * molecule_cnt_list[i];
9471 atom = &mol->atoms[nr % mol->n_atoms];
9477 return(TNG_FAILURE);
9481 return(TNG_FAILURE);
9484 *id = atom->residue->id;
9486 return(TNG_SUCCESS);
9489 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9490 (const tng_trajectory_t tng_data,
9494 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9497 tng_bool found = TNG_FALSE;
9499 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9500 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9502 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9504 if(!molecule_cnt_list)
9506 return(TNG_FAILURE);
9509 for(i = 0; i < tng_data->n_molecules; i++)
9511 mol = &tng_data->molecules[i];
9512 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9514 cnt += mol->n_atoms * molecule_cnt_list[i];
9515 offset += mol->n_residues * molecule_cnt_list[i];
9518 atom = &mol->atoms[nr % mol->n_atoms];
9524 return(TNG_FAILURE);
9528 return(TNG_FAILURE);
9531 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9533 *id = atom->residue->id + offset;
9535 return(TNG_SUCCESS);
9538 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9539 (const tng_trajectory_t tng_data,
9544 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9547 tng_bool found = TNG_FALSE;
9549 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9550 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9552 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9554 if(!molecule_cnt_list)
9556 return(TNG_FAILURE);
9559 for(i = 0; i < tng_data->n_molecules; i++)
9561 mol = &tng_data->molecules[i];
9562 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9564 cnt += mol->n_atoms * molecule_cnt_list[i];
9567 atom = &mol->atoms[nr % mol->n_atoms];
9573 return(TNG_FAILURE);
9576 strncpy(name, atom->name, max_len - 1);
9577 name[max_len - 1] = 0;
9579 if(strlen(atom->name) > (unsigned int)max_len - 1)
9581 return(TNG_FAILURE);
9583 return(TNG_SUCCESS);
9586 tng_function_status tng_atom_type_of_particle_nr_get
9587 (const tng_trajectory_t tng_data,
9592 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9595 tng_bool found = TNG_FALSE;
9597 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9598 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9600 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9602 if(!molecule_cnt_list)
9604 return(TNG_FAILURE);
9607 for(i = 0; i < tng_data->n_molecules; i++)
9609 mol = &tng_data->molecules[i];
9610 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9612 cnt += mol->n_atoms * molecule_cnt_list[i];
9615 atom = &mol->atoms[nr % mol->n_atoms];
9621 return(TNG_FAILURE);
9624 strncpy(type, atom->atom_type, max_len - 1);
9625 type[max_len - 1] = 0;
9627 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9629 return(TNG_FAILURE);
9631 return(TNG_SUCCESS);
9634 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9635 (tng_trajectory_t tng_data,
9636 const int64_t num_first_particle,
9637 const int64_t n_particles,
9638 const int64_t *mapping_table)
9641 tng_particle_mapping_t mapping;
9642 tng_trajectory_frame_set_t frame_set;
9644 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9646 frame_set = &tng_data->current_trajectory_frame_set;
9648 /* Sanity check of the particle ranges. Split into multiple if
9649 * statements for improved readability */
9650 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9652 mapping = &frame_set->mappings[i];
9653 if(num_first_particle >= mapping->num_first_particle &&
9654 num_first_particle < mapping->num_first_particle +
9655 mapping->n_particles)
9657 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9658 return(TNG_FAILURE);
9660 if(num_first_particle + n_particles >=
9661 mapping->num_first_particle &&
9662 num_first_particle + n_particles <
9663 mapping->num_first_particle + mapping->n_particles)
9665 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9666 return(TNG_FAILURE);
9668 if(mapping->num_first_particle >= num_first_particle &&
9669 mapping->num_first_particle < num_first_particle +
9672 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9673 return(TNG_FAILURE);
9675 if(mapping->num_first_particle + mapping->n_particles >
9676 num_first_particle &&
9677 mapping->num_first_particle + mapping->n_particles <
9678 num_first_particle + n_particles)
9680 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9681 return(TNG_FAILURE);
9685 frame_set->n_mapping_blocks++;
9687 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9688 frame_set->n_mapping_blocks);
9692 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9693 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9694 __FILE__, __LINE__);
9695 free(frame_set->mappings);
9696 frame_set->mappings = 0;
9697 return(TNG_CRITICAL);
9699 frame_set->mappings = mapping;
9701 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9702 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9704 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9705 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9707 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9708 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9709 return(TNG_CRITICAL);
9712 for(i=0; i<n_particles; i++)
9714 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9717 return(TNG_SUCCESS);
9720 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9722 tng_trajectory_frame_set_t frame_set;
9723 tng_particle_mapping_t mapping;
9726 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9728 frame_set = &tng_data->current_trajectory_frame_set;
9730 if(frame_set->n_mapping_blocks && frame_set->mappings)
9732 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9734 mapping = &frame_set->mappings[i];
9735 if(mapping->real_particle_numbers)
9737 free(mapping->real_particle_numbers);
9738 mapping->real_particle_numbers = 0;
9741 free(frame_set->mappings);
9742 frame_set->mappings = 0;
9743 frame_set->n_mapping_blocks = 0;
9746 return(TNG_SUCCESS);
9749 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9752 tng_trajectory_frame_set_t frame_set;
9753 tng_trajectory_t tng_data;
9755 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9758 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9759 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9760 return(TNG_CRITICAL);
9763 tng_data = *tng_data_p;
9765 frame_set = &tng_data->current_trajectory_frame_set;
9767 tng_data->input_file_path = 0;
9768 tng_data->input_file = 0;
9769 tng_data->input_file_len = 0;
9770 tng_data->output_file_path = 0;
9771 tng_data->output_file = 0;
9773 tng_data->first_program_name = 0;
9774 tng_data->first_user_name = 0;
9775 tng_data->first_computer_name = 0;
9776 tng_data->first_pgp_signature = 0;
9777 tng_data->last_program_name = 0;
9778 tng_data->last_user_name = 0;
9779 tng_data->last_computer_name = 0;
9780 tng_data->last_pgp_signature = 0;
9781 tng_data->forcefield_name = 0;
9786 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9790 tng_data->time = seconds;
9793 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9794 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9795 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9796 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9797 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9798 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9799 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9800 tng_data->frame_set_n_frames = 100;
9801 tng_data->n_trajectory_frame_sets = 0;
9802 tng_data->medium_stride_length = 100;
9803 tng_data->long_stride_length = 10000;
9805 tng_data->time_per_frame = -1;
9807 tng_data->n_particle_data_blocks = 0;
9808 tng_data->n_data_blocks = 0;
9810 tng_data->non_tr_particle_data = 0;
9811 tng_data->non_tr_data = 0;
9813 tng_data->compress_algo_pos = 0;
9814 tng_data->compress_algo_vel = 0;
9815 tng_data->compression_precision = 1000;
9816 tng_data->distance_unit_exponential = -9;
9818 frame_set->first_frame = -1;
9819 frame_set->n_mapping_blocks = 0;
9820 frame_set->mappings = 0;
9821 frame_set->molecule_cnt_list = 0;
9823 frame_set->n_particle_data_blocks = 0;
9824 frame_set->n_data_blocks = 0;
9826 frame_set->tr_particle_data = 0;
9827 frame_set->tr_data = 0;
9829 frame_set->n_written_frames = 0;
9830 frame_set->n_unwritten_frames = 0;
9832 frame_set->next_frame_set_file_pos = -1;
9833 frame_set->prev_frame_set_file_pos = -1;
9834 frame_set->medium_stride_next_frame_set_file_pos = -1;
9835 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9836 frame_set->long_stride_next_frame_set_file_pos = -1;
9837 frame_set->long_stride_prev_frame_set_file_pos = -1;
9839 frame_set->first_frame_time = -1;
9841 tng_data->n_molecules = 0;
9842 tng_data->molecules = 0;
9843 tng_data->molecule_cnt_list = 0;
9844 tng_data->n_particles = 0;
9847 /* Check the endianness of the computer */
9848 static int32_t endianness_32 = 0x01234567;
9850 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9852 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9856 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9858 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9863 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9865 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9869 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9870 /* 0x0123456789ABCDEF */
9871 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9873 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9876 /* 0xEFCDAB8967452301 */
9877 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9879 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9882 /* 0x89ABCDEF01234567 */
9883 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9885 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9888 /* 0x45670123CDEF89AB */
9889 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9891 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9894 /* 0x23016745AB89EFCD */
9895 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9897 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9901 /* By default do not swap the byte order, i.e. keep the byte order of the
9902 * architecture. The input file endianness will be set when reading the
9903 * header. The output endianness can be changed - before the file is
9905 tng_data->input_endianness_swap_func_32 = 0;
9906 tng_data->input_endianness_swap_func_64 = 0;
9907 tng_data->output_endianness_swap_func_32 = 0;
9908 tng_data->output_endianness_swap_func_64 = 0;
9910 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9911 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9912 tng_data->current_trajectory_frame_set.n_frames = 0;
9914 return(TNG_SUCCESS);
9917 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9920 int64_t n_particles, n_values_per_frame;
9921 tng_trajectory_t tng_data = *tng_data_p;
9922 tng_trajectory_frame_set_t frame_set;
9926 return(TNG_SUCCESS);
9929 frame_set = &tng_data->current_trajectory_frame_set;
9931 if(tng_data->input_file_path)
9933 free(tng_data->input_file_path);
9934 tng_data->input_file_path = 0;
9937 if(tng_data->input_file)
9939 if(tng_data->output_file == tng_data->input_file)
9941 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9942 tng_data->output_file = 0;
9944 fclose(tng_data->input_file);
9945 tng_data->input_file = 0;
9948 if(tng_data->output_file_path)
9950 free(tng_data->output_file_path);
9951 tng_data->output_file_path = 0;
9954 if(tng_data->output_file)
9956 /* FIXME: Do not always write the hash */
9957 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9958 fclose(tng_data->output_file);
9959 tng_data->output_file = 0;
9962 if(tng_data->first_program_name)
9964 free(tng_data->first_program_name);
9965 tng_data->first_program_name = 0;
9968 if(tng_data->last_program_name)
9970 free(tng_data->last_program_name);
9971 tng_data->last_program_name = 0;
9974 if(tng_data->first_user_name)
9976 free(tng_data->first_user_name);
9977 tng_data->first_user_name = 0;
9980 if(tng_data->last_user_name)
9982 free(tng_data->last_user_name);
9983 tng_data->last_user_name = 0;
9986 if(tng_data->first_computer_name)
9988 free(tng_data->first_computer_name);
9989 tng_data->first_computer_name = 0;
9992 if(tng_data->last_computer_name)
9994 free(tng_data->last_computer_name);
9995 tng_data->last_computer_name = 0;
9998 if(tng_data->first_pgp_signature)
10000 free(tng_data->first_pgp_signature);
10001 tng_data->first_pgp_signature = 0;
10004 if(tng_data->last_pgp_signature)
10006 free(tng_data->last_pgp_signature);
10007 tng_data->last_pgp_signature = 0;
10010 if(tng_data->forcefield_name)
10012 free(tng_data->forcefield_name);
10013 tng_data->forcefield_name = 0;
10016 tng_frame_set_particle_mapping_free(tng_data);
10018 if(frame_set->molecule_cnt_list)
10020 free(frame_set->molecule_cnt_list);
10021 frame_set->molecule_cnt_list = 0;
10024 if(tng_data->var_num_atoms_flag)
10026 n_particles = frame_set->n_particles;
10030 n_particles = tng_data->n_particles;
10033 if(tng_data->non_tr_particle_data)
10035 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
10037 if(tng_data->non_tr_particle_data[i].values)
10039 free(tng_data->non_tr_particle_data[i].values);
10040 tng_data->non_tr_particle_data[i].values = 0;
10043 if(tng_data->non_tr_particle_data[i].strings)
10045 n_values_per_frame = tng_data->non_tr_particle_data[i].
10046 n_values_per_frame;
10047 if(tng_data->non_tr_particle_data[i].strings[0])
10049 for(j = 0; j < n_particles; j++)
10051 if(tng_data->non_tr_particle_data[i].strings[0][j])
10053 for(k = 0; k < n_values_per_frame; k++)
10055 if(tng_data->non_tr_particle_data[i].
10058 free(tng_data->non_tr_particle_data[i].
10060 tng_data->non_tr_particle_data[i].
10061 strings[0][j][k] = 0;
10064 free(tng_data->non_tr_particle_data[i].
10066 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
10069 free(tng_data->non_tr_particle_data[i].strings[0]);
10070 tng_data->non_tr_particle_data[i].strings[0] = 0;
10072 free(tng_data->non_tr_particle_data[i].strings);
10073 tng_data->non_tr_particle_data[i].strings = 0;
10076 if(tng_data->non_tr_particle_data[i].block_name)
10078 free(tng_data->non_tr_particle_data[i].block_name);
10079 tng_data->non_tr_particle_data[i].block_name = 0;
10082 free(tng_data->non_tr_particle_data);
10083 tng_data->non_tr_particle_data = 0;
10086 if(tng_data->non_tr_data)
10088 for(i = 0; i < tng_data->n_data_blocks; i++)
10090 if(tng_data->non_tr_data[i].values)
10092 free(tng_data->non_tr_data[i].values);
10093 tng_data->non_tr_data[i].values = 0;
10096 if(tng_data->non_tr_data[i].strings)
10098 n_values_per_frame = tng_data->non_tr_data[i].
10099 n_values_per_frame;
10100 if(tng_data->non_tr_data[i].strings[0])
10102 for(j = 0; j < n_values_per_frame; j++)
10104 if(tng_data->non_tr_data[i].strings[0][j])
10106 free(tng_data->non_tr_data[i].strings[0][j]);
10107 tng_data->non_tr_data[i].strings[0][j] = 0;
10110 free(tng_data->non_tr_data[i].strings[0]);
10111 tng_data->non_tr_data[i].strings[0] = 0;
10113 free(tng_data->non_tr_data[i].strings);
10114 tng_data->non_tr_data[i].strings = 0;
10117 if(tng_data->non_tr_data[i].block_name)
10119 free(tng_data->non_tr_data[i].block_name);
10120 tng_data->non_tr_data[i].block_name = 0;
10123 free(tng_data->non_tr_data);
10124 tng_data->non_tr_data = 0;
10127 tng_data->n_particle_data_blocks = 0;
10128 tng_data->n_data_blocks = 0;
10130 if(tng_data->compress_algo_pos)
10132 free(tng_data->compress_algo_pos);
10133 tng_data->compress_algo_pos = 0;
10135 if(tng_data->compress_algo_vel)
10137 free(tng_data->compress_algo_vel);
10138 tng_data->compress_algo_vel = 0;
10141 if(frame_set->tr_particle_data)
10143 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10145 if(frame_set->tr_particle_data[i].values)
10147 free(frame_set->tr_particle_data[i].values);
10148 frame_set->tr_particle_data[i].values = 0;
10151 if(frame_set->tr_particle_data[i].strings)
10153 n_values_per_frame = frame_set->tr_particle_data[i].
10154 n_values_per_frame;
10155 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10157 if(frame_set->tr_particle_data[i].strings[j])
10159 for(k = 0; k < n_particles; k++)
10161 if(frame_set->tr_particle_data[i].
10164 for(l = 0; l < n_values_per_frame; l++)
10166 if(frame_set->tr_particle_data[i].
10169 free(frame_set->tr_particle_data[i].
10171 frame_set->tr_particle_data[i].
10172 strings[j][k][l] = 0;
10175 free(frame_set->tr_particle_data[i].
10177 frame_set->tr_particle_data[i].
10181 free(frame_set->tr_particle_data[i].strings[j]);
10182 frame_set->tr_particle_data[i].strings[j] = 0;
10185 free(frame_set->tr_particle_data[i].strings);
10186 frame_set->tr_particle_data[i].strings = 0;
10189 if(frame_set->tr_particle_data[i].block_name)
10191 free(frame_set->tr_particle_data[i].block_name);
10192 frame_set->tr_particle_data[i].block_name = 0;
10195 free(frame_set->tr_particle_data);
10196 frame_set->tr_particle_data = 0;
10199 if(frame_set->tr_data)
10201 for(i = 0; i < frame_set->n_data_blocks; i++)
10203 if(frame_set->tr_data[i].values)
10205 free(frame_set->tr_data[i].values);
10206 frame_set->tr_data[i].values = 0;
10209 if(frame_set->tr_data[i].strings)
10211 n_values_per_frame = frame_set->tr_data[i].
10212 n_values_per_frame;
10213 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10215 if(frame_set->tr_data[i].strings[j])
10217 for(k = 0; k < n_values_per_frame; k++)
10219 if(frame_set->tr_data[i].strings[j][k])
10221 free(frame_set->tr_data[i].strings[j][k]);
10222 frame_set->tr_data[i].strings[j][k] = 0;
10225 free(frame_set->tr_data[i].strings[j]);
10226 frame_set->tr_data[i].strings[j] = 0;
10229 free(frame_set->tr_data[i].strings);
10230 frame_set->tr_data[i].strings = 0;
10233 if(frame_set->tr_data[i].block_name)
10235 free(frame_set->tr_data[i].block_name);
10236 frame_set->tr_data[i].block_name = 0;
10239 free(frame_set->tr_data);
10240 frame_set->tr_data = 0;
10243 frame_set->n_particle_data_blocks = 0;
10244 frame_set->n_data_blocks = 0;
10246 if(tng_data->molecules)
10248 for(i = 0; i < tng_data->n_molecules; i++)
10250 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10252 free(tng_data->molecules);
10253 tng_data->molecules = 0;
10254 tng_data->n_molecules = 0;
10256 if(tng_data->molecule_cnt_list)
10258 free(tng_data->molecule_cnt_list);
10259 tng_data->molecule_cnt_list = 0;
10265 return(TNG_SUCCESS);
10268 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10269 tng_trajectory_t *dest_p)
10271 tng_trajectory_frame_set_t frame_set;
10272 tng_trajectory_t dest;
10274 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10276 *dest_p = malloc(sizeof(struct tng_trajectory));
10279 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10280 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10281 return(TNG_CRITICAL);
10286 frame_set = &dest->current_trajectory_frame_set;
10288 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10289 if(!dest->input_file_path)
10291 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10292 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10293 return(TNG_CRITICAL);
10295 strcpy(dest->input_file_path, src->input_file_path);
10296 dest->input_file = 0;
10297 dest->input_file_len = src->input_file_len;
10298 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10299 if(!dest->output_file_path)
10301 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10302 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10303 return(TNG_CRITICAL);
10305 strcpy(dest->output_file_path, src->output_file_path);
10306 dest->output_file = 0;
10308 dest->first_program_name = 0;
10309 dest->first_user_name = 0;
10310 dest->first_computer_name = 0;
10311 dest->first_pgp_signature = 0;
10312 dest->last_program_name = 0;
10313 dest->last_user_name = 0;
10314 dest->last_computer_name = 0;
10315 dest->last_pgp_signature = 0;
10316 dest->forcefield_name = 0;
10318 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10319 dest->first_trajectory_frame_set_input_file_pos =
10320 src->first_trajectory_frame_set_input_file_pos;
10321 dest->last_trajectory_frame_set_input_file_pos =
10322 src->last_trajectory_frame_set_input_file_pos;
10323 dest->current_trajectory_frame_set_input_file_pos =
10324 src->current_trajectory_frame_set_input_file_pos;
10325 dest->first_trajectory_frame_set_output_file_pos =
10326 src->first_trajectory_frame_set_output_file_pos;
10327 dest->last_trajectory_frame_set_output_file_pos =
10328 src->last_trajectory_frame_set_output_file_pos;
10329 dest->current_trajectory_frame_set_output_file_pos =
10330 src->current_trajectory_frame_set_output_file_pos;
10331 dest->frame_set_n_frames = src->frame_set_n_frames;
10332 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10333 dest->medium_stride_length = src->medium_stride_length;
10334 dest->long_stride_length = src->long_stride_length;
10336 dest->time_per_frame = src->time_per_frame;
10338 /* Currently the non trajectory data blocks are not copied since it
10339 * can lead to problems when freeing memory in a parallel block. */
10340 dest->n_particle_data_blocks = 0;
10341 dest->n_data_blocks = 0;
10342 dest->non_tr_particle_data = 0;
10343 dest->non_tr_data = 0;
10345 dest->compress_algo_pos = 0;
10346 dest->compress_algo_vel = 0;
10347 dest->distance_unit_exponential = -9;
10348 dest->compression_precision = 1000;
10350 frame_set->n_mapping_blocks = 0;
10351 frame_set->mappings = 0;
10352 frame_set->molecule_cnt_list = 0;
10354 frame_set->n_particle_data_blocks = 0;
10355 frame_set->n_data_blocks = 0;
10357 frame_set->tr_particle_data = 0;
10358 frame_set->tr_data = 0;
10360 frame_set->next_frame_set_file_pos = -1;
10361 frame_set->prev_frame_set_file_pos = -1;
10362 frame_set->medium_stride_next_frame_set_file_pos = -1;
10363 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10364 frame_set->long_stride_next_frame_set_file_pos = -1;
10365 frame_set->long_stride_prev_frame_set_file_pos = -1;
10366 frame_set->first_frame = -1;
10368 dest->n_molecules = 0;
10369 dest->molecules = 0;
10370 dest->molecule_cnt_list = 0;
10371 dest->n_particles = src->n_particles;
10373 dest->endianness_32 = src->endianness_32;
10374 dest->endianness_64 = src->endianness_64;
10375 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10376 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10377 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10378 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10380 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10381 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10382 dest->current_trajectory_frame_set.n_frames = 0;
10384 return(TNG_SUCCESS);
10387 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10388 char *file_name, const int max_len)
10390 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10391 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10393 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10394 file_name[max_len - 1] = 0;
10396 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10398 return(TNG_FAILURE);
10400 return(TNG_SUCCESS);
10403 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10404 const char *file_name)
10409 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10410 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10413 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10416 return(TNG_SUCCESS);
10419 if(tng_data->input_file)
10421 fclose(tng_data->input_file);
10424 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10425 temp = realloc(tng_data->input_file_path, len);
10428 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10429 __FILE__, __LINE__);
10430 free(tng_data->input_file_path);
10431 tng_data->input_file_path = 0;
10432 return(TNG_CRITICAL);
10434 tng_data->input_file_path = temp;
10436 strncpy(tng_data->input_file_path, file_name, len);
10438 return(tng_input_file_init(tng_data));
10441 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10442 char *file_name, const int max_len)
10444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10445 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10447 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10448 file_name[max_len - 1] = 0;
10450 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10452 return(TNG_FAILURE);
10454 return(TNG_SUCCESS);
10457 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10458 const char *file_name)
10463 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10464 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10466 if(tng_data->output_file_path &&
10467 strcmp(tng_data->output_file_path, file_name) == 0)
10469 return(TNG_SUCCESS);
10472 if(tng_data->output_file)
10474 fclose(tng_data->output_file);
10477 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10478 temp = realloc(tng_data->output_file_path, len);
10481 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10482 __FILE__, __LINE__);
10483 free(tng_data->output_file_path);
10484 tng_data->output_file_path = 0;
10485 return(TNG_CRITICAL);
10487 tng_data->output_file_path = temp;
10489 strncpy(tng_data->output_file_path, file_name, len);
10491 return(tng_output_file_init(tng_data));
10494 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10495 (tng_trajectory_t tng_data,
10496 const char *file_name)
10501 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10502 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10504 if(tng_data->output_file_path &&
10505 strcmp(tng_data->output_file_path, file_name) == 0)
10507 return(TNG_SUCCESS);
10510 if(tng_data->output_file)
10512 fclose(tng_data->output_file);
10515 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10516 temp = realloc(tng_data->output_file_path, len);
10519 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10520 __FILE__, __LINE__);
10521 free(tng_data->output_file_path);
10522 tng_data->output_file_path = 0;
10523 return(TNG_CRITICAL);
10525 tng_data->output_file_path = temp;
10527 strncpy(tng_data->output_file_path, file_name, len);
10529 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10530 if(!tng_data->output_file)
10532 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10533 tng_data->output_file_path, __FILE__, __LINE__);
10534 return(TNG_CRITICAL);
10536 tng_data->input_file = tng_data->output_file;
10538 return(TNG_SUCCESS);
10541 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10542 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10544 tng_endianness_32 end_32;
10545 tng_endianness_64 end_64;
10547 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10548 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10550 if(tng_data->output_endianness_swap_func_32)
10552 /* If other endianness variants are added they must be added here as well */
10553 if(tng_data->output_endianness_swap_func_32 ==
10554 &tng_swap_byte_order_big_endian_32)
10556 end_32 = TNG_BIG_ENDIAN_32;
10558 else if(tng_data->output_endianness_swap_func_32 ==
10559 &tng_swap_byte_order_little_endian_32)
10561 end_32 = TNG_LITTLE_ENDIAN_32;
10565 return(TNG_FAILURE);
10570 end_32 = (tng_endianness_32)tng_data->endianness_32;
10573 if(tng_data->output_endianness_swap_func_64)
10575 /* If other endianness variants are added they must be added here as well */
10576 if(tng_data->output_endianness_swap_func_64 ==
10577 &tng_swap_byte_order_big_endian_64)
10579 end_64 = TNG_BIG_ENDIAN_64;
10581 else if(tng_data->output_endianness_swap_func_64 ==
10582 &tng_swap_byte_order_little_endian_64)
10584 end_64 = TNG_LITTLE_ENDIAN_64;
10588 return(TNG_FAILURE);
10593 end_64 = (tng_endianness_64)tng_data->endianness_64;
10596 if((int)end_32 != (int)end_64)
10598 return(TNG_FAILURE);
10601 if(end_32 == TNG_LITTLE_ENDIAN_32)
10603 *endianness = TNG_LITTLE_ENDIAN;
10606 else if(end_32 == TNG_BIG_ENDIAN_32)
10608 *endianness = TNG_BIG_ENDIAN;
10612 return(TNG_FAILURE);
10615 return(TNG_SUCCESS);
10618 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10619 (tng_trajectory_t tng_data,
10620 const tng_file_endianness endianness)
10622 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10624 /* Tne endianness cannot be changed if the data has already been written
10625 * to the output file. */
10626 if(ftell(tng_data->output_file) > 0)
10628 return(TNG_FAILURE);
10631 if(endianness == TNG_BIG_ENDIAN)
10633 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10635 tng_data->output_endianness_swap_func_32 = 0;
10639 tng_data->output_endianness_swap_func_32 =
10640 &tng_swap_byte_order_big_endian_32;
10642 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10644 tng_data->output_endianness_swap_func_64 = 0;
10648 tng_data->output_endianness_swap_func_64 =
10649 &tng_swap_byte_order_big_endian_64;
10651 return(TNG_SUCCESS);
10653 else if(endianness == TNG_LITTLE_ENDIAN)
10655 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10657 tng_data->output_endianness_swap_func_32 = 0;
10661 tng_data->output_endianness_swap_func_32 =
10662 &tng_swap_byte_order_little_endian_32;
10664 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10666 tng_data->output_endianness_swap_func_64 = 0;
10670 tng_data->output_endianness_swap_func_64 =
10671 &tng_swap_byte_order_little_endian_64;
10673 return(TNG_SUCCESS);
10676 /* If the specified endianness is neither big nor little endian return a
10678 return(TNG_FAILURE);
10681 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10682 (const tng_trajectory_t tng_data,
10683 char *name, const int max_len)
10685 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10686 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10688 strncpy(name, tng_data->first_program_name, max_len - 1);
10689 name[max_len - 1] = 0;
10691 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10693 return(TNG_FAILURE);
10695 return(TNG_SUCCESS);
10698 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10699 const char *new_name)
10703 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10704 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10706 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10708 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10710 free(tng_data->first_program_name);
10711 tng_data->first_program_name = 0;
10713 if(!tng_data->first_program_name)
10715 tng_data->first_program_name = malloc(len);
10716 if(!tng_data->first_program_name)
10718 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10719 __FILE__, __LINE__);
10720 return(TNG_CRITICAL);
10724 strncpy(tng_data->first_program_name, new_name, len);
10726 return(TNG_SUCCESS);
10729 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10730 (const tng_trajectory_t tng_data,
10731 char *name, const int max_len)
10733 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10734 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10736 strncpy(name, tng_data->last_program_name, max_len - 1);
10737 name[max_len - 1] = 0;
10739 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10741 return(TNG_FAILURE);
10743 return(TNG_SUCCESS);
10746 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10747 (tng_trajectory_t tng_data,
10748 const char *new_name)
10752 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10753 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10755 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10757 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10759 free(tng_data->last_program_name);
10760 tng_data->last_program_name = 0;
10762 if(!tng_data->last_program_name)
10764 tng_data->last_program_name = malloc(len);
10765 if(!tng_data->last_program_name)
10767 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10768 __FILE__, __LINE__);
10769 return(TNG_CRITICAL);
10773 strncpy(tng_data->last_program_name, new_name, len);
10775 return(TNG_SUCCESS);
10778 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10779 (const tng_trajectory_t tng_data,
10780 char *name, const int max_len)
10782 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10783 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10785 strncpy(name, tng_data->first_user_name, max_len - 1);
10786 name[max_len - 1] = 0;
10788 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10790 return(TNG_FAILURE);
10792 return(TNG_SUCCESS);
10795 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10796 (tng_trajectory_t tng_data,
10797 const char *new_name)
10801 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10802 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10804 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10806 /* If the currently stored string length is not enough to store the new
10807 * string it is freed and reallocated. */
10808 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10810 free(tng_data->first_user_name);
10811 tng_data->first_user_name = 0;
10813 if(!tng_data->first_user_name)
10815 tng_data->first_user_name = malloc(len);
10816 if(!tng_data->first_user_name)
10818 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10819 __FILE__, __LINE__);
10820 return(TNG_CRITICAL);
10824 strncpy(tng_data->first_user_name, new_name, len);
10826 return(TNG_SUCCESS);
10829 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10830 (const tng_trajectory_t tng_data,
10831 char *name, const int max_len)
10833 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10834 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10836 strncpy(name, tng_data->last_user_name, max_len - 1);
10837 name[max_len - 1] = 0;
10839 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10841 return(TNG_FAILURE);
10843 return(TNG_SUCCESS);
10846 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10847 (tng_trajectory_t tng_data,
10848 const char *new_name)
10852 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10853 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10855 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10857 /* If the currently stored string length is not enough to store the new
10858 * string it is freed and reallocated. */
10859 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10861 free(tng_data->last_user_name);
10862 tng_data->last_user_name = 0;
10864 if(!tng_data->last_user_name)
10866 tng_data->last_user_name = malloc(len);
10867 if(!tng_data->last_user_name)
10869 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10870 __FILE__, __LINE__);
10871 return(TNG_CRITICAL);
10875 strncpy(tng_data->last_user_name, new_name, len);
10877 return(TNG_SUCCESS);
10880 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10881 (const tng_trajectory_t tng_data,
10882 char *name, const int max_len)
10884 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10885 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10887 strncpy(name, tng_data->first_computer_name, max_len - 1);
10888 name[max_len - 1] = 0;
10890 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10892 return(TNG_FAILURE);
10894 return(TNG_SUCCESS);
10897 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10898 (tng_trajectory_t tng_data,
10899 const char *new_name)
10903 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10904 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10906 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10908 /* If the currently stored string length is not enough to store the new
10909 * string it is freed and reallocated. */
10910 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10912 free(tng_data->first_computer_name);
10913 tng_data->first_computer_name = 0;
10915 if(!tng_data->first_computer_name)
10917 tng_data->first_computer_name = malloc(len);
10918 if(!tng_data->first_computer_name)
10920 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10921 __FILE__, __LINE__);
10922 return(TNG_CRITICAL);
10926 strncpy(tng_data->first_computer_name, new_name, len);
10928 return(TNG_SUCCESS);
10931 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10932 (const tng_trajectory_t tng_data,
10933 char *name, const int max_len)
10935 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10936 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10938 strncpy(name, tng_data->last_computer_name, max_len - 1);
10939 name[max_len - 1] = 0;
10941 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10943 return(TNG_FAILURE);
10945 return(TNG_SUCCESS);
10948 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10949 (tng_trajectory_t tng_data,
10950 const char *new_name)
10954 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10955 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10957 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10959 /* If the currently stored string length is not enough to store the new
10960 * string it is freed and reallocated. */
10961 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10964 free(tng_data->last_computer_name);
10965 tng_data->last_computer_name = 0;
10967 if(!tng_data->last_computer_name)
10969 tng_data->last_computer_name = malloc(len);
10970 if(!tng_data->last_computer_name)
10972 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10973 __FILE__, __LINE__);
10974 return(TNG_CRITICAL);
10978 strncpy(tng_data->last_computer_name, new_name, len);
10980 return(TNG_SUCCESS);
10983 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10984 (const tng_trajectory_t tng_data,
10985 char *signature, const int max_len)
10987 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10988 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10990 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
10991 signature[max_len - 1] = 0;
10993 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10995 return(TNG_FAILURE);
10997 return(TNG_SUCCESS);
11000 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
11001 (tng_trajectory_t tng_data,
11002 const char *signature)
11006 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11007 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11009 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11011 /* If the currently stored string length is not enough to store the new
11012 * string it is freed and reallocated. */
11013 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
11016 free(tng_data->first_pgp_signature);
11017 tng_data->first_pgp_signature = 0;
11019 if(!tng_data->first_pgp_signature)
11021 tng_data->first_pgp_signature = malloc(len);
11022 if(!tng_data->first_pgp_signature)
11024 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11025 __FILE__, __LINE__);
11026 return(TNG_CRITICAL);
11030 strncpy(tng_data->first_pgp_signature, signature, len);
11032 return(TNG_SUCCESS);
11035 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11036 (const tng_trajectory_t tng_data,
11037 char *signature, const int max_len)
11039 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11040 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11042 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
11043 signature[max_len - 1] = 0;
11045 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
11047 return(TNG_FAILURE);
11049 return(TNG_SUCCESS);
11052 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11053 (tng_trajectory_t tng_data,
11054 const char *signature)
11058 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11059 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
11061 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
11063 /* If the currently stored string length is not enough to store the new
11064 * string it is freed and reallocated. */
11065 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
11068 free(tng_data->last_pgp_signature);
11069 tng_data->last_pgp_signature = 0;
11071 if(!tng_data->last_pgp_signature)
11073 tng_data->last_pgp_signature = malloc(len);
11074 if(!tng_data->last_pgp_signature)
11076 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11077 __FILE__, __LINE__);
11078 return(TNG_CRITICAL);
11082 strncpy(tng_data->last_pgp_signature, signature, len);
11084 return(TNG_SUCCESS);
11087 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11088 (const tng_trajectory_t tng_data,
11089 char *name, const int max_len)
11091 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11092 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11094 strncpy(name, tng_data->forcefield_name, max_len - 1);
11095 name[max_len - 1] = 0;
11097 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11099 return(TNG_FAILURE);
11101 return(TNG_SUCCESS);
11104 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11105 (tng_trajectory_t tng_data,
11106 const char *new_name)
11110 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11111 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11113 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11115 /* If the currently stored string length is not enough to store the new
11116 * string it is freed and reallocated. */
11117 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11119 free(tng_data->forcefield_name);
11120 tng_data->forcefield_name = 0;
11122 if(!tng_data->forcefield_name)
11124 tng_data->forcefield_name = malloc(len);
11125 if(!tng_data->forcefield_name)
11127 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11128 __FILE__, __LINE__);
11129 return(TNG_CRITICAL);
11133 strncpy(tng_data->forcefield_name, new_name, len);
11135 return(TNG_SUCCESS);
11138 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11139 (const tng_trajectory_t tng_data,
11142 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11143 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11145 *len = tng_data->medium_stride_length;
11147 return(TNG_SUCCESS);
11150 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11151 (tng_trajectory_t tng_data,
11154 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11156 if(len >= tng_data->long_stride_length)
11158 return(TNG_FAILURE);
11160 tng_data->medium_stride_length = len;
11162 return(TNG_SUCCESS);
11165 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11166 (const tng_trajectory_t tng_data,
11169 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11170 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11172 *len = tng_data->long_stride_length;
11174 return(TNG_SUCCESS);
11177 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11178 (tng_trajectory_t tng_data,
11181 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11183 if(len <= tng_data->medium_stride_length)
11185 return(TNG_FAILURE);
11187 tng_data->long_stride_length = len;
11189 return(TNG_SUCCESS);
11192 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11193 (const tng_trajectory_t tng_data,
11196 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11197 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11199 *time = tng_data->time_per_frame;
11201 return(TNG_SUCCESS);
11204 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11205 (tng_trajectory_t tng_data,
11208 tng_trajectory_frame_set_t frame_set;
11210 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11211 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11213 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11215 return(TNG_SUCCESS);
11218 frame_set = &tng_data->current_trajectory_frame_set;
11220 /* If the current frame set is not finished write it to disk before
11221 changing time per frame. */
11222 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11224 frame_set->n_frames = frame_set->n_unwritten_frames;
11225 tng_frame_set_write(tng_data, TNG_USE_HASH);
11227 tng_data->time_per_frame = time;
11229 return(TNG_SUCCESS);
11232 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11233 (const tng_trajectory_t tng_data,
11236 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11237 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11239 *len = tng_data->input_file_len;
11241 return(TNG_SUCCESS);
11244 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11245 (const tng_trajectory_t tng_data,
11248 tng_gen_block_t block;
11249 tng_function_status stat;
11251 int64_t last_file_pos, first_frame, n_frames;
11253 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11254 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11255 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11257 file_pos = ftell(tng_data->input_file);
11258 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11260 if(last_file_pos <= 0)
11262 return(TNG_FAILURE);
11265 tng_block_init(&block);
11266 fseek(tng_data->input_file,
11267 (long)last_file_pos,
11269 /* Read block headers first to see that a frame set block is found. */
11270 stat = tng_block_header_read(tng_data, block);
11271 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11273 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11274 __FILE__, __LINE__);
11275 tng_block_destroy(&block);
11276 return(TNG_FAILURE);
11278 tng_block_destroy(&block);
11280 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11282 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11283 __FILE__, __LINE__);
11284 return(TNG_CRITICAL);
11286 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11288 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11289 __FILE__, __LINE__);
11290 return(TNG_CRITICAL);
11292 fseek(tng_data->input_file, file_pos, SEEK_SET);
11294 *n = first_frame + n_frames;
11296 return(TNG_SUCCESS);
11299 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11300 (const tng_trajectory_t tng_data,
11303 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11305 *precision = tng_data->compression_precision;
11307 return(TNG_SUCCESS);
11310 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11311 (tng_trajectory_t tng_data,
11312 const double precision)
11314 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11316 tng_data->compression_precision = precision;
11318 return(TNG_SUCCESS);
11321 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11322 (tng_trajectory_t tng_data,
11325 tng_molecule_t mol;
11329 tng_function_status stat;
11330 int64_t diff, n_mod, n_impl;
11332 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11334 diff = n - tng_data->n_particles;
11336 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11337 if(stat == TNG_SUCCESS)
11339 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11341 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11342 __FILE__, __LINE__);
11343 return(TNG_FAILURE);
11345 diff -= n_impl * mol->n_atoms;
11350 if(stat == TNG_SUCCESS)
11352 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11355 return(TNG_SUCCESS);
11359 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11360 fprintf(stderr, "particle count.\n");
11361 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11362 __FILE__, __LINE__);
11363 /* FIXME: Should we set the count of all other molecules to 0 and add
11364 * implicit molecules? */
11365 return(TNG_FAILURE);
11367 if(stat != TNG_SUCCESS)
11369 stat = tng_molecule_add(tng_data,
11370 "TNG_IMPLICIT_MOL",
11372 if(stat != TNG_SUCCESS)
11376 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11377 if(stat != TNG_SUCCESS)
11381 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11382 if(stat != TNG_SUCCESS)
11386 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11387 if(stat != TNG_SUCCESS)
11394 if(mol->n_atoms > 1)
11396 n_mod = diff % mol->n_atoms;
11399 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11400 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11401 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11402 __FILE__, __LINE__);
11403 return(TNG_FAILURE);
11405 diff /= mol->n_atoms;
11408 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11413 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11414 (const tng_trajectory_t tng_data,
11417 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11418 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11420 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11422 *n = tng_data->n_particles;
11426 *n = tng_data->current_trajectory_frame_set.n_particles;
11429 return(TNG_SUCCESS);
11432 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11433 (const tng_trajectory_t tng_data,
11436 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11437 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11439 *variable = tng_data->var_num_atoms_flag;
11441 return(TNG_SUCCESS);
11444 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11445 (const tng_trajectory_t tng_data,
11448 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11449 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11451 *n = tng_data->n_molecules;
11453 return(TNG_SUCCESS);
11456 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11457 (const tng_trajectory_t tng_data,
11460 int64_t *cnt_list = 0, cnt = 0, i;
11462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11463 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11465 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11469 return(TNG_FAILURE);
11472 for(i = 0; i < tng_data->n_molecules; i++)
11474 cnt += cnt_list[i];
11479 return(TNG_SUCCESS);
11482 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11483 (const tng_trajectory_t tng_data,
11484 int64_t **mol_cnt_list)
11486 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11488 if(tng_data->var_num_atoms_flag)
11490 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11495 *mol_cnt_list = tng_data->molecule_cnt_list;
11497 if(*mol_cnt_list == 0)
11499 return(TNG_FAILURE);
11501 return(TNG_SUCCESS);
11504 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11505 (const tng_trajectory_t tng_data,
11508 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11509 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11511 *exp = tng_data->distance_unit_exponential;
11513 return(TNG_SUCCESS);
11516 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11517 (const tng_trajectory_t tng_data,
11520 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11522 tng_data->distance_unit_exponential = exp;
11524 return(TNG_SUCCESS);
11527 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11528 (const tng_trajectory_t tng_data,
11531 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11532 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11534 *n = tng_data->frame_set_n_frames;
11536 return(TNG_SUCCESS);
11539 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11540 (const tng_trajectory_t tng_data,
11543 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11545 tng_data->frame_set_n_frames = n;
11547 return(TNG_SUCCESS);
11550 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11551 (const tng_trajectory_t tng_data,
11554 int64_t long_stride_length, medium_stride_length;
11555 long file_pos, orig_frame_set_file_pos;
11556 tng_trajectory_frame_set_t frame_set;
11557 struct tng_trajectory_frame_set orig_frame_set;
11558 tng_gen_block_t block;
11559 tng_function_status stat;
11562 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11563 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11565 orig_frame_set = tng_data->current_trajectory_frame_set;
11567 frame_set = &tng_data->current_trajectory_frame_set;
11569 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11570 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
11574 *n = tng_data->n_trajectory_frame_sets = cnt;
11575 return(TNG_SUCCESS);
11578 tng_block_init(&block);
11579 fseek(tng_data->input_file,
11582 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11583 /* Read block headers first to see what block is found. */
11584 stat = tng_block_header_read(tng_data, block);
11585 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11587 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n", file_pos,
11588 __FILE__, __LINE__);
11589 tng_block_destroy(&block);
11590 return(TNG_CRITICAL);
11593 if(tng_block_read_next(tng_data, block,
11594 TNG_SKIP_HASH) != TNG_SUCCESS)
11596 tng_block_destroy(&block);
11597 return(TNG_CRITICAL);
11602 long_stride_length = tng_data->long_stride_length;
11603 medium_stride_length = tng_data->medium_stride_length;
11605 /* Take long steps forward until a long step forward would be too long or
11606 * the last frame set is found */
11607 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
11608 while(file_pos > 0)
11612 cnt += long_stride_length;
11613 fseek(tng_data->input_file, file_pos, SEEK_SET);
11614 /* Read block headers first to see what block is found. */
11615 stat = tng_block_header_read(tng_data, block);
11616 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11618 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11619 file_pos, __FILE__, __LINE__);
11620 tng_block_destroy(&block);
11621 return(TNG_CRITICAL);
11624 if(tng_block_read_next(tng_data, block,
11625 TNG_SKIP_HASH) != TNG_SUCCESS)
11627 tng_block_destroy(&block);
11628 return(TNG_CRITICAL);
11631 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
11634 /* Take medium steps forward until a medium step forward would be too long
11635 * or the last frame set is found */
11636 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11637 while(file_pos > 0)
11641 cnt += medium_stride_length;
11642 fseek(tng_data->input_file,
11645 /* Read block headers first to see what block is found. */
11646 stat = tng_block_header_read(tng_data, block);
11647 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11649 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11650 file_pos, __FILE__, __LINE__);
11651 tng_block_destroy(&block);
11652 return(TNG_CRITICAL);
11655 if(tng_block_read_next(tng_data, block,
11656 TNG_SKIP_HASH) != TNG_SUCCESS)
11658 tng_block_destroy(&block);
11659 return(TNG_CRITICAL);
11662 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11665 /* Take one step forward until the last frame set is found */
11666 file_pos = (long)frame_set->next_frame_set_file_pos;
11667 while(file_pos > 0)
11672 fseek(tng_data->input_file,
11675 /* Read block headers first to see what block is found. */
11676 stat = tng_block_header_read(tng_data, block);
11677 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11679 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11680 file_pos, __FILE__, __LINE__);
11681 tng_block_destroy(&block);
11682 return(TNG_CRITICAL);
11685 if(tng_block_read_next(tng_data, block,
11686 TNG_SKIP_HASH) != TNG_SUCCESS)
11688 tng_block_destroy(&block);
11689 return(TNG_CRITICAL);
11692 file_pos = (long)frame_set->next_frame_set_file_pos;
11695 tng_block_destroy(&block);
11697 *n = tng_data->n_trajectory_frame_sets = cnt;
11699 *frame_set = orig_frame_set;
11700 /* The mapping block in the original frame set has been freed when reading
11701 * other frame sets. */
11702 frame_set->mappings = 0;
11703 frame_set->n_mapping_blocks = 0;
11705 fseek(tng_data->input_file,
11706 (long)tng_data->first_trajectory_frame_set_input_file_pos,
11709 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11711 return(TNG_SUCCESS);
11714 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11715 (const tng_trajectory_t tng_data,
11716 tng_trajectory_frame_set_t *frame_set_p)
11718 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11720 *frame_set_p = &tng_data->current_trajectory_frame_set;
11722 return(TNG_SUCCESS);
11725 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11726 (tng_trajectory_t tng_data,
11729 int64_t long_stride_length, medium_stride_length;
11730 int64_t file_pos, curr_nr = 0, n_frame_sets;
11731 tng_trajectory_frame_set_t frame_set;
11732 tng_gen_block_t block;
11733 tng_function_status stat;
11735 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11736 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11738 frame_set = &tng_data->current_trajectory_frame_set;
11740 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11742 if(stat != TNG_SUCCESS)
11747 if(nr >= n_frame_sets)
11749 return(TNG_FAILURE);
11752 long_stride_length = tng_data->long_stride_length;
11753 medium_stride_length = tng_data->medium_stride_length;
11755 /* FIXME: The frame set number of the current frame set is not stored */
11757 if(nr < n_frame_sets - 1 - nr)
11759 /* Start from the beginning */
11760 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11764 /* Start from the end */
11765 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11766 curr_nr = n_frame_sets - 1;
11770 return(TNG_FAILURE);
11773 tng_block_init(&block);
11774 fseek(tng_data->input_file,
11777 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11778 /* Read block headers first to see what block is found. */
11779 stat = tng_block_header_read(tng_data, block);
11780 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11782 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11783 __FILE__, __LINE__);
11784 tng_block_destroy(&block);
11785 return(TNG_CRITICAL);
11788 if(tng_block_read_next(tng_data, block,
11789 TNG_SKIP_HASH) != TNG_SUCCESS)
11791 tng_block_destroy(&block);
11792 return(TNG_CRITICAL);
11797 tng_block_destroy(&block);
11798 return(TNG_SUCCESS);
11801 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11803 /* Take long steps forward until a long step forward would be too long or
11804 * the right frame set is found */
11805 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11807 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11810 curr_nr += long_stride_length;
11811 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11812 /* Read block headers first to see what block is found. */
11813 stat = tng_block_header_read(tng_data, block);
11814 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11816 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11817 file_pos, __FILE__, __LINE__);
11818 tng_block_destroy(&block);
11819 return(TNG_CRITICAL);
11822 if(tng_block_read_next(tng_data, block,
11823 TNG_SKIP_HASH) != TNG_SUCCESS)
11825 tng_block_destroy(&block);
11826 return(TNG_CRITICAL);
11830 tng_block_destroy(&block);
11831 return(TNG_SUCCESS);
11836 /* Take medium steps forward until a medium step forward would be too long
11837 * or the right frame set is found */
11838 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11840 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11843 curr_nr += medium_stride_length;
11844 fseek(tng_data->input_file,
11847 /* Read block headers first to see what block is found. */
11848 stat = tng_block_header_read(tng_data, block);
11849 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11851 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11852 file_pos, __FILE__, __LINE__);
11853 tng_block_destroy(&block);
11854 return(TNG_CRITICAL);
11857 if(tng_block_read_next(tng_data, block,
11858 TNG_SKIP_HASH) != TNG_SUCCESS)
11860 tng_block_destroy(&block);
11861 return(TNG_CRITICAL);
11865 tng_block_destroy(&block);
11866 return(TNG_SUCCESS);
11871 /* Take one step forward until the right frame set is found */
11872 while(file_pos > 0 && curr_nr < nr)
11874 file_pos = frame_set->next_frame_set_file_pos;
11879 fseek(tng_data->input_file,
11882 /* Read block headers first to see what block is found. */
11883 stat = tng_block_header_read(tng_data, block);
11884 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11886 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11887 file_pos, __FILE__, __LINE__);
11888 tng_block_destroy(&block);
11889 return(TNG_CRITICAL);
11892 if(tng_block_read_next(tng_data, block,
11893 TNG_SKIP_HASH) != TNG_SUCCESS)
11895 tng_block_destroy(&block);
11896 return(TNG_CRITICAL);
11900 tng_block_destroy(&block);
11901 return(TNG_SUCCESS);
11906 /* Take long steps backward until a long step backward would be too long
11907 * or the right frame set is found */
11908 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11910 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11913 curr_nr -= long_stride_length;
11914 fseek(tng_data->input_file,
11917 /* Read block headers first to see what block is found. */
11918 stat = tng_block_header_read(tng_data, block);
11919 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11921 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11922 file_pos, __FILE__, __LINE__);
11923 tng_block_destroy(&block);
11924 return(TNG_CRITICAL);
11927 if(tng_block_read_next(tng_data, block,
11928 TNG_SKIP_HASH) != TNG_SUCCESS)
11930 tng_block_destroy(&block);
11931 return(TNG_CRITICAL);
11935 tng_block_destroy(&block);
11936 return(TNG_SUCCESS);
11941 /* Take medium steps backward until a medium step backward would be too long
11942 * or the right frame set is found */
11943 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11945 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11948 curr_nr -= medium_stride_length;
11949 fseek(tng_data->input_file,
11952 /* Read block headers first to see what block is found. */
11953 stat = tng_block_header_read(tng_data, block);
11954 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11956 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11957 file_pos, __FILE__, __LINE__);
11958 tng_block_destroy(&block);
11959 return(TNG_CRITICAL);
11962 if(tng_block_read_next(tng_data, block,
11963 TNG_SKIP_HASH) != TNG_SUCCESS)
11965 tng_block_destroy(&block);
11966 return(TNG_CRITICAL);
11970 tng_block_destroy(&block);
11971 return(TNG_SUCCESS);
11976 /* Take one step backward until the right frame set is found */
11977 while(file_pos > 0 && curr_nr > nr)
11979 file_pos = frame_set->prev_frame_set_file_pos;
11983 fseek(tng_data->input_file,
11986 /* Read block headers first to see what block is found. */
11987 stat = tng_block_header_read(tng_data, block);
11988 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11990 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11991 file_pos, __FILE__, __LINE__);
11992 tng_block_destroy(&block);
11993 return(TNG_CRITICAL);
11996 if(tng_block_read_next(tng_data, block,
11997 TNG_SKIP_HASH) != TNG_SUCCESS)
11999 tng_block_destroy(&block);
12000 return(TNG_CRITICAL);
12004 tng_block_destroy(&block);
12005 return(TNG_SUCCESS);
12010 /* If for some reason the current frame set is not yet found,
12011 * take one step forward until the right frame set is found */
12012 while(file_pos > 0 && curr_nr < nr)
12014 file_pos = frame_set->next_frame_set_file_pos;
12018 fseek(tng_data->input_file,
12021 /* Read block headers first to see what block is found. */
12022 stat = tng_block_header_read(tng_data, block);
12023 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12025 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12026 file_pos, __FILE__, __LINE__);
12027 tng_block_destroy(&block);
12028 return(TNG_CRITICAL);
12031 if(tng_block_read_next(tng_data, block,
12032 TNG_SKIP_HASH) != TNG_SUCCESS)
12034 tng_block_destroy(&block);
12035 return(TNG_CRITICAL);
12039 tng_block_destroy(&block);
12040 return(TNG_SUCCESS);
12045 tng_block_destroy(&block);
12046 return(TNG_FAILURE);
12049 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12050 (tng_trajectory_t tng_data,
12051 const int64_t frame)
12053 int64_t first_frame, last_frame, n_frames_per_frame_set;
12054 int64_t long_stride_length, medium_stride_length;
12055 int64_t file_pos, temp_frame, n_frames;
12056 tng_trajectory_frame_set_t frame_set;
12057 tng_gen_block_t block;
12058 tng_function_status stat;
12060 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12061 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
12063 frame_set = &tng_data->current_trajectory_frame_set;
12065 tng_block_init(&block);
12067 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
12069 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12070 fseek(tng_data->input_file,
12073 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
12074 /* Read block headers first to see what block is found. */
12075 stat = tng_block_header_read(tng_data, block);
12076 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12078 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12079 file_pos, __FILE__, __LINE__);
12080 tng_block_destroy(&block);
12081 return(TNG_CRITICAL);
12084 if(tng_block_read_next(tng_data, block,
12085 TNG_SKIP_HASH) != TNG_SUCCESS)
12087 tng_block_destroy(&block);
12088 return(TNG_CRITICAL);
12092 first_frame = tng_max_i64(frame_set->first_frame, 0);
12093 last_frame = first_frame + frame_set->n_frames - 1;
12094 /* Is this the right frame set? */
12095 if(first_frame <= frame && frame <= last_frame)
12097 tng_block_destroy(&block);
12098 return(TNG_SUCCESS);
12101 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12102 long_stride_length = tng_data->long_stride_length;
12103 medium_stride_length = tng_data->medium_stride_length;
12105 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12108 if(temp_frame - first_frame > n_frames_per_frame_set)
12110 n_frames_per_frame_set = temp_frame - first_frame;
12114 tng_num_frames_get(tng_data, &n_frames);
12116 if(frame >= n_frames)
12118 tng_block_destroy(&block);
12119 return(TNG_FAILURE);
12122 if(first_frame - frame >= frame ||
12123 frame - last_frame >
12124 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12126 /* Start from the beginning */
12127 if(first_frame - frame >= frame)
12129 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12133 tng_block_destroy(&block);
12134 return(TNG_FAILURE);
12137 /* Start from the end */
12138 else if(frame - first_frame > (n_frames - 1) - frame)
12140 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12142 /* If the last frame set position is not set start from the current
12143 * frame set, since it will be closer than the first frame set. */
12145 /* Start from current */
12148 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12153 fseek(tng_data->input_file,
12156 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
12157 /* Read block headers first to see what block is found. */
12158 stat = tng_block_header_read(tng_data, block);
12159 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12161 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12162 file_pos, __FILE__, __LINE__);
12163 tng_block_destroy(&block);
12164 return(TNG_CRITICAL);
12167 if(tng_block_read_next(tng_data, block,
12168 TNG_SKIP_HASH) != TNG_SUCCESS)
12170 tng_block_destroy(&block);
12171 return(TNG_CRITICAL);
12176 first_frame = tng_max_i64(frame_set->first_frame, 0);
12177 last_frame = first_frame + frame_set->n_frames - 1;
12179 if(frame >= first_frame && frame <= last_frame)
12181 tng_block_destroy(&block);
12182 return(TNG_SUCCESS);
12185 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12187 /* Take long steps forward until a long step forward would be too long or
12188 * the right frame set is found */
12189 while(file_pos > 0 && first_frame + long_stride_length *
12190 n_frames_per_frame_set <= frame)
12192 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12195 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
12196 /* Read block headers first to see what block is found. */
12197 stat = tng_block_header_read(tng_data, block);
12198 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12200 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12201 file_pos, __FILE__, __LINE__);
12202 tng_block_destroy(&block);
12203 return(TNG_CRITICAL);
12206 if(tng_block_read_next(tng_data, block,
12207 TNG_SKIP_HASH) != TNG_SUCCESS)
12209 tng_block_destroy(&block);
12210 return(TNG_CRITICAL);
12213 first_frame = tng_max_i64(frame_set->first_frame, 0);
12214 last_frame = first_frame + frame_set->n_frames - 1;
12215 if(frame >= first_frame && frame <= last_frame)
12217 tng_block_destroy(&block);
12218 return(TNG_SUCCESS);
12222 /* Take medium steps forward until a medium step forward would be too long
12223 * or the right frame set is found */
12224 while(file_pos > 0 && first_frame + medium_stride_length *
12225 n_frames_per_frame_set <= frame)
12227 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12230 fseek(tng_data->input_file,
12233 /* Read block headers first to see what block is found. */
12234 stat = tng_block_header_read(tng_data, block);
12235 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12237 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12238 file_pos, __FILE__, __LINE__);
12239 tng_block_destroy(&block);
12240 return(TNG_CRITICAL);
12243 if(tng_block_read_next(tng_data, block,
12244 TNG_SKIP_HASH) != TNG_SUCCESS)
12246 tng_block_destroy(&block);
12247 return(TNG_CRITICAL);
12250 first_frame = tng_max_i64(frame_set->first_frame, 0);
12251 last_frame = first_frame + frame_set->n_frames - 1;
12252 if(frame >= first_frame && frame <= last_frame)
12254 tng_block_destroy(&block);
12255 return(TNG_SUCCESS);
12259 /* Take one step forward until the right frame set is found */
12260 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12262 file_pos = frame_set->next_frame_set_file_pos;
12265 fseek(tng_data->input_file,
12268 /* Read block headers first to see what block is found. */
12269 stat = tng_block_header_read(tng_data, block);
12270 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12272 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12273 file_pos, __FILE__, __LINE__);
12274 tng_block_destroy(&block);
12275 return(TNG_CRITICAL);
12278 if(tng_block_read_next(tng_data, block,
12279 TNG_SKIP_HASH) != TNG_SUCCESS)
12281 tng_block_destroy(&block);
12282 return(TNG_CRITICAL);
12285 first_frame = tng_max_i64(frame_set->first_frame, 0);
12286 last_frame = first_frame + frame_set->n_frames - 1;
12287 if(frame >= first_frame && frame <= last_frame)
12289 tng_block_destroy(&block);
12290 return(TNG_SUCCESS);
12294 /* Take long steps backward until a long step backward would be too long
12295 * or the right frame set is found */
12296 while(file_pos > 0 && first_frame - long_stride_length *
12297 n_frames_per_frame_set >= frame)
12299 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12302 fseek(tng_data->input_file,
12305 /* Read block headers first to see what block is found. */
12306 stat = tng_block_header_read(tng_data, block);
12307 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12309 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12310 file_pos, __FILE__, __LINE__);
12311 tng_block_destroy(&block);
12312 return(TNG_CRITICAL);
12315 if(tng_block_read_next(tng_data, block,
12316 TNG_SKIP_HASH) != TNG_SUCCESS)
12318 tng_block_destroy(&block);
12319 return(TNG_CRITICAL);
12322 first_frame = tng_max_i64(frame_set->first_frame, 0);
12323 last_frame = first_frame + frame_set->n_frames - 1;
12324 if(frame >= first_frame && frame <= last_frame)
12326 tng_block_destroy(&block);
12327 return(TNG_SUCCESS);
12331 /* Take medium steps backward until a medium step backward would be too long
12332 * or the right frame set is found */
12333 while(file_pos > 0 && first_frame - medium_stride_length *
12334 n_frames_per_frame_set >= frame)
12336 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12339 fseek(tng_data->input_file,
12342 /* Read block headers first to see what block is found. */
12343 stat = tng_block_header_read(tng_data, block);
12344 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12346 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12347 file_pos, __FILE__, __LINE__);
12348 tng_block_destroy(&block);
12349 return(TNG_CRITICAL);
12352 if(tng_block_read_next(tng_data, block,
12353 TNG_SKIP_HASH) != TNG_SUCCESS)
12355 tng_block_destroy(&block);
12356 return(TNG_CRITICAL);
12359 first_frame = tng_max_i64(frame_set->first_frame, 0);
12360 last_frame = first_frame + frame_set->n_frames - 1;
12361 if(frame >= first_frame && frame <= last_frame)
12363 tng_block_destroy(&block);
12364 return(TNG_SUCCESS);
12368 /* Take one step backward until the right frame set is found */
12369 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12371 file_pos = frame_set->prev_frame_set_file_pos;
12374 fseek(tng_data->input_file,
12377 /* Read block headers first to see what block is found. */
12378 stat = tng_block_header_read(tng_data, block);
12379 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12381 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12382 file_pos, __FILE__, __LINE__);
12383 tng_block_destroy(&block);
12384 return(TNG_CRITICAL);
12387 if(tng_block_read_next(tng_data, block,
12388 TNG_SKIP_HASH) != TNG_SUCCESS)
12390 tng_block_destroy(&block);
12391 return(TNG_CRITICAL);
12394 first_frame = tng_max_i64(frame_set->first_frame, 0);
12395 last_frame = first_frame + frame_set->n_frames - 1;
12396 if(frame >= first_frame && frame <= last_frame)
12398 tng_block_destroy(&block);
12399 return(TNG_SUCCESS);
12403 /* If for some reason the current frame set is not yet found,
12404 * take one step forward until the right frame set is found */
12405 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12407 file_pos = frame_set->next_frame_set_file_pos;
12410 fseek(tng_data->input_file,
12413 /* Read block headers first to see what block is found. */
12414 stat = tng_block_header_read(tng_data, block);
12415 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12417 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12418 file_pos, __FILE__, __LINE__);
12419 tng_block_destroy(&block);
12420 return(TNG_CRITICAL);
12423 if(tng_block_read_next(tng_data, block,
12424 TNG_SKIP_HASH) != TNG_SUCCESS)
12426 tng_block_destroy(&block);
12427 return(TNG_CRITICAL);
12430 first_frame = tng_max_i64(frame_set->first_frame, 0);
12431 last_frame = first_frame + frame_set->n_frames - 1;
12432 if(frame >= first_frame && frame <= last_frame)
12434 tng_block_destroy(&block);
12435 return(TNG_SUCCESS);
12439 tng_block_destroy(&block);
12440 return(TNG_FAILURE);
12443 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12444 (const tng_trajectory_t tng_data,
12445 const tng_trajectory_frame_set_t frame_set,
12450 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12451 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12453 *pos = frame_set->next_frame_set_file_pos;
12455 return(TNG_SUCCESS);
12458 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12459 (const tng_trajectory_t tng_data,
12460 const tng_trajectory_frame_set_t frame_set,
12465 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12466 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12468 *pos = frame_set->prev_frame_set_file_pos;
12470 return(TNG_SUCCESS);
12473 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12474 (const tng_trajectory_t tng_data,
12475 const tng_trajectory_frame_set_t frame_set,
12476 int64_t *first_frame,
12477 int64_t *last_frame)
12481 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12482 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12483 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12485 *first_frame = frame_set->first_frame;
12486 *last_frame = *first_frame + frame_set->n_frames - 1;
12488 return(TNG_SUCCESS);
12491 /** Translate from the particle numbering used in a frame set to the real
12492 * particle numbering - used in the molecule description.
12493 * @param frame_set is the frame_set containing the mappings to use.
12494 * @param local is the index number of the atom in this frame set
12495 * @param real is set to the index of the atom in the molecular system.
12496 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12499 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12500 (const tng_trajectory_frame_set_t frame_set,
12501 const int64_t local,
12504 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12505 tng_particle_mapping_t mapping;
12509 return(TNG_SUCCESS);
12511 for(i = 0; i < n_blocks; i++)
12513 mapping = &frame_set->mappings[i];
12514 first = mapping->num_first_particle;
12515 if(local < first ||
12516 local >= first + mapping->n_particles)
12520 *real = mapping->real_particle_numbers[local-first];
12521 return(TNG_SUCCESS);
12524 return(TNG_FAILURE);
12527 /** Translate from the real particle numbering to the particle numbering
12528 * used in a frame set.
12529 * @param frame_set is the frame_set containing the mappings to use.
12530 * @param real is the index number of the atom in the molecular system.
12531 * @param local is set to the index of the atom in this frame set.
12532 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12535 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12536 (const tng_trajectory_frame_set_t frame_set,
12537 const int64_t real,
12540 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12541 tng_particle_mapping_t mapping;
12545 return(TNG_SUCCESS);
12547 for(i = 0; i < n_blocks; i++)
12549 mapping = &frame_set->mappings[i];
12550 for(j = mapping->n_particles; j--;)
12552 if(mapping->real_particle_numbers[j] == real)
12555 return(TNG_SUCCESS);
12559 return(TNG_FAILURE);
12563 static tng_function_status tng_file_headers_len_get
12564 (tng_trajectory_t tng_data,
12568 tng_gen_block_t block;
12570 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12572 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12574 return(TNG_CRITICAL);
12579 orig_pos = ftell(tng_data->input_file);
12581 if(!tng_data->input_file_len)
12583 fseek(tng_data->input_file, 0, SEEK_END);
12584 tng_data->input_file_len = ftell(tng_data->input_file);
12586 fseek(tng_data->input_file, 0, SEEK_SET);
12588 tng_block_init(&block);
12589 /* Read through the headers of non-trajectory blocks (they come before the
12590 * trajectory blocks in the file) */
12591 while (*len < tng_data->input_file_len &&
12592 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12594 block->id != TNG_TRAJECTORY_FRAME_SET)
12596 *len += block->header_contents_size + block->block_contents_size;
12597 fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12600 fseek(tng_data->input_file, orig_pos, SEEK_SET);
12602 tng_block_destroy(&block);
12604 return(TNG_SUCCESS);
12607 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12608 (tng_trajectory_t tng_data,
12609 const char hash_mode)
12611 int64_t prev_pos = 0;
12612 tng_gen_block_t block;
12614 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12616 tng_data->n_trajectory_frame_sets = 0;
12618 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12620 return(TNG_CRITICAL);
12623 if(!tng_data->input_file_len)
12625 fseek(tng_data->input_file, 0, SEEK_END);
12626 tng_data->input_file_len = ftell(tng_data->input_file);
12628 fseek(tng_data->input_file, 0, SEEK_SET);
12630 tng_block_init(&block);
12631 /* Non trajectory blocks (they come before the trajectory
12632 * blocks in the file) */
12633 while (prev_pos < tng_data->input_file_len &&
12634 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12636 block->id != TNG_TRAJECTORY_FRAME_SET)
12638 tng_block_read_next(tng_data, block, hash_mode);
12639 prev_pos = ftell(tng_data->input_file);
12642 /* Go back if a trajectory block was encountered */
12643 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12645 fseek(tng_data->input_file, prev_pos, SEEK_SET);
12648 tng_block_destroy(&block);
12650 return(TNG_SUCCESS);
12653 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12654 (tng_trajectory_t tng_data,
12655 const char hash_mode)
12658 int64_t len, orig_len, tot_len = 0, data_start_pos;
12659 tng_function_status stat;
12660 tng_gen_block_t block;
12662 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12664 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12666 return(TNG_CRITICAL);
12669 if(tng_data->n_trajectory_frame_sets > 0)
12671 stat = tng_file_headers_len_get(tng_data, &orig_len);
12672 if(stat != TNG_SUCCESS)
12677 tng_block_init(&block);
12678 block->name = malloc(TNG_MAX_STR_LEN);
12681 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12682 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12683 tng_block_destroy(&block);
12684 return(TNG_CRITICAL);
12686 strcpy(block->name, "GENERAL INFO");
12687 tng_block_header_len_calculate(tng_data, block, &len);
12689 tng_general_info_block_len_calculate(tng_data, &len);
12691 strcpy(block->name, "MOLECULES");
12692 tng_block_header_len_calculate(tng_data, block, &len);
12694 tng_molecules_block_len_calculate(tng_data, &len);
12697 for(i = 0; i < tng_data->n_data_blocks; i++)
12699 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12700 tng_block_header_len_calculate(tng_data, block, &len);
12702 tng_data_block_len_calculate(tng_data,
12703 (tng_particle_data_t)&tng_data->non_tr_data[i],
12704 TNG_FALSE, 1, 1, 1, 0,
12705 1, 0, &data_start_pos,
12709 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12711 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12712 tng_block_header_len_calculate(tng_data, block, &len);
12714 tng_data_block_len_calculate(tng_data,
12715 &tng_data->non_tr_particle_data[i],
12716 TNG_TRUE, 1, 1, 1, 0,
12717 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12722 tng_block_destroy(&block);
12724 if(tot_len > orig_len)
12726 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12729 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12732 /* TODO: If there is already frame set data written to this file (e.g. when
12733 * appending to an already existing file we might need to move frame sets to
12734 * the end of the file. */
12736 if(tng_general_info_block_write(tng_data, hash_mode)
12739 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12740 tng_data->input_file_path, __FILE__, __LINE__);
12741 return(TNG_CRITICAL);
12744 if(tng_molecules_block_write(tng_data, hash_mode)
12747 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12748 tng_data->input_file_path, __FILE__, __LINE__);
12749 return(TNG_CRITICAL);
12752 /* FIXME: Currently writing non-trajectory data blocks here.
12753 * Should perhaps be moved. */
12754 tng_block_init(&block);
12755 for(i = 0; i < tng_data->n_data_blocks; i++)
12757 block->id = tng_data->non_tr_data[i].block_id;
12758 tng_data_block_write(tng_data, block,
12762 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12764 block->id = tng_data->non_tr_particle_data[i].block_id;
12765 tng_particle_data_block_write(tng_data, block,
12769 tng_block_destroy(&block);
12771 return(TNG_SUCCESS);
12774 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12775 tng_gen_block_t block,
12776 const char hash_mode)
12778 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12779 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12783 case TNG_TRAJECTORY_FRAME_SET:
12784 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12785 case TNG_PARTICLE_MAPPING:
12786 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12787 case TNG_GENERAL_INFO:
12788 return(tng_general_info_block_read(tng_data, block, hash_mode));
12789 case TNG_MOLECULES:
12790 return(tng_molecules_block_read(tng_data, block, hash_mode));
12792 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12794 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12798 /* Skip to the next block */
12799 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12800 return(TNG_FAILURE);
12805 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12806 (tng_trajectory_t tng_data,
12807 const char hash_mode)
12810 tng_gen_block_t block;
12811 tng_function_status stat;
12813 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12815 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12817 return(TNG_CRITICAL);
12820 file_pos = ftell(tng_data->input_file);
12822 tng_block_init(&block);
12824 if(!tng_data->input_file_len)
12826 fseek(tng_data->input_file, 0, SEEK_END);
12827 tng_data->input_file_len = ftell(tng_data->input_file);
12828 fseek(tng_data->input_file, file_pos, SEEK_SET);
12831 /* Read block headers first to see what block is found. */
12832 stat = tng_block_header_read(tng_data, block);
12833 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12836 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12837 file_pos, __FILE__, __LINE__);
12838 tng_block_destroy(&block);
12839 return(TNG_CRITICAL);
12842 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12844 if(tng_block_read_next(tng_data, block,
12845 hash_mode) == TNG_SUCCESS)
12847 tng_data->n_trajectory_frame_sets++;
12848 file_pos = ftell(tng_data->input_file);
12849 /* Read all blocks until next frame set block */
12850 stat = tng_block_header_read(tng_data, block);
12851 while(file_pos < tng_data->input_file_len &&
12852 stat != TNG_CRITICAL &&
12853 block->id != TNG_TRAJECTORY_FRAME_SET &&
12856 stat = tng_block_read_next(tng_data, block,
12858 if(stat != TNG_CRITICAL)
12860 file_pos = ftell(tng_data->input_file);
12861 if(file_pos < tng_data->input_file_len)
12863 stat = tng_block_header_read(tng_data, block);
12867 if(stat == TNG_CRITICAL)
12869 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12870 file_pos, __FILE__, __LINE__);
12871 tng_block_destroy(&block);
12875 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12877 fseek(tng_data->input_file, file_pos, SEEK_SET);
12881 tng_block_destroy(&block);
12883 return(TNG_SUCCESS);
12887 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12888 (tng_trajectory_t tng_data,
12889 const char hash_mode,
12890 const int64_t block_id)
12893 tng_gen_block_t block;
12894 tng_function_status stat;
12895 int found_flag = 1;
12897 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12899 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12901 return(TNG_CRITICAL);
12904 file_pos = (long)tng_data->current_trajectory_frame_set_input_file_pos;
12908 /* No current frame set. This means that the first frame set must be
12911 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12916 fseek(tng_data->input_file,
12922 return(TNG_FAILURE);
12925 tng_block_init(&block);
12927 if(!tng_data->input_file_len)
12929 fseek(tng_data->input_file, 0, SEEK_END);
12930 tng_data->input_file_len = ftell(tng_data->input_file);
12931 fseek(tng_data->input_file, file_pos, SEEK_SET);
12934 /* Read block headers first to see what block is found. */
12935 stat = tng_block_header_read(tng_data, block);
12936 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12938 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12939 file_pos, __FILE__, __LINE__);
12940 tng_block_destroy(&block);
12941 return(TNG_CRITICAL);
12943 /* If the current frame set had already been read skip its block contents */
12946 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12948 /* Otherwiese read the frame set block */
12951 stat = tng_block_read_next(tng_data, block,
12953 if(stat != TNG_SUCCESS)
12955 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12956 tng_block_destroy(&block);
12960 file_pos = ftell(tng_data->input_file);
12964 /* Read only blocks of the requested ID
12965 * until next frame set block */
12966 stat = tng_block_header_read(tng_data, block);
12967 while(file_pos < tng_data->input_file_len &&
12968 stat != TNG_CRITICAL &&
12969 block->id != TNG_TRAJECTORY_FRAME_SET &&
12972 if(block->id == block_id)
12974 stat = tng_block_read_next(tng_data, block,
12976 if(stat != TNG_CRITICAL)
12978 file_pos = ftell(tng_data->input_file);
12980 if(file_pos < tng_data->input_file_len)
12982 stat = tng_block_header_read(tng_data, block);
12988 file_pos += (long)(block->block_contents_size + block->header_contents_size);
12989 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12990 if(file_pos < tng_data->input_file_len)
12992 stat = tng_block_header_read(tng_data, block);
12996 if(stat == TNG_CRITICAL)
12998 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12999 file_pos, __FILE__, __LINE__);
13000 tng_block_destroy(&block);
13004 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13006 fseek(tng_data->input_file, file_pos, SEEK_SET);
13009 tng_block_destroy(&block);
13013 return(TNG_SUCCESS);
13017 return(TNG_FAILURE);
13021 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
13022 (tng_trajectory_t tng_data,
13023 const char hash_mode)
13027 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13029 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13031 return(TNG_CRITICAL);
13034 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13036 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13038 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13043 fseek(tng_data->input_file,
13049 return(TNG_FAILURE);
13052 return(tng_frame_set_read(tng_data, hash_mode));
13055 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13056 (tng_trajectory_t tng_data,
13057 const char hash_mode,
13058 const int64_t block_id)
13061 tng_gen_block_t block;
13062 tng_function_status stat;
13064 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13066 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
13068 return(TNG_CRITICAL);
13071 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
13073 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13075 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13080 fseek(tng_data->input_file,
13086 return(TNG_FAILURE);
13089 tng_block_init(&block);
13091 if(!tng_data->input_file_len)
13093 fseek(tng_data->input_file, 0, SEEK_END);
13094 tng_data->input_file_len = ftell(tng_data->input_file);
13095 fseek(tng_data->input_file, file_pos, SEEK_SET);
13098 /* Read block headers first to see what block is found. */
13099 stat = tng_block_header_read(tng_data, block);
13100 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13102 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13103 file_pos, __FILE__, __LINE__);
13104 tng_block_destroy(&block);
13105 return(TNG_CRITICAL);
13108 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13110 if(tng_block_read_next(tng_data, block,
13111 hash_mode) == TNG_SUCCESS)
13113 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13116 tng_block_destroy(&block);
13121 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13122 const char hash_mode)
13125 tng_gen_block_t block;
13126 tng_trajectory_frame_set_t frame_set;
13127 tng_function_status stat;
13129 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13131 frame_set = &tng_data->current_trajectory_frame_set;
13133 if(frame_set->n_written_frames == frame_set->n_frames)
13135 return(TNG_SUCCESS);
13138 tng_data->current_trajectory_frame_set_output_file_pos =
13139 ftell(tng_data->output_file);
13140 tng_data->last_trajectory_frame_set_output_file_pos =
13141 tng_data->current_trajectory_frame_set_output_file_pos;
13143 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13145 return(TNG_FAILURE);
13148 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13150 tng_data->first_trajectory_frame_set_output_file_pos =
13151 tng_data->current_trajectory_frame_set_output_file_pos;
13154 tng_block_init(&block);
13156 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13158 tng_block_destroy(&block);
13159 return(TNG_FAILURE);
13162 /* Write non-particle data blocks */
13163 for(i = 0; i<frame_set->n_data_blocks; i++)
13165 block->id = frame_set->tr_data[i].block_id;
13166 tng_data_block_write(tng_data, block, i, hash_mode);
13168 /* Write the mapping blocks and particle data blocks*/
13169 if(frame_set->n_mapping_blocks)
13171 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13173 block->id = TNG_PARTICLE_MAPPING;
13174 if(frame_set->mappings[i].n_particles > 0)
13176 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13177 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13179 block->id = frame_set->tr_particle_data[j].block_id;
13180 tng_particle_data_block_write(tng_data, block,
13181 j, &frame_set->mappings[i],
13189 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13191 block->id = frame_set->tr_particle_data[i].block_id;
13192 tng_particle_data_block_write(tng_data, block,
13198 /* Update pointers in the general info block */
13199 stat = tng_header_pointers_update(tng_data, hash_mode);
13201 if(stat == TNG_SUCCESS)
13203 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13206 tng_block_destroy(&block);
13208 frame_set->n_unwritten_frames = 0;
13210 fflush(tng_data->output_file);
13215 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13216 (tng_trajectory_t tng_data,
13217 const char hash_mode)
13219 tng_trajectory_frame_set_t frame_set;
13221 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13223 frame_set = &tng_data->current_trajectory_frame_set;
13225 if(frame_set->n_unwritten_frames == 0)
13227 return(TNG_SUCCESS);
13229 frame_set->n_frames = frame_set->n_unwritten_frames;
13231 return(tng_frame_set_write(tng_data, hash_mode));
13234 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13235 (tng_trajectory_t tng_data,
13236 const int64_t first_frame,
13237 const int64_t n_frames)
13239 tng_gen_block_t block;
13240 tng_trajectory_frame_set_t frame_set;
13241 FILE *temp = tng_data->input_file;
13244 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13245 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13246 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13248 frame_set = &tng_data->current_trajectory_frame_set;
13250 curr_pos = ftell(tng_data->output_file);
13254 tng_file_headers_write(tng_data, TNG_USE_HASH);
13257 /* Set pointer to previous frame set to the one that was loaded
13259 * FIXME: This is a bit risky. If they are not added in order
13260 * it will be wrong. */
13261 if(tng_data->n_trajectory_frame_sets)
13263 frame_set->prev_frame_set_file_pos =
13264 tng_data->current_trajectory_frame_set_output_file_pos;
13267 tng_data->current_trajectory_frame_set_output_file_pos =
13268 ftell(tng_data->output_file);
13270 tng_data->n_trajectory_frame_sets++;
13272 /* Set the medium range pointers */
13273 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13275 frame_set->medium_stride_prev_frame_set_file_pos =
13276 tng_data->first_trajectory_frame_set_output_file_pos;
13278 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13280 /* FIXME: Currently only working if the previous frame set has its
13281 * medium stride pointer already set. This might need some fixing. */
13282 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13283 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13285 tng_block_init(&block);
13286 tng_data->input_file = tng_data->output_file;
13288 curr_pos = ftell(tng_data->output_file);
13289 fseek(tng_data->output_file,
13290 (long)frame_set->medium_stride_prev_frame_set_file_pos,
13293 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13295 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13296 __FILE__, __LINE__);
13297 tng_data->input_file = temp;
13298 tng_block_destroy(&block);
13299 return(TNG_CRITICAL);
13302 /* Read the next frame set from the previous frame set and one
13303 * medium stride step back */
13304 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
13305 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13306 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13307 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13308 1, tng_data->output_file) == 0)
13310 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13311 tng_data->input_file = temp;
13312 tng_block_destroy(&block);
13313 return(TNG_CRITICAL);
13316 if(tng_data->input_endianness_swap_func_64)
13318 if(tng_data->input_endianness_swap_func_64(tng_data,
13319 &frame_set->medium_stride_prev_frame_set_file_pos)
13322 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13323 __FILE__, __LINE__);
13327 tng_block_destroy(&block);
13329 /* Set the long range pointers */
13330 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13332 frame_set->long_stride_prev_frame_set_file_pos =
13333 tng_data->first_trajectory_frame_set_output_file_pos;
13335 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13337 /* FIXME: Currently only working if the previous frame set has its
13338 * long stride pointer already set. This might need some fixing. */
13339 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13340 frame_set->long_stride_prev_frame_set_file_pos != 0)
13342 tng_block_init(&block);
13343 tng_data->input_file = tng_data->output_file;
13345 fseek(tng_data->output_file,
13346 (long)frame_set->long_stride_prev_frame_set_file_pos,
13349 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13351 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13352 __FILE__, __LINE__);
13353 tng_data->input_file = temp;
13354 tng_block_destroy(&block);
13355 return(TNG_CRITICAL);
13358 /* Read the next frame set from the previous frame set and one
13359 * long stride step back */
13360 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
13361 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13363 tng_block_destroy(&block);
13365 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13366 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13367 1, tng_data->output_file) == 0)
13369 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13370 tng_data->input_file = temp;
13371 return(TNG_CRITICAL);
13374 if(tng_data->input_endianness_swap_func_64)
13376 if(tng_data->input_endianness_swap_func_64(tng_data,
13377 &frame_set->long_stride_prev_frame_set_file_pos)
13380 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13381 __FILE__, __LINE__);
13388 tng_data->input_file = temp;
13389 fseek(tng_data->output_file, (long)curr_pos, SEEK_SET);
13393 frame_set->first_frame = first_frame;
13394 frame_set->n_frames = n_frames;
13395 frame_set->n_written_frames = 0;
13396 frame_set->n_unwritten_frames = 0;
13397 frame_set->first_frame_time = -1;
13399 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13400 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13402 tng_data->first_trajectory_frame_set_output_file_pos =
13403 tng_data->current_trajectory_frame_set_output_file_pos;
13405 /* FIXME: Should check the frame number instead of the file_pos,
13406 * in case frame sets are not in order */
13407 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13408 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13409 tng_data->last_trajectory_frame_set_output_file_pos <
13410 tng_data->current_trajectory_frame_set_output_file_pos)
13412 tng_data->last_trajectory_frame_set_output_file_pos =
13413 tng_data->current_trajectory_frame_set_output_file_pos;
13416 return(TNG_SUCCESS);
13419 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13420 (tng_trajectory_t tng_data,
13421 const int64_t first_frame,
13422 const int64_t n_frames,
13423 const double first_frame_time)
13425 tng_function_status stat;
13427 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13428 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13429 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13430 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13433 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13434 if(stat != TNG_SUCCESS)
13438 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13443 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13444 (tng_trajectory_t tng_data,
13445 const double first_frame_time)
13447 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13448 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13450 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13452 return(TNG_SUCCESS);
13455 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13456 (const tng_trajectory_t tng_data,
13459 long file_pos, next_frame_set_file_pos;
13460 tng_gen_block_t block;
13461 tng_function_status stat;
13463 tng_trajectory_frame_set_t frame_set;
13465 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13466 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13467 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13469 file_pos = ftell(tng_data->input_file);
13471 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13473 next_frame_set_file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13477 frame_set = &tng_data->current_trajectory_frame_set;
13478 next_frame_set_file_pos = (long)frame_set->next_frame_set_file_pos;
13481 if(next_frame_set_file_pos <= 0)
13483 return(TNG_FAILURE);
13486 fseek(tng_data->input_file, (long)next_frame_set_file_pos, SEEK_SET);
13487 /* Read block headers first to see that a frame set block is found. */
13488 tng_block_init(&block);
13489 stat = tng_block_header_read(tng_data, block);
13490 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13492 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13493 file_pos, __FILE__, __LINE__);
13494 return(TNG_CRITICAL);
13496 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13498 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13500 tng_block_destroy(&block);
13502 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13504 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13505 __FILE__, __LINE__);
13506 return(TNG_CRITICAL);
13508 fseek(tng_data->input_file, file_pos, SEEK_SET);
13510 return(TNG_SUCCESS);
13513 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13514 (tng_trajectory_t tng_data,
13516 const char *block_name,
13517 const char datatype,
13518 const char block_type_flag,
13520 const int64_t n_values_per_frame,
13521 int64_t stride_length,
13522 const int64_t codec_id,
13525 int i, j, size, len;
13526 tng_trajectory_frame_set_t frame_set;
13527 tng_non_particle_data_t data;
13528 char **first_dim_values;
13529 char *new_data_c=new_data;
13530 int64_t n_frames_div;
13532 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13533 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13534 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13536 frame_set = &tng_data->current_trajectory_frame_set;
13538 if(stride_length <= 0)
13543 /* If the block does not exist, create it */
13544 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13546 if(tng_data_block_create(tng_data, block_type_flag) !=
13549 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13550 __FILE__, __LINE__);
13551 return(TNG_CRITICAL);
13553 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13555 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13559 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13561 data->block_id = id;
13563 data->block_name = malloc(strlen(block_name) + 1);
13564 if(!data->block_name)
13566 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13567 (int)strlen(block_name)+1, __FILE__, __LINE__);
13568 return(TNG_CRITICAL);
13570 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13573 /* FIXME: Memory leak from strings. */
13575 data->last_retrieved_frame = -1;
13578 data->datatype = datatype;
13579 data->stride_length = tng_max_i64(stride_length, 1);
13580 data->n_values_per_frame = n_values_per_frame;
13581 data->n_frames = n_frames;
13582 data->codec_id = codec_id;
13583 data->compression_multiplier = 1.0;
13584 /* FIXME: This can cause problems. */
13585 data->first_frame_with_data = frame_set->first_frame;
13589 case TNG_FLOAT_DATA:
13590 size = sizeof(float);
13593 size = sizeof(int64_t);
13595 case TNG_DOUBLE_DATA:
13597 size = sizeof(double);
13603 /* Allocate memory */
13604 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13605 n_values_per_frame) !=
13608 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13609 __FILE__, __LINE__);
13610 return(TNG_CRITICAL);
13613 if(n_frames > frame_set->n_unwritten_frames)
13615 frame_set->n_unwritten_frames = n_frames;
13618 n_frames_div = (n_frames % stride_length) ?
13619 n_frames / stride_length + 1:
13620 n_frames / stride_length;
13622 if(datatype == TNG_CHAR_DATA)
13624 for(i = 0; i < n_frames_div; i++)
13626 first_dim_values = data->strings[i];
13627 for(j = 0; j < n_values_per_frame; j++)
13629 len = tng_min_i((int)strlen(new_data_c) + 1,
13631 if(first_dim_values[j])
13633 free(first_dim_values[j]);
13635 first_dim_values[j] = malloc(len);
13636 if(!first_dim_values[j])
13638 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13639 len, __FILE__, __LINE__);
13640 return(TNG_CRITICAL);
13642 strncpy(first_dim_values[j],
13650 memcpy(data->values, new_data, size * n_frames_div *
13651 n_values_per_frame);
13655 return(TNG_SUCCESS);
13658 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13659 (tng_trajectory_t tng_data,
13661 const char *block_name,
13662 const char datatype,
13663 const char block_type_flag,
13665 const int64_t n_values_per_frame,
13666 int64_t stride_length,
13667 const int64_t num_first_particle,
13668 const int64_t n_particles,
13669 const int64_t codec_id,
13674 int64_t tot_n_particles, n_frames_div;
13675 char ***first_dim_values, **second_dim_values;
13676 tng_trajectory_frame_set_t frame_set;
13677 tng_particle_data_t data;
13678 char *new_data_c=new_data;
13680 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13681 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13682 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13683 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13684 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13687 frame_set = &tng_data->current_trajectory_frame_set;
13689 if(stride_length <= 0)
13694 /* If the block does not exist, create it */
13695 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13697 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13700 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13701 __FILE__, __LINE__);
13702 return(TNG_CRITICAL);
13704 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13706 data = &frame_set->tr_particle_data[frame_set->
13707 n_particle_data_blocks - 1];
13711 data = &tng_data->non_tr_particle_data[tng_data->
13712 n_particle_data_blocks - 1];
13714 data->block_id = id;
13716 data->block_name = malloc(strlen(block_name) + 1);
13717 if(!data->block_name)
13719 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13720 (int)strlen(block_name)+1, __FILE__, __LINE__);
13721 return(TNG_CRITICAL);
13723 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13725 data->datatype = datatype;
13728 /* FIXME: Memory leak from strings. */
13730 data->last_retrieved_frame = -1;
13733 data->stride_length = tng_max_i64(stride_length, 1);
13734 data->n_values_per_frame = n_values_per_frame;
13735 data->n_frames = n_frames;
13736 data->codec_id = codec_id;
13737 data->compression_multiplier = 1.0;
13738 /* FIXME: This can cause problems. */
13739 data->first_frame_with_data = frame_set->first_frame;
13741 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13743 tot_n_particles = frame_set->n_particles;
13747 tot_n_particles = tng_data->n_particles;
13750 /* If data values are supplied add that data to the data block. */
13753 /* Allocate memory */
13754 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13755 stride_length, tot_n_particles,
13756 n_values_per_frame) !=
13759 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13760 __FILE__, __LINE__);
13761 return(TNG_CRITICAL);
13764 if(n_frames > frame_set->n_unwritten_frames)
13766 frame_set->n_unwritten_frames = n_frames;
13769 n_frames_div = (n_frames % stride_length) ?
13770 n_frames / stride_length + 1:
13771 n_frames / stride_length;
13773 if(datatype == TNG_CHAR_DATA)
13775 for(i = 0; i < n_frames_div; i++)
13777 first_dim_values = data->strings[i];
13778 for(j = num_first_particle; j < num_first_particle + n_particles;
13781 second_dim_values = first_dim_values[j];
13782 for(k = 0; k < n_values_per_frame; k++)
13784 len = tng_min_i((int)strlen(new_data_c) + 1,
13786 if(second_dim_values[k])
13788 free(second_dim_values[k]);
13790 second_dim_values[k] = malloc(len);
13791 if(!second_dim_values[k])
13793 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13794 len, __FILE__, __LINE__);
13795 return(TNG_CRITICAL);
13797 strncpy(second_dim_values[k],
13809 size = sizeof(int64_t);
13811 case TNG_FLOAT_DATA:
13812 size = sizeof(float);
13814 case TNG_DOUBLE_DATA:
13816 size = sizeof(double);
13819 memcpy(data->values, new_data, size * n_frames_div *
13820 n_particles * n_values_per_frame);
13824 return(TNG_SUCCESS);
13827 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13828 (tng_trajectory_t tng_data,
13834 tng_trajectory_frame_set_t frame_set;
13835 tng_function_status stat;
13836 tng_particle_data_t p_data;
13837 tng_non_particle_data_t np_data;
13838 int block_type = -1;
13840 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13841 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13843 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13845 p_data = &tng_data->non_tr_particle_data[i];
13846 if(p_data->block_id == block_id)
13848 strncpy(name, p_data->block_name, max_len);
13849 name[max_len - 1] = '\0';
13850 return(TNG_SUCCESS);
13853 for(i = 0; i < tng_data->n_data_blocks; i++)
13855 np_data = &tng_data->non_tr_data[i];
13856 if(np_data->block_id == block_id)
13858 strncpy(name, np_data->block_name, max_len);
13859 name[max_len - 1] = '\0';
13860 return(TNG_SUCCESS);
13864 frame_set = &tng_data->current_trajectory_frame_set;
13866 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13867 if(stat == TNG_SUCCESS)
13869 block_type = TNG_PARTICLE_BLOCK_DATA;
13873 stat = tng_data_find(tng_data, block_id, &np_data);
13874 if(stat == TNG_SUCCESS)
13876 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13880 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13881 if(stat != TNG_SUCCESS)
13885 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13886 if(stat == TNG_SUCCESS)
13888 block_type = TNG_PARTICLE_BLOCK_DATA;
13892 stat = tng_data_find(tng_data, block_id, &np_data);
13893 if(stat == TNG_SUCCESS)
13895 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13900 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13902 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13904 p_data = &frame_set->tr_particle_data[i];
13905 if(p_data->block_id == block_id)
13907 strncpy(name, p_data->block_name, max_len);
13908 name[max_len - 1] = '\0';
13909 return(TNG_SUCCESS);
13913 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13915 for(i = 0; i < frame_set->n_data_blocks; i++)
13917 np_data = &frame_set->tr_data[i];
13918 if(np_data->block_id == block_id)
13920 strncpy(name, np_data->block_name, max_len);
13921 name[max_len - 1] = '\0';
13922 return(TNG_SUCCESS);
13927 return(TNG_FAILURE);
13930 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13931 (const tng_trajectory_t tng_data,
13933 int *block_dependency)
13936 tng_function_status stat;
13937 tng_particle_data_t p_data;
13938 tng_non_particle_data_t np_data;
13940 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13941 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13943 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13945 p_data = &tng_data->non_tr_particle_data[i];
13946 if(p_data->block_id == block_id)
13948 *block_dependency = TNG_PARTICLE_DEPENDENT;
13949 return(TNG_SUCCESS);
13952 for(i = 0; i < tng_data->n_data_blocks; i++)
13954 np_data = &tng_data->non_tr_data[i];
13955 if(np_data->block_id == block_id)
13957 *block_dependency = 0;
13958 return(TNG_SUCCESS);
13962 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13963 if(stat == TNG_SUCCESS)
13965 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13966 return(TNG_SUCCESS);
13970 stat = tng_data_find(tng_data, block_id, &np_data);
13971 if(stat == TNG_SUCCESS)
13973 *block_dependency = TNG_FRAME_DEPENDENT;
13974 return(TNG_SUCCESS);
13978 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13979 if(stat != TNG_SUCCESS)
13983 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13984 if(stat == TNG_SUCCESS)
13986 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13987 return(TNG_SUCCESS);
13991 stat = tng_data_find(tng_data, block_id, &np_data);
13992 if(stat == TNG_SUCCESS)
13994 *block_dependency = TNG_FRAME_DEPENDENT;
13995 return(TNG_SUCCESS);
14001 return(TNG_FAILURE);
14004 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
14005 (const tng_trajectory_t tng_data,
14007 int64_t *n_values_per_frame)
14010 tng_function_status stat;
14011 tng_particle_data_t p_data;
14012 tng_non_particle_data_t np_data;
14014 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14015 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14017 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
14019 p_data = &tng_data->non_tr_particle_data[i];
14020 if(p_data->block_id == block_id)
14022 *n_values_per_frame = p_data->n_values_per_frame;
14023 return(TNG_SUCCESS);
14026 for(i = 0; i < tng_data->n_data_blocks; i++)
14028 np_data = &tng_data->non_tr_data[i];
14029 if(np_data->block_id == block_id)
14031 *n_values_per_frame = np_data->n_values_per_frame;
14032 return(TNG_SUCCESS);
14036 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14037 if(stat == TNG_SUCCESS)
14039 *n_values_per_frame = p_data->n_values_per_frame;
14040 return(TNG_SUCCESS);
14044 stat = tng_data_find(tng_data, block_id, &np_data);
14045 if(stat == TNG_SUCCESS)
14047 *n_values_per_frame = np_data->n_values_per_frame;
14048 return(TNG_SUCCESS);
14052 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14053 if(stat != TNG_SUCCESS)
14057 stat = tng_particle_data_find(tng_data, block_id, &p_data);
14058 if(stat == TNG_SUCCESS)
14060 *n_values_per_frame = p_data->n_values_per_frame;
14061 return(TNG_SUCCESS);
14065 stat = tng_data_find(tng_data, block_id, &np_data);
14066 if(stat == TNG_SUCCESS)
14068 *n_values_per_frame = np_data->n_values_per_frame;
14069 return(TNG_SUCCESS);
14075 return(TNG_FAILURE);
14078 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14079 (tng_trajectory_t tng_data,
14080 const int64_t frame_nr,
14081 const int64_t block_id,
14082 const void *values,
14083 const char hash_mode)
14085 int64_t header_pos, file_pos;
14086 int64_t output_file_len, n_values_per_frame, size, contents_size;
14087 int64_t header_size, temp_first, temp_last;
14088 int64_t i, last_frame;
14090 tng_gen_block_t block;
14091 tng_trajectory_frame_set_t frame_set;
14092 FILE *temp = tng_data->input_file;
14093 struct tng_non_particle_data data;
14094 tng_function_status stat;
14095 char dependency, sparse_data, datatype;
14098 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14099 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14100 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14102 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14104 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14105 __FILE__, __LINE__);
14106 return(TNG_CRITICAL);
14109 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14110 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14111 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14112 tng_data->first_trajectory_frame_set_input_file_pos =
14113 tng_data->first_trajectory_frame_set_output_file_pos;
14114 tng_data->last_trajectory_frame_set_input_file_pos =
14115 tng_data->last_trajectory_frame_set_output_file_pos;
14116 tng_data->current_trajectory_frame_set_input_file_pos =
14117 tng_data->current_trajectory_frame_set_output_file_pos;
14119 tng_data->input_file = tng_data->output_file;
14121 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14123 frame_set = &tng_data->current_trajectory_frame_set;
14125 if(stat != TNG_SUCCESS)
14127 last_frame = frame_set->first_frame +
14128 frame_set->n_frames - 1;
14129 /* If the wanted frame would be in the frame set after the last
14130 * frame set create a new frame set. */
14131 if(stat == TNG_FAILURE &&
14132 last_frame < frame_nr)
14133 /* (last_frame < frame_nr &&
14134 tng_data->current_trajectory_frame_set.first_frame +
14135 tng_data->frame_set_n_frames >= frame_nr))*/
14137 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14139 last_frame = frame_nr - 1;
14141 tng_frame_set_new(tng_data,
14143 tng_data->frame_set_n_frames);
14144 file_pos = ftell(tng_data->output_file);
14145 fseek(tng_data->output_file, 0, SEEK_END);
14146 output_file_len = ftell(tng_data->output_file);
14147 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14149 /* Read mapping blocks from the last frame set */
14150 tng_block_init(&block);
14152 stat = tng_block_header_read(tng_data, block);
14153 while(file_pos < output_file_len &&
14154 stat != TNG_CRITICAL &&
14155 block->id != TNG_TRAJECTORY_FRAME_SET &&
14158 if(block->id == TNG_PARTICLE_MAPPING)
14160 tng_trajectory_mapping_block_read(tng_data, block,
14165 fseek(tng_data->output_file, (long)block->block_contents_size,
14168 file_pos = ftell(tng_data->output_file);
14169 if(file_pos < output_file_len)
14171 stat = tng_block_header_read(tng_data, block);
14175 tng_block_destroy(&block);
14176 /* Write the frame set to disk */
14177 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14179 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14180 return(TNG_CRITICAL);
14185 tng_data->input_file = temp;
14186 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14187 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14188 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14193 tng_block_init(&block);
14195 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14197 fseek(tng_data->output_file, 0, SEEK_END);
14198 output_file_len = ftell(tng_data->output_file);
14199 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14201 /* Read past the frame set block first */
14202 stat = tng_block_header_read(tng_data, block);
14203 if(stat == TNG_CRITICAL)
14205 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14206 file_pos, __FILE__, __LINE__);
14207 tng_block_destroy(&block);
14208 tng_data->input_file = temp;
14210 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14211 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14212 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14215 fseek(tng_data->output_file, (long)block->block_contents_size,
14218 /* Read all block headers until next frame set block or
14219 * until the wanted block id is found */
14220 stat = tng_block_header_read(tng_data, block);
14221 while(file_pos < output_file_len &&
14222 stat != TNG_CRITICAL &&
14223 block->id != block_id &&
14224 block->id != TNG_TRAJECTORY_FRAME_SET &&
14227 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
14228 file_pos = ftell(tng_data->output_file);
14229 if(file_pos < output_file_len)
14231 stat = tng_block_header_read(tng_data, block);
14234 if(stat == TNG_CRITICAL)
14236 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14237 file_pos, __FILE__, __LINE__);
14238 tng_block_destroy(&block);
14239 tng_data->input_file = temp;
14240 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14241 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14242 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14246 contents_size = block->block_contents_size;
14247 header_size = block->header_contents_size;
14249 header_pos = ftell(tng_data->output_file) - header_size;
14250 frame_set = &tng_data->current_trajectory_frame_set;
14252 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14254 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14255 tng_block_destroy(&block);
14256 return(TNG_CRITICAL);
14258 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14260 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14261 tng_block_destroy(&block);
14262 return(TNG_CRITICAL);
14264 data.datatype = datatype;
14266 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14267 (dependency & TNG_PARTICLE_DEPENDENT))
14269 tng_block_destroy(&block);
14270 tng_data->input_file = temp;
14272 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14273 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14274 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14275 return(TNG_FAILURE);
14278 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14280 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14281 tng_block_destroy(&block);
14282 return(TNG_CRITICAL);
14285 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14286 tng_data->input_file) == 0)
14288 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14289 tng_block_destroy(&block);
14290 return(TNG_CRITICAL);
14292 if(tng_data->output_endianness_swap_func_64)
14294 if(tng_data->output_endianness_swap_func_64(tng_data,
14295 &data.n_values_per_frame)
14298 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14299 __FILE__, __LINE__);
14303 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14304 tng_data->input_file) == 0)
14306 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14307 tng_block_destroy(&block);
14308 return(TNG_CRITICAL);
14310 if(tng_data->output_endianness_swap_func_64)
14312 if(tng_data->output_endianness_swap_func_64(tng_data,
14316 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14317 __FILE__, __LINE__);
14321 if(data.codec_id != TNG_UNCOMPRESSED)
14323 if(fread(&data.compression_multiplier,
14324 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14327 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14328 tng_block_destroy(&block);
14329 return(TNG_CRITICAL);
14331 if(tng_data->output_endianness_swap_func_64)
14333 if(tng_data->output_endianness_swap_func_64(tng_data,
14334 (int64_t *)&data.compression_multiplier)
14337 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14338 __FILE__, __LINE__);
14344 data.compression_multiplier = 1;
14349 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14350 1, tng_data->input_file) == 0)
14352 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14353 tng_block_destroy(&block);
14354 return(TNG_CRITICAL);
14356 if(tng_data->output_endianness_swap_func_64)
14358 if(tng_data->output_endianness_swap_func_64(tng_data,
14359 &data.first_frame_with_data)
14362 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14363 __FILE__, __LINE__);
14367 if(fread(&data.stride_length, sizeof(data.stride_length),
14368 1, tng_data->input_file) == 0)
14370 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14371 tng_block_destroy(&block);
14372 return(TNG_CRITICAL);
14374 if(tng_data->output_endianness_swap_func_64)
14376 if(tng_data->output_endianness_swap_func_64(tng_data,
14377 &data.stride_length)
14380 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14381 __FILE__, __LINE__);
14387 data.first_frame_with_data = 0;
14388 data.stride_length = 1;
14390 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14392 tng_data->input_file = temp;
14394 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14395 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14396 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14398 switch(data.datatype)
14400 case(TNG_INT_DATA):
14401 size = sizeof(int64_t);
14403 case(TNG_FLOAT_DATA):
14404 size = sizeof(float);
14406 case(TNG_DOUBLE_DATA):
14407 size = sizeof(double);
14410 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14412 tng_block_destroy(&block);
14413 return(TNG_FAILURE);
14416 n_values_per_frame = data.n_values_per_frame;
14418 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14419 data.first_frame_with_data)) /
14420 data.stride_length;
14421 file_pos *= size * n_values_per_frame;
14423 if(file_pos > contents_size)
14425 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14427 tng_block_destroy(&block);
14428 return(TNG_FAILURE);
14431 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14433 /* If the endianness is not big endian the data needs to be swapped */
14434 if((data.datatype == TNG_INT_DATA ||
14435 data.datatype == TNG_DOUBLE_DATA) &&
14436 tng_data->output_endianness_swap_func_64)
14438 copy = malloc(n_values_per_frame * size);
14439 memcpy(copy, values, n_values_per_frame * size);
14440 for(i = 0; i < n_values_per_frame; i++)
14442 if(tng_data->output_endianness_swap_func_64(tng_data,
14446 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14447 __FILE__, __LINE__);
14450 fwrite(copy, n_values_per_frame, size,
14451 tng_data->output_file);
14454 else if(data.datatype == TNG_FLOAT_DATA &&
14455 tng_data->output_endianness_swap_func_32)
14457 copy = malloc(n_values_per_frame * size);
14458 memcpy(copy, values, n_values_per_frame * size);
14459 for(i = 0; i < n_values_per_frame; i++)
14461 if(tng_data->output_endianness_swap_func_32(tng_data,
14465 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14466 __FILE__, __LINE__);
14469 fwrite(copy, n_values_per_frame, size,
14470 tng_data->output_file);
14476 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14479 fflush(tng_data->output_file);
14481 /* Update the number of written frames in the frame set. */
14482 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14484 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14487 /* If the last frame has been written update the hash */
14488 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14489 data.first_frame_with_data) >=
14490 frame_set->n_frames)
14492 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14496 tng_block_destroy(&block);
14498 return(TNG_SUCCESS);
14501 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14502 (tng_trajectory_t tng_data,
14503 const int64_t frame_nr,
14504 const int64_t block_id,
14505 const int64_t val_first_particle,
14506 const int64_t val_n_particles,
14507 const void *values,
14508 const char hash_mode)
14510 int64_t header_pos, file_pos, tot_n_particles;
14511 int64_t output_file_len, n_values_per_frame, size, contents_size;
14512 int64_t header_size, temp_first, temp_last;
14513 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14514 int64_t i, last_frame;
14516 tng_gen_block_t block;
14517 tng_trajectory_frame_set_t frame_set;
14518 FILE *temp = tng_data->input_file;
14519 struct tng_particle_data data;
14520 tng_function_status stat;
14521 tng_particle_mapping_t mapping;
14522 char dependency, sparse_data, datatype;
14525 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14526 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14527 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14528 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14529 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14531 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14533 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14534 __FILE__, __LINE__);
14535 return(TNG_CRITICAL);
14538 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14539 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14540 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14541 tng_data->first_trajectory_frame_set_input_file_pos =
14542 tng_data->first_trajectory_frame_set_output_file_pos;
14543 tng_data->last_trajectory_frame_set_input_file_pos =
14544 tng_data->last_trajectory_frame_set_output_file_pos;
14545 tng_data->current_trajectory_frame_set_input_file_pos =
14546 tng_data->current_trajectory_frame_set_output_file_pos;
14548 tng_data->input_file = tng_data->output_file;
14550 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14552 frame_set = &tng_data->current_trajectory_frame_set;
14554 if(stat != TNG_SUCCESS)
14556 last_frame = frame_set->first_frame +
14557 frame_set->n_frames - 1;
14558 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14560 /* If the wanted frame would be in the frame set after the last
14561 * frame set create a new frame set. */
14562 if(stat == TNG_FAILURE &&
14563 (last_frame < frame_nr &&
14564 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14566 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14568 last_frame = frame_nr - 1;
14570 tng_frame_set_new(tng_data,
14572 tng_data->frame_set_n_frames);
14574 file_pos = ftell(tng_data->output_file);
14575 fseek(tng_data->output_file, 0, SEEK_END);
14576 output_file_len = ftell(tng_data->output_file);
14577 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14579 /* Read mapping blocks from the last frame set */
14580 tng_block_init(&block);
14582 stat = tng_block_header_read(tng_data, block);
14583 while(file_pos < output_file_len &&
14584 stat != TNG_CRITICAL &&
14585 block->id != TNG_TRAJECTORY_FRAME_SET &&
14588 if(block->id == TNG_PARTICLE_MAPPING)
14590 tng_trajectory_mapping_block_read(tng_data, block,
14595 fseek(tng_data->output_file, (long)block->block_contents_size,
14598 file_pos = ftell(tng_data->output_file);
14599 if(file_pos < output_file_len)
14601 stat = tng_block_header_read(tng_data, block);
14605 tng_block_destroy(&block);
14606 /* Write the frame set to disk */
14607 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14609 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14615 tng_data->input_file = temp;
14616 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14617 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14618 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14624 tng_block_init(&block);
14626 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14628 fseek(tng_data->output_file, 0, SEEK_END);
14629 output_file_len = ftell(tng_data->output_file);
14630 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14632 /* Read past the frame set block first */
14633 stat = tng_block_header_read(tng_data, block);
14634 if(stat == TNG_CRITICAL)
14636 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14637 file_pos, __FILE__, __LINE__);
14638 tng_block_destroy(&block);
14639 tng_data->input_file = temp;
14641 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14642 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14643 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14646 fseek(tng_data->output_file, (long)block->block_contents_size,
14649 if(tng_data->var_num_atoms_flag)
14651 tot_n_particles = frame_set->n_particles;
14655 tot_n_particles = tng_data->n_particles;
14658 if(val_n_particles < tot_n_particles)
14660 mapping_block_end_pos = -1;
14661 /* Read all mapping blocks to find the right place to put the data */
14662 stat = tng_block_header_read(tng_data, block);
14663 while(file_pos < output_file_len &&
14664 stat != TNG_CRITICAL &&
14665 block->id != TNG_TRAJECTORY_FRAME_SET &&
14668 if(block->id == TNG_PARTICLE_MAPPING)
14670 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14674 fseek(tng_data->output_file, (long)block->block_contents_size,
14677 file_pos = ftell(tng_data->output_file);
14678 if(block->id == TNG_PARTICLE_MAPPING)
14680 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14681 if(val_first_particle >= mapping->num_first_particle &&
14682 val_first_particle < mapping->num_first_particle +
14683 mapping->n_particles &&
14684 val_first_particle + val_n_particles <=
14685 mapping->num_first_particle + mapping->n_particles)
14687 mapping_block_end_pos = file_pos;
14690 if(file_pos < output_file_len)
14692 stat = tng_block_header_read(tng_data, block);
14695 if(stat == TNG_CRITICAL)
14697 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14698 file_pos, __FILE__, __LINE__);
14699 tng_block_destroy(&block);
14700 tng_data->input_file = temp;
14702 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14703 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14704 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14707 if(mapping_block_end_pos < 0)
14709 tng_block_destroy(&block);
14710 tng_data->input_file = temp;
14712 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14713 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14714 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14715 return(TNG_FAILURE);
14717 fseek(tng_data->output_file, (long)mapping_block_end_pos, SEEK_SET);
14720 /* Read all block headers until next frame set block or
14721 * until the wanted block id is found */
14722 stat = tng_block_header_read(tng_data, block);
14723 while(file_pos < output_file_len &&
14724 stat != TNG_CRITICAL &&
14725 block->id != block_id &&
14726 block->id != TNG_PARTICLE_MAPPING &&
14727 block->id != TNG_TRAJECTORY_FRAME_SET &&
14730 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
14731 file_pos = ftell(tng_data->output_file);
14732 if(file_pos < output_file_len)
14734 stat = tng_block_header_read(tng_data, block);
14737 if(stat == TNG_CRITICAL)
14739 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14740 file_pos, __FILE__, __LINE__);
14741 tng_block_destroy(&block);
14742 tng_data->input_file = temp;
14744 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14745 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14746 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14750 contents_size = block->block_contents_size;
14751 header_size = block->header_contents_size;
14753 header_pos = ftell(tng_data->output_file) - header_size;
14754 frame_set = &tng_data->current_trajectory_frame_set;
14756 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14758 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14759 tng_block_destroy(&block);
14760 return(TNG_CRITICAL);
14763 data.datatype = datatype;
14765 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14767 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14768 tng_block_destroy(&block);
14769 return(TNG_CRITICAL);
14772 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14773 !(dependency & TNG_PARTICLE_DEPENDENT))
14775 tng_block_destroy(&block);
14776 tng_data->input_file = temp;
14778 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14779 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14780 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14781 return(TNG_FAILURE);
14784 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14786 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14787 tng_block_destroy(&block);
14788 return(TNG_CRITICAL);
14791 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14792 tng_data->input_file) == 0)
14794 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14795 tng_block_destroy(&block);
14796 return(TNG_CRITICAL);
14798 if(tng_data->output_endianness_swap_func_64)
14800 if(tng_data->output_endianness_swap_func_64(tng_data,
14801 &data.n_values_per_frame)
14804 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14805 __FILE__, __LINE__);
14809 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14810 tng_data->input_file) == 0)
14812 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14813 tng_block_destroy(&block);
14814 return(TNG_CRITICAL);
14816 if(tng_data->output_endianness_swap_func_64)
14818 if(tng_data->output_endianness_swap_func_64(tng_data,
14822 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14823 __FILE__, __LINE__);
14827 if(data.codec_id != TNG_UNCOMPRESSED)
14829 if(fread(&data.compression_multiplier,
14830 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14833 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14834 tng_block_destroy(&block);
14835 return(TNG_CRITICAL);
14838 if(tng_data->output_endianness_swap_func_64)
14840 if(tng_data->output_endianness_swap_func_64(tng_data,
14841 (int64_t *)&data.compression_multiplier)
14844 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14845 __FILE__, __LINE__);
14851 data.compression_multiplier = 1;
14856 if(fread(&data.first_frame_with_data,
14857 sizeof(data.first_frame_with_data),
14858 1, tng_data->input_file) == 0)
14860 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14861 tng_block_destroy(&block);
14862 return(TNG_CRITICAL);
14864 if(tng_data->output_endianness_swap_func_64)
14866 if(tng_data->output_endianness_swap_func_64(tng_data,
14867 &data.first_frame_with_data)
14870 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14871 __FILE__, __LINE__);
14875 if(fread(&data.stride_length, sizeof(data.stride_length),
14876 1, tng_data->input_file) == 0)
14878 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14879 tng_block_destroy(&block);
14880 return(TNG_CRITICAL);
14882 if(tng_data->output_endianness_swap_func_64)
14884 if(tng_data->output_endianness_swap_func_64(tng_data,
14885 &data.stride_length)
14888 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14889 __FILE__, __LINE__);
14895 data.first_frame_with_data = 0;
14896 data.stride_length = 1;
14898 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14900 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14901 tng_data->input_file) == 0)
14903 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14904 tng_block_destroy(&block);
14905 return(TNG_CRITICAL);
14907 if(tng_data->output_endianness_swap_func_64)
14909 if(tng_data->output_endianness_swap_func_64(tng_data,
14910 &num_first_particle)
14913 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14914 __FILE__, __LINE__);
14918 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14919 tng_data->input_file) == 0)
14921 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14922 tng_block_destroy(&block);
14923 return(TNG_CRITICAL);
14925 if(tng_data->output_endianness_swap_func_64)
14927 if(tng_data->output_endianness_swap_func_64(tng_data,
14928 &block_n_particles)
14931 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14932 __FILE__, __LINE__);
14937 tng_data->input_file = temp;
14939 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14940 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14941 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14944 switch(data.datatype)
14946 case(TNG_INT_DATA):
14947 size = sizeof(int64_t);
14949 case(TNG_FLOAT_DATA):
14950 size = sizeof(float);
14952 case(TNG_DOUBLE_DATA):
14953 size = sizeof(double);
14956 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14958 tng_block_destroy(&block);
14959 return(TNG_FAILURE);
14962 n_values_per_frame = data.n_values_per_frame;
14964 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14965 data.first_frame_with_data)) /
14966 data.stride_length;
14967 file_pos *= block_n_particles * size * n_values_per_frame;
14969 if(file_pos > contents_size)
14971 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14973 tng_block_destroy(&block);
14974 return(TNG_FAILURE);
14977 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14979 /* If the endianness is not big endian the data needs to be swapped */
14980 if((data.datatype == TNG_INT_DATA ||
14981 data.datatype == TNG_DOUBLE_DATA) &&
14982 tng_data->output_endianness_swap_func_64)
14984 copy = malloc(val_n_particles * n_values_per_frame * size);
14985 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14986 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14988 if(tng_data->output_endianness_swap_func_64(tng_data,
14989 (int64_t *) copy+i)
14992 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14993 __FILE__, __LINE__);
14996 fwrite(copy, val_n_particles * n_values_per_frame, size,
14997 tng_data->output_file);
15000 else if(data.datatype == TNG_FLOAT_DATA &&
15001 tng_data->output_endianness_swap_func_32)
15003 copy = malloc(val_n_particles * n_values_per_frame * size);
15004 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
15005 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
15007 if(tng_data->output_endianness_swap_func_32(tng_data,
15008 (int32_t *) copy+i)
15011 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
15012 __FILE__, __LINE__);
15015 fwrite(copy, val_n_particles * n_values_per_frame, size,
15016 tng_data->output_file);
15022 fwrite(values, val_n_particles * n_values_per_frame, size,
15023 tng_data->output_file);
15025 fflush(tng_data->output_file);
15027 /* Update the number of written frames in the frame set. */
15028 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
15030 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
15033 /* If the last frame has been written update the hash */
15034 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
15035 data.first_frame_with_data) >=
15036 frame_set->n_frames)
15038 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
15042 tng_block_destroy(&block);
15043 return(TNG_SUCCESS);
15046 static tng_function_status tng_data_values_alloc
15047 (const tng_trajectory_t tng_data,
15048 union data_values ***values,
15049 const int64_t n_frames,
15050 const int64_t n_values_per_frame,
15054 tng_function_status stat;
15056 if(n_frames <= 0 || n_values_per_frame <= 0)
15058 return(TNG_FAILURE);
15063 stat = tng_data_values_free(tng_data, *values, n_frames,
15064 n_values_per_frame,
15066 if(stat != TNG_SUCCESS)
15068 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15069 __FILE__, __LINE__);
15073 *values = malloc(sizeof(union data_values *) * n_frames);
15076 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15077 sizeof(union data_values **) * n_frames,
15078 __FILE__, __LINE__);
15079 return(TNG_CRITICAL);
15083 for(i = 0; i < n_frames; i++)
15085 (*values)[i] = malloc(sizeof(union data_values) *
15086 n_values_per_frame);
15089 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15090 sizeof(union data_values) * n_values_per_frame,
15091 __FILE__, __LINE__);
15094 return(TNG_CRITICAL);
15097 return(TNG_SUCCESS);
15100 /* FIXME: This needs ***values */
15101 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15102 (const tng_trajectory_t tng_data,
15103 union data_values **values,
15104 const int64_t n_frames,
15105 const int64_t n_values_per_frame,
15113 for(i = 0; i < n_frames; i++)
15117 if(type == TNG_CHAR_DATA)
15119 for(j = 0; j < n_values_per_frame; j++)
15123 free(values[i][j].c);
15124 values[i][j].c = 0;
15136 return(TNG_SUCCESS);
15139 static tng_function_status tng_particle_data_values_alloc
15140 (const tng_trajectory_t tng_data,
15141 union data_values ****values,
15142 const int64_t n_frames,
15143 const int64_t n_particles,
15144 const int64_t n_values_per_frame,
15148 tng_function_status stat;
15150 if(n_particles == 0 || n_values_per_frame == 0)
15152 return(TNG_FAILURE);
15157 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15158 n_particles, n_values_per_frame,
15160 if(stat != TNG_SUCCESS)
15162 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15163 __FILE__, __LINE__);
15167 *values = malloc(sizeof(union data_values **) * n_frames);
15170 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15171 sizeof(union data_values **) * n_frames,
15172 __FILE__, __LINE__);
15173 return(TNG_CRITICAL);
15177 for(i = 0; i < n_frames; i++)
15179 (*values)[i] = malloc(sizeof(union data_values *) *
15183 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15184 sizeof(union data_values *) * n_particles,
15185 __FILE__, __LINE__);
15188 return(TNG_CRITICAL);
15190 for(j = 0; j < n_particles; j++)
15192 (*values)[i][j] = malloc(sizeof(union data_values) *
15193 n_values_per_frame);
15194 if(!(*values)[i][j])
15196 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15197 sizeof(union data_values *) * n_particles,
15198 __FILE__, __LINE__);
15199 tng_particle_data_values_free(tng_data, *values, n_frames,
15200 n_particles, n_values_per_frame,
15203 return(TNG_CRITICAL);
15207 return(TNG_SUCCESS);
15210 /* FIXME: This needs ****values */
15211 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15212 (const tng_trajectory_t tng_data,
15213 union data_values ***values,
15214 const int64_t n_frames,
15215 const int64_t n_particles,
15216 const int64_t n_values_per_frame,
15224 for(i = 0; i < n_frames; i++)
15228 for(j = 0; j < n_particles; j++)
15230 if(type == TNG_CHAR_DATA)
15232 for(k = 0; k < n_values_per_frame; k++)
15234 if(values[i][j][k].c)
15236 free(values[i][j][k].c);
15237 values[i][j][k].c = 0;
15241 free(values[i][j]);
15252 return(TNG_SUCCESS);
15256 tng_function_status DECLSPECDLLEXPORT tng_data_get
15257 (tng_trajectory_t tng_data,
15258 const int64_t block_id,
15259 union data_values ***values,
15261 int64_t *n_values_per_frame,
15264 int64_t i, j, file_pos, block_index;
15267 tng_non_particle_data_t data;
15268 tng_trajectory_frame_set_t frame_set;
15269 tng_gen_block_t block;
15270 tng_function_status stat;
15272 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15273 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15274 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15275 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15277 frame_set = &tng_data->current_trajectory_frame_set;
15282 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15284 tng_block_init(&block);
15285 file_pos = ftell(tng_data->input_file);
15286 /* Read all blocks until next frame set block */
15287 stat = tng_block_header_read(tng_data, block);
15288 while(file_pos < tng_data->input_file_len &&
15289 stat != TNG_CRITICAL &&
15290 block->id != TNG_TRAJECTORY_FRAME_SET &&
15293 /* Use hash by default */
15294 stat = tng_block_read_next(tng_data, block,
15296 if(stat != TNG_CRITICAL)
15298 file_pos = ftell(tng_data->input_file);
15299 if(file_pos < tng_data->input_file_len)
15301 stat = tng_block_header_read(tng_data, block);
15305 tng_block_destroy(&block);
15306 if(stat == TNG_CRITICAL)
15308 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15309 file_pos, __FILE__, __LINE__);
15313 for(i = 0; i < frame_set->n_data_blocks; i++)
15315 data = &frame_set->tr_data[i];
15316 if(data->block_id == block_id)
15322 if(block_index < 0)
15324 return(TNG_FAILURE);
15328 *n_frames = tng_max_i64(1, data->n_frames);
15329 *n_values_per_frame = data->n_values_per_frame;
15330 *type = data->datatype;
15334 if(tng_data_values_alloc(tng_data, values, *n_frames,
15335 *n_values_per_frame,
15339 return(TNG_CRITICAL);
15345 case TNG_CHAR_DATA:
15346 for(i = 0; i < *n_frames; i++)
15348 for(j = 0; j < *n_values_per_frame; j++)
15350 len = strlen(data->strings[i][j]) + 1;
15351 (*values)[i][j].c = malloc(len);
15352 strncpy((*values)[i][j].c, data->strings[i][j], len);
15357 size = sizeof(int);
15358 for(i = 0; i < *n_frames; i++)
15360 for(j = 0; j < *n_values_per_frame; j++)
15362 (*values)[i][j].i = *(int *)((char *)data->values + size *
15363 (i*(*n_values_per_frame) + j));
15367 case TNG_FLOAT_DATA:
15368 size = sizeof(float);
15369 for(i = 0; i < *n_frames; i++)
15371 for(j = 0; j < *n_values_per_frame; j++)
15373 (*values)[i][j].f = *(float *)((char *)data->values + size *
15374 (i*(*n_values_per_frame) + j));
15378 case TNG_DOUBLE_DATA:
15380 size = sizeof(double);
15381 for(i = 0; i < *n_frames; i++)
15383 for(j = 0; j < *n_values_per_frame; j++)
15385 (*values)[i][j].d = *(double *)((char *)data->values + size *
15386 (i*(*n_values_per_frame) + j));
15391 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15393 return(TNG_SUCCESS);
15396 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15397 const int64_t block_id,
15400 int64_t *stride_length,
15401 int64_t *n_values_per_frame,
15404 int64_t file_pos, data_size, n_frames_div, block_index;
15406 tng_non_particle_data_t data;
15407 tng_trajectory_frame_set_t frame_set;
15408 tng_gen_block_t block;
15410 tng_function_status stat;
15412 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15413 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15414 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15415 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15416 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15418 frame_set = &tng_data->current_trajectory_frame_set;
15423 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15425 tng_block_init(&block);
15426 file_pos = ftell(tng_data->input_file);
15427 /* Read all blocks until next frame set block */
15428 stat = tng_block_header_read(tng_data, block);
15429 while(file_pos < tng_data->input_file_len &&
15430 stat != TNG_CRITICAL &&
15431 block->id != TNG_TRAJECTORY_FRAME_SET &&
15434 /* Use hash by default */
15435 stat = tng_block_read_next(tng_data, block,
15437 if(stat != TNG_CRITICAL)
15439 file_pos = ftell(tng_data->input_file);
15440 if(file_pos < tng_data->input_file_len)
15442 stat = tng_block_header_read(tng_data, block);
15446 tng_block_destroy(&block);
15447 if(stat == TNG_CRITICAL)
15449 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15450 file_pos, __FILE__, __LINE__);
15454 for(i = 0; i < frame_set->n_data_blocks; i++)
15456 data = &frame_set->tr_data[i];
15457 if(data->block_id == block_id)
15463 if(block_index < 0)
15465 return(TNG_FAILURE);
15469 *type = data->datatype;
15473 case TNG_CHAR_DATA:
15474 return(TNG_FAILURE);
15476 size = sizeof(int64_t);
15478 case TNG_FLOAT_DATA:
15479 size = sizeof(float);
15481 case TNG_DOUBLE_DATA:
15483 size = sizeof(double);
15486 *n_frames = data->n_frames;
15487 *n_values_per_frame = data->n_values_per_frame;
15488 *stride_length = data->stride_length;
15489 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15490 *n_frames / *stride_length;
15492 data_size = n_frames_div * size *
15493 *n_values_per_frame;
15495 temp = realloc(*values, data_size);
15498 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15499 data_size, __FILE__, __LINE__);
15502 return(TNG_CRITICAL);
15507 memcpy(*values, data->values, data_size);
15509 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15511 return(TNG_SUCCESS);
15514 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15515 (tng_trajectory_t tng_data,
15516 const int64_t block_id,
15517 const int64_t start_frame_nr,
15518 const int64_t end_frame_nr,
15519 const char hash_mode,
15520 union data_values ***values,
15521 int64_t *n_values_per_frame,
15524 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15525 int64_t block_index;
15528 tng_non_particle_data_t data;
15529 tng_trajectory_frame_set_t frame_set;
15530 tng_gen_block_t block;
15531 tng_function_status stat;
15533 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15534 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15535 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15536 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15540 frame_set = &tng_data->current_trajectory_frame_set;
15541 first_frame = frame_set->first_frame;
15543 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15544 if(stat != TNG_SUCCESS)
15550 /* Do not re-read the frame set. */
15551 if(first_frame != frame_set->first_frame ||
15552 frame_set->n_data_blocks <= 0)
15554 tng_block_init(&block);
15555 file_pos = ftell(tng_data->input_file);
15556 /* Read all blocks until next frame set block */
15557 stat = tng_block_header_read(tng_data, block);
15558 while(file_pos < tng_data->input_file_len &&
15559 stat != TNG_CRITICAL &&
15560 block->id != TNG_TRAJECTORY_FRAME_SET &&
15563 stat = tng_block_read_next(tng_data, block,
15565 if(stat != TNG_CRITICAL)
15567 file_pos = ftell(tng_data->input_file);
15568 if(file_pos < tng_data->input_file_len)
15570 stat = tng_block_header_read(tng_data, block);
15574 tng_block_destroy(&block);
15575 if(stat == TNG_CRITICAL)
15577 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15578 file_pos, __FILE__, __LINE__);
15584 /* See if there is a data block of this ID.
15585 * Start checking the last read frame set */
15586 for(i = 0; i < frame_set->n_data_blocks; i++)
15588 data = &frame_set->tr_data[i];
15589 if(data->block_id == block_id)
15596 if(block_index < 0)
15598 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15599 block_id, __FILE__, __LINE__);
15600 return(TNG_FAILURE);
15603 n_frames = end_frame_nr - start_frame_nr + 1;
15604 *n_values_per_frame = data->n_values_per_frame;
15605 *type = data->datatype;
15609 if(tng_data_values_alloc(tng_data, values, n_frames,
15610 *n_values_per_frame,
15611 *type) != TNG_SUCCESS)
15613 return(TNG_CRITICAL);
15617 current_frame_pos = start_frame_nr - frame_set->first_frame;
15618 /* It's not very elegant to reuse so much of the code in the different case
15619 * statements, but it's unnecessarily slow to have the switch-case block
15620 * inside the for loops. */
15623 case TNG_CHAR_DATA:
15624 for(i=0; i<n_frames; i++)
15626 if(current_frame_pos == frame_set->n_frames)
15628 stat = tng_frame_set_read_next(tng_data, hash_mode);
15629 if(stat != TNG_SUCCESS)
15633 current_frame_pos = 0;
15635 for(j = 0; j < *n_values_per_frame; j++)
15637 len = strlen(data->strings[current_frame_pos][j]) + 1;
15638 (*values)[i][j].c = malloc(len);
15639 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15641 current_frame_pos++;
15645 size = sizeof(int);
15646 for(i=0; i<n_frames; i++)
15648 if(current_frame_pos == frame_set->n_frames)
15650 stat = tng_frame_set_read_next(tng_data, hash_mode);
15651 if(stat != TNG_SUCCESS)
15655 current_frame_pos = 0;
15657 for(j = 0; j < *n_values_per_frame; j++)
15659 (*values)[i][j].i = *(int *)((char *)data->values + size *
15660 (current_frame_pos *
15661 (*n_values_per_frame) + j));
15663 current_frame_pos++;
15666 case TNG_FLOAT_DATA:
15667 size = sizeof(float);
15668 for(i=0; i<n_frames; i++)
15670 if(current_frame_pos == frame_set->n_frames)
15672 stat = tng_frame_set_read_next(tng_data, hash_mode);
15673 if(stat != TNG_SUCCESS)
15677 current_frame_pos = 0;
15679 for(j = 0; j < *n_values_per_frame; j++)
15681 (*values)[i][j].f = *(float *)((char *)data->values + size *
15682 (current_frame_pos *
15683 (*n_values_per_frame) + j));
15685 current_frame_pos++;
15688 case TNG_DOUBLE_DATA:
15690 size = sizeof(double);
15691 for(i=0; i<n_frames; i++)
15693 if(current_frame_pos == frame_set->n_frames)
15695 stat = tng_frame_set_read_next(tng_data, hash_mode);
15696 if(stat != TNG_SUCCESS)
15700 current_frame_pos = 0;
15702 for(j = 0; j < *n_values_per_frame; j++)
15704 (*values)[i][j].d = *(double *)((char *)data->values + size *
15705 (current_frame_pos *
15706 (*n_values_per_frame) + j));
15708 current_frame_pos++;
15712 data->last_retrieved_frame = end_frame_nr;
15714 return(TNG_SUCCESS);
15717 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15718 (tng_trajectory_t tng_data,
15719 const int64_t block_id,
15720 const int64_t start_frame_nr,
15721 const int64_t end_frame_nr,
15722 const char hash_mode,
15724 int64_t *stride_length,
15725 int64_t *n_values_per_frame,
15728 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15729 int64_t file_pos, current_frame_pos, data_size, frame_size;
15730 int64_t last_frame_pos;
15732 tng_trajectory_frame_set_t frame_set;
15733 tng_non_particle_data_t np_data;
15734 tng_gen_block_t block;
15735 void *current_values = 0, *temp;
15736 tng_function_status stat;
15738 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15739 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15740 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15741 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15742 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15744 frame_set = &tng_data->current_trajectory_frame_set;
15745 first_frame = frame_set->first_frame;
15747 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15748 if(stat != TNG_SUCCESS)
15753 /* Do not re-read the frame set and only need the requested block. */
15754 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15755 stat = tng_data_find(tng_data, block_id, &np_data);
15756 if(first_frame != frame_set->first_frame ||
15757 stat != TNG_SUCCESS)
15759 tng_block_init(&block);
15760 if(stat != TNG_SUCCESS)
15762 fseek(tng_data->input_file,
15763 (long)tng_data->current_trajectory_frame_set_input_file_pos,
15765 stat = tng_block_header_read(tng_data, block);
15766 if(stat != TNG_SUCCESS)
15768 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15769 __FILE__, __LINE__);
15773 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15775 file_pos = ftell(tng_data->input_file);
15776 /* Read until next frame set block */
15777 stat = tng_block_header_read(tng_data, block);
15778 while(file_pos < tng_data->input_file_len &&
15779 stat != TNG_CRITICAL &&
15780 block->id != TNG_TRAJECTORY_FRAME_SET &&
15783 if(block->id == block_id)
15785 stat = tng_block_read_next(tng_data, block,
15787 if(stat != TNG_CRITICAL)
15789 file_pos = ftell(tng_data->input_file);
15790 if(file_pos < tng_data->input_file_len)
15792 stat = tng_block_header_read(tng_data, block);
15798 file_pos += block->block_contents_size + block->header_contents_size;
15799 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15800 if(file_pos < tng_data->input_file_len)
15802 stat = tng_block_header_read(tng_data, block);
15806 tng_block_destroy(&block);
15807 if(stat == TNG_CRITICAL)
15809 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15810 file_pos, __FILE__, __LINE__);
15815 stat = tng_data_find(tng_data, block_id, &np_data);
15816 if(stat != TNG_SUCCESS)
15821 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15822 &n_frames, stride_length,
15823 n_values_per_frame, type);
15825 if(stat != TNG_SUCCESS)
15829 free(current_values);
15834 if(n_frames == 1 && n_frames < frame_set->n_frames)
15840 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15845 case TNG_CHAR_DATA:
15846 return(TNG_FAILURE);
15848 size = sizeof(int64_t);
15850 case TNG_FLOAT_DATA:
15851 size = sizeof(float);
15853 case TNG_DOUBLE_DATA:
15855 size = sizeof(double);
15858 n_frames_div = (tot_n_frames % *stride_length) ?
15859 tot_n_frames / *stride_length + 1:
15860 tot_n_frames / *stride_length;
15861 data_size = n_frames_div * size * (*n_values_per_frame);
15863 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15864 size, n_frames_div, data_size);
15866 temp = realloc(*values, data_size);
15869 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15870 data_size, __FILE__, __LINE__);
15873 return(TNG_CRITICAL);
15878 if( n_frames == 1 && n_frames < frame_set->n_frames)
15880 memcpy(*values, current_values, size * (*n_values_per_frame));
15884 current_frame_pos = start_frame_nr - frame_set->first_frame;
15886 frame_size = size * (*n_values_per_frame);
15888 last_frame_pos = tng_min_i64(n_frames,
15889 end_frame_nr - start_frame_nr);
15891 n_frames_div = current_frame_pos / *stride_length;
15892 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15893 last_frame_pos / *stride_length + 1:
15894 last_frame_pos / *stride_length;
15895 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15897 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15898 n_frames_div_2 * frame_size);
15900 current_frame_pos += n_frames - current_frame_pos;
15902 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15904 stat = tng_frame_set_read_next(tng_data, hash_mode);
15905 if(stat != TNG_SUCCESS)
15909 free(current_values);
15916 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15917 &n_frames, stride_length,
15918 n_values_per_frame, type);
15920 if(stat != TNG_SUCCESS)
15924 free(current_values);
15931 last_frame_pos = tng_min_i64(n_frames,
15932 end_frame_nr - current_frame_pos);
15934 n_frames_div = current_frame_pos / *stride_length;
15935 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15936 last_frame_pos / *stride_length + 1:
15937 last_frame_pos / *stride_length;
15938 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15940 memcpy(((char *)*values) + n_frames_div * frame_size,
15942 n_frames_div_2 * frame_size);
15944 current_frame_pos += n_frames;
15950 free(current_values);
15953 np_data->last_retrieved_frame = end_frame_nr;
15955 return(TNG_SUCCESS);
15958 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15959 (tng_trajectory_t tng_data,
15960 const int64_t block_id,
15961 union data_values ****values,
15963 int64_t *n_particles,
15964 int64_t *n_values_per_frame,
15967 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15970 tng_particle_data_t data;
15971 tng_trajectory_frame_set_t frame_set;
15972 tng_gen_block_t block;
15973 char block_type_flag;
15974 tng_function_status stat;
15976 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15977 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15978 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15979 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15980 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15982 frame_set = &tng_data->current_trajectory_frame_set;
15987 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15989 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15991 block_type_flag = TNG_TRAJECTORY_BLOCK;
15995 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15998 tng_block_init(&block);
15999 file_pos = ftell(tng_data->input_file);
16000 /* Read all blocks until next frame set block */
16001 stat = tng_block_header_read(tng_data, block);
16002 while(file_pos < tng_data->input_file_len &&
16003 stat != TNG_CRITICAL &&
16004 block->id != TNG_TRAJECTORY_FRAME_SET &&
16007 /* Use hash by default */
16008 stat = tng_block_read_next(tng_data, block,
16010 if(stat != TNG_CRITICAL)
16012 file_pos = ftell(tng_data->input_file);
16013 if(file_pos < tng_data->input_file_len)
16015 stat = tng_block_header_read(tng_data, block);
16019 tng_block_destroy(&block);
16020 if(stat == TNG_CRITICAL)
16022 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16023 file_pos, __FILE__, __LINE__);
16027 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16029 data = &frame_set->tr_particle_data[i];
16030 if(data->block_id == block_id)
16033 block_type_flag = TNG_TRAJECTORY_BLOCK;
16037 if(block_index < 0)
16039 return(TNG_FAILURE);
16044 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16046 block_type_flag = TNG_TRAJECTORY_BLOCK;
16050 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16054 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16055 tng_data->var_num_atoms_flag)
16057 *n_particles = frame_set->n_particles;
16061 *n_particles = tng_data->n_particles;
16064 *n_frames = tng_max_i64(1, data->n_frames);
16065 *n_values_per_frame = data->n_values_per_frame;
16066 *type = data->datatype;
16070 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16071 *n_particles, *n_values_per_frame,
16075 return(TNG_CRITICAL);
16079 /* It's not very elegant to reuse so much of the code in the different case
16080 * statements, but it's unnecessarily slow to have the switch-case block
16081 * inside the for loops. */
16084 case TNG_CHAR_DATA:
16085 for(i = 0; i < *n_frames; i++)
16087 for(j = 0; j < *n_particles; j++)
16089 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16090 for(k = 0; k < *n_values_per_frame; k++)
16092 len = strlen(data->strings[i][j][k]) + 1;
16093 (*values)[i][mapping][k].c = malloc(len);
16094 strncpy((*values)[i][mapping][k].c,
16095 data->strings[i][j][k], len);
16101 size = sizeof(int);
16102 i_step = (*n_particles) * (*n_values_per_frame);
16103 for(i = 0; i < *n_frames; i++)
16105 for(j = 0; j < *n_particles; j++)
16107 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16108 for(k = 0; k < *n_values_per_frame; k++)
16110 (*values)[i][mapping][k].i = *(int *)
16111 ((char *)data->values + size *
16113 (*n_values_per_frame) + k));
16118 case TNG_FLOAT_DATA:
16119 size = sizeof(float);
16120 i_step = (*n_particles) * (*n_values_per_frame);
16121 for(i = 0; i < *n_frames; i++)
16123 for(j = 0; j < *n_particles; j++)
16125 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16126 for(k = 0; k < *n_values_per_frame; k++)
16128 (*values)[i][mapping][k].f = *(float *)
16129 ((char *)data->values + size *
16131 (*n_values_per_frame) + k));
16136 case TNG_DOUBLE_DATA:
16138 size = sizeof(double);
16139 i_step = (*n_particles) * (*n_values_per_frame);
16140 for(i = 0; i < *n_frames; i++)
16142 for(j = 0; j < *n_particles; j++)
16144 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16145 for(k = 0; k < *n_values_per_frame; k++)
16147 (*values)[i][mapping][k].d = *(double *)
16148 ((char *)data->values + size *
16150 (*n_values_per_frame) + k));
16156 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16158 return(TNG_SUCCESS);
16161 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16162 (tng_trajectory_t tng_data,
16163 const int64_t block_id,
16166 int64_t *stride_length,
16167 int64_t *n_particles,
16168 int64_t *n_values_per_frame,
16171 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16172 int64_t block_index;
16174 tng_particle_data_t data;
16175 tng_trajectory_frame_set_t frame_set;
16176 tng_gen_block_t block;
16178 char block_type_flag;
16179 tng_function_status stat;
16181 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16182 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16183 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16184 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16185 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16187 frame_set = &tng_data->current_trajectory_frame_set;
16192 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16194 tng_block_init(&block);
16195 file_pos = ftell(tng_data->input_file);
16196 /* Read all blocks until next frame set block */
16197 stat = tng_block_header_read(tng_data, block);
16198 while(file_pos < tng_data->input_file_len &&
16199 stat != TNG_CRITICAL &&
16200 block->id != TNG_TRAJECTORY_FRAME_SET &&
16203 /* Use hash by default */
16204 stat = tng_block_read_next(tng_data, block,
16206 if(stat != TNG_CRITICAL)
16208 file_pos = ftell(tng_data->input_file);
16209 if(file_pos < tng_data->input_file_len)
16211 stat = tng_block_header_read(tng_data, block);
16215 tng_block_destroy(&block);
16216 if(stat == TNG_CRITICAL)
16218 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16219 file_pos, __FILE__, __LINE__);
16223 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16225 data = &frame_set->tr_particle_data[i];
16226 if(data->block_id == block_id)
16232 if(block_index < 0)
16234 return(TNG_FAILURE);
16238 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16240 block_type_flag = TNG_TRAJECTORY_BLOCK;
16244 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16247 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16248 tng_data->var_num_atoms_flag)
16250 *n_particles = frame_set->n_particles;
16254 *n_particles = tng_data->n_particles;
16257 *type = data->datatype;
16261 case TNG_CHAR_DATA:
16262 return(TNG_FAILURE);
16264 size = sizeof(int64_t);
16266 case TNG_FLOAT_DATA:
16267 size = sizeof(float);
16269 case TNG_DOUBLE_DATA:
16271 size = sizeof(double);
16274 *n_frames = tng_max_i64(1, data->n_frames);
16275 *n_values_per_frame = data->n_values_per_frame;
16276 *stride_length = data->stride_length;
16278 n_frames_div = (*n_frames % *stride_length) ?
16279 *n_frames / *stride_length + 1:
16280 *n_frames / *stride_length;
16282 data_size = n_frames_div * size * (*n_particles) *
16283 (*n_values_per_frame);
16285 temp = realloc(*values, data_size);
16288 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16289 data_size, __FILE__, __LINE__);
16292 return(TNG_CRITICAL);
16297 if(frame_set->n_mapping_blocks <= 0)
16299 memcpy(*values, data->values, data_size);
16303 i_step = (*n_particles) * (*n_values_per_frame);
16304 for(i = 0; i < *n_frames; i++)
16306 for(j = 0; j < *n_particles; j++)
16308 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16309 memcpy(((char *)*values) + size * (i * i_step + mapping *
16310 (*n_values_per_frame)),
16311 (char *)data->values + size *
16312 (i * i_step + j * (*n_values_per_frame)),
16313 size * (*n_values_per_frame));
16318 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16320 return(TNG_SUCCESS);
16323 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16324 (tng_trajectory_t tng_data,
16325 const int64_t block_id,
16326 const int64_t start_frame_nr,
16327 const int64_t end_frame_nr,
16328 const char hash_mode,
16329 union data_values ****values,
16330 int64_t *n_particles,
16331 int64_t *n_values_per_frame,
16334 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16335 int64_t first_frame, block_index;
16338 tng_particle_data_t data;
16339 tng_trajectory_frame_set_t frame_set;
16340 tng_gen_block_t block;
16341 char block_type_flag;
16342 tng_function_status stat;
16344 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16345 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16346 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16347 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16348 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16352 frame_set = &tng_data->current_trajectory_frame_set;
16353 first_frame = frame_set->first_frame;
16355 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16356 if(stat != TNG_SUCCESS)
16361 /* Do not re-read the frame set. */
16362 if(first_frame != frame_set->first_frame ||
16363 frame_set->n_particle_data_blocks <= 0)
16365 tng_block_init(&block);
16366 file_pos = ftell(tng_data->input_file);
16367 /* Read all blocks until next frame set block */
16368 stat = tng_block_header_read(tng_data, block);
16369 while(file_pos < tng_data->input_file_len &&
16370 stat != TNG_CRITICAL &&
16371 block->id != TNG_TRAJECTORY_FRAME_SET &&
16374 stat = tng_block_read_next(tng_data, block,
16376 if(stat != TNG_CRITICAL)
16378 file_pos = ftell(tng_data->input_file);
16379 if(file_pos < tng_data->input_file_len)
16381 stat = tng_block_header_read(tng_data, block);
16385 tng_block_destroy(&block);
16386 if(stat == TNG_CRITICAL)
16388 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16389 file_pos, __FILE__, __LINE__);
16394 /* See if there is already a data block of this ID.
16395 * Start checking the last read frame set */
16396 for(i = frame_set->n_particle_data_blocks; i-- ;)
16398 data = &frame_set->tr_particle_data[i];
16399 if(data->block_id == block_id)
16402 block_type_flag = TNG_TRAJECTORY_BLOCK;
16407 if(block_index < 0)
16409 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16410 block_id, __FILE__, __LINE__);
16411 return(TNG_FAILURE);
16414 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16415 tng_data->var_num_atoms_flag)
16417 *n_particles = frame_set->n_particles;
16421 *n_particles = tng_data->n_particles;
16424 n_frames = end_frame_nr - start_frame_nr + 1;
16425 *n_values_per_frame = data->n_values_per_frame;
16426 *type = data->datatype;
16430 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16431 *n_particles, *n_values_per_frame,
16435 return(TNG_CRITICAL);
16439 current_frame_pos = start_frame_nr - frame_set->first_frame;
16440 /* It's not very elegant to reuse so much of the code in the different case
16441 * statements, but it's unnecessarily slow to have the switch-case block
16442 * inside the for loops. */
16445 case TNG_CHAR_DATA:
16446 for(i=0; i<n_frames; i++)
16448 if(current_frame_pos == frame_set->n_frames)
16450 stat = tng_frame_set_read_next(tng_data, hash_mode);
16451 if(stat != TNG_SUCCESS)
16455 current_frame_pos = 0;
16457 for(j = 0; j < *n_particles; j++)
16459 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16460 for(k = 0; k < *n_values_per_frame; k++)
16462 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16463 (*values)[i][mapping][k].c = malloc(len);
16464 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16467 current_frame_pos++;
16471 size = sizeof(int);
16472 i_step = (*n_particles) * (*n_values_per_frame);
16473 for(i=0; i<n_frames; i++)
16475 if(current_frame_pos == frame_set->n_frames)
16477 stat = tng_frame_set_read_next(tng_data, hash_mode);
16478 if(stat != TNG_SUCCESS)
16482 current_frame_pos = 0;
16484 for(j = 0; j < *n_particles; j++)
16486 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16487 for(k = 0; k < *n_values_per_frame; k++)
16489 (*values)[i][mapping][k].i = *(int *)
16490 ((char *)data->values + size *
16491 (current_frame_pos *
16493 (*n_values_per_frame) + k));
16496 current_frame_pos++;
16499 case TNG_FLOAT_DATA:
16500 size = sizeof(float);
16501 i_step = (*n_particles) * (*n_values_per_frame);
16502 for(i=0; i<n_frames; i++)
16504 if(current_frame_pos == frame_set->n_frames)
16506 stat = tng_frame_set_read_next(tng_data, hash_mode);
16507 if(stat != TNG_SUCCESS)
16511 current_frame_pos = 0;
16513 for(j=0; j<*n_particles; j++)
16515 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16516 for(k=0; k<*n_values_per_frame; k++)
16518 (*values)[i][mapping][k].f = *(float *)
16519 ((char *)data->values + size *
16520 (current_frame_pos *
16522 (*n_values_per_frame) + k));
16525 current_frame_pos++;
16528 case TNG_DOUBLE_DATA:
16530 size = sizeof(double);
16531 i_step = (*n_particles) * (*n_values_per_frame);
16532 for(i=0; i<n_frames; i++)
16534 if(current_frame_pos == frame_set->n_frames)
16536 stat = tng_frame_set_read_next(tng_data, hash_mode);
16537 if(stat != TNG_SUCCESS)
16541 current_frame_pos = 0;
16543 for(j=0; j<*n_particles; j++)
16545 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16546 for(k=0; k<*n_values_per_frame; k++)
16548 (*values)[i][mapping][k].d = *(double *)
16549 ((char *)data->values + size *
16550 (current_frame_pos *
16552 (*n_values_per_frame) + k));
16555 current_frame_pos++;
16559 data->last_retrieved_frame = end_frame_nr;
16561 return(TNG_SUCCESS);
16564 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16565 (tng_trajectory_t tng_data,
16566 const int64_t block_id,
16567 const int64_t start_frame_nr,
16568 const int64_t end_frame_nr,
16569 const char hash_mode,
16571 int64_t *n_particles,
16572 int64_t *stride_length,
16573 int64_t *n_values_per_frame,
16576 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16577 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16579 tng_trajectory_frame_set_t frame_set;
16580 tng_particle_data_t p_data;
16581 tng_gen_block_t block;
16582 void *current_values = 0, *temp;
16583 tng_function_status stat;
16585 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16586 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16587 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16588 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16589 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16590 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16592 frame_set = &tng_data->current_trajectory_frame_set;
16593 first_frame = frame_set->first_frame;
16595 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16596 if(stat != TNG_SUCCESS)
16601 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16602 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16603 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16604 if(first_frame != frame_set->first_frame ||
16605 stat != TNG_SUCCESS)
16607 tng_block_init(&block);
16608 if(stat != TNG_SUCCESS)
16610 fseek(tng_data->input_file,
16611 (long)tng_data->current_trajectory_frame_set_input_file_pos,
16613 stat = tng_block_header_read(tng_data, block);
16614 if(stat != TNG_SUCCESS)
16616 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16617 __FILE__, __LINE__);
16621 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
16623 file_pos = ftell(tng_data->input_file);
16624 /* Read until next frame set block */
16625 stat = tng_block_header_read(tng_data, block);
16626 while(file_pos < tng_data->input_file_len &&
16627 stat != TNG_CRITICAL &&
16628 block->id != TNG_TRAJECTORY_FRAME_SET &&
16631 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16633 stat = tng_block_read_next(tng_data, block,
16635 if(stat != TNG_CRITICAL)
16637 file_pos = ftell(tng_data->input_file);
16638 if(file_pos < tng_data->input_file_len)
16640 stat = tng_block_header_read(tng_data, block);
16646 file_pos += block->block_contents_size + block->header_contents_size;
16647 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
16648 if(file_pos < tng_data->input_file_len)
16650 stat = tng_block_header_read(tng_data, block);
16654 tng_block_destroy(&block);
16655 if(stat == TNG_CRITICAL)
16657 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16658 file_pos, __FILE__, __LINE__);
16662 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16663 if(stat != TNG_SUCCESS)
16668 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16669 &n_frames, stride_length, n_particles,
16670 n_values_per_frame, type);
16672 if(stat != TNG_SUCCESS || *n_particles == 0)
16676 free(current_values);
16681 if(n_frames == 1 && n_frames < frame_set->n_frames)
16687 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16692 case TNG_CHAR_DATA:
16693 return(TNG_FAILURE);
16695 size = sizeof(int64_t);
16697 case TNG_FLOAT_DATA:
16698 size = sizeof(float);
16700 case TNG_DOUBLE_DATA:
16702 size = sizeof(double);
16705 n_frames_div = (tot_n_frames % *stride_length) ?
16706 tot_n_frames / *stride_length + 1:
16707 tot_n_frames / *stride_length;
16709 data_size = n_frames_div * size * (*n_particles) *
16710 (*n_values_per_frame);
16712 temp = realloc(*values, data_size);
16715 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16716 data_size, __FILE__, __LINE__);
16719 return(TNG_CRITICAL);
16724 if( n_frames == 1 && n_frames < frame_set->n_frames)
16726 memcpy(*values, current_values, size * (*n_particles) *
16727 (*n_values_per_frame));
16731 current_frame_pos = start_frame_nr - frame_set->first_frame;
16733 frame_size = size * (*n_particles) * (*n_values_per_frame);
16735 last_frame_pos = tng_min_i64(n_frames,
16736 end_frame_nr - start_frame_nr);
16738 n_frames_div = current_frame_pos / *stride_length;
16739 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16740 last_frame_pos / *stride_length + 1:
16741 last_frame_pos / *stride_length;
16742 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16744 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16745 n_frames_div_2 * frame_size);
16747 current_frame_pos += n_frames - current_frame_pos;
16749 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16751 stat = tng_frame_set_read_next(tng_data, hash_mode);
16752 if(stat != TNG_SUCCESS)
16756 free(current_values);
16763 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16764 &n_frames, stride_length, n_particles,
16765 n_values_per_frame, type);
16767 if(stat != TNG_SUCCESS)
16771 free(current_values);
16778 last_frame_pos = tng_min_i64(n_frames,
16779 end_frame_nr - current_frame_pos);
16781 n_frames_div = current_frame_pos / *stride_length;
16782 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16783 last_frame_pos / *stride_length + 1:
16784 last_frame_pos / *stride_length;
16785 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16787 memcpy(((char *)*values) + n_frames_div * frame_size,
16789 n_frames_div_2 * frame_size);
16791 current_frame_pos += n_frames;
16797 free(current_values);
16800 p_data->last_retrieved_frame = end_frame_nr;
16802 return(TNG_SUCCESS);
16805 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16806 (const tng_trajectory_t tng_data,
16807 const int64_t block_id,
16809 int64_t *stride_length)
16811 tng_function_status stat;
16812 tng_non_particle_data_t np_data;
16813 tng_particle_data_t p_data;
16814 long orig_file_pos, file_pos;
16815 int is_particle_data;
16817 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16824 stat = tng_frame_set_of_frame_find(tng_data, frame);
16825 if(stat != TNG_SUCCESS)
16830 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16831 stat = tng_data_find(tng_data, block_id, &np_data);
16832 if(stat != TNG_SUCCESS)
16834 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16835 if(stat != TNG_SUCCESS)
16837 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16838 /* If no specific frame was required read until this data block is found */
16841 file_pos = ftell(tng_data->input_file);
16842 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16844 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16845 file_pos = ftell(tng_data->input_file);
16848 if(stat != TNG_SUCCESS)
16850 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16854 stat = tng_data_find(tng_data, block_id, &np_data);
16855 if(stat != TNG_SUCCESS)
16857 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16858 if(stat != TNG_SUCCESS)
16860 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16866 is_particle_data = 1;
16871 is_particle_data = 0;
16876 is_particle_data = 1;
16881 is_particle_data = 0;
16883 if(is_particle_data)
16885 *stride_length = p_data->stride_length;
16889 *stride_length = np_data->stride_length;
16891 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16893 return(TNG_SUCCESS);
16896 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16897 (const tng_trajectory_t tng_data,
16900 struct tm *time_data;
16903 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16904 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16906 secs = tng_data->time;
16908 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16909 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16910 "%4d-%02d-%02d %02d:%02d:%02d",
16911 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16912 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16914 return(TNG_SUCCESS);
16918 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16919 (const char *filename,
16921 tng_trajectory_t *tng_data_p)
16923 tng_function_status stat;
16925 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16927 if(mode != 'r' && mode != 'w' && mode != 'a')
16929 return(TNG_FAILURE);
16932 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16934 tng_trajectory_destroy(tng_data_p);
16935 return(TNG_CRITICAL);
16938 if(mode == 'r' || mode == 'a')
16940 tng_input_file_set(*tng_data_p, filename);
16942 /* Read the file headers */
16943 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16945 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16947 if(stat != TNG_SUCCESS)
16955 tng_output_file_set(*tng_data_p, filename);
16957 else if(mode == 'a')
16959 if((*tng_data_p)->output_file)
16961 fclose((*tng_data_p)->output_file);
16963 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
16964 fseek((*tng_data_p)->input_file,
16965 (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16968 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16969 if(stat != TNG_SUCCESS)
16971 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16972 __FILE__, __LINE__);
16974 (*tng_data_p)->output_file = 0;
16976 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16977 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16978 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16979 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16980 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16981 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16982 if((*tng_data_p)->input_file)
16984 fclose((*tng_data_p)->input_file);
16985 (*tng_data_p)->input_file = 0;
16987 if((*tng_data_p)->input_file_path)
16989 free((*tng_data_p)->input_file_path);
16990 (*tng_data_p)->input_file_path = 0;
16992 tng_output_append_file_set(*tng_data_p, filename);
16994 fseek((*tng_data_p)->output_file, 0, SEEK_END);
16997 return(TNG_SUCCESS);
17000 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
17001 (tng_trajectory_t *tng_data_p)
17003 tng_trajectory_frame_set_t frame_set;
17005 if(tng_data_p == 0)
17007 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
17008 __FILE__, __LINE__);
17009 return(TNG_FAILURE);
17012 if(*tng_data_p == 0)
17014 return(TNG_SUCCESS);
17017 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
17019 if(frame_set->n_unwritten_frames > 0)
17021 frame_set->n_frames = frame_set->n_unwritten_frames;
17022 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
17025 return(tng_trajectory_destroy(tng_data_p));
17028 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
17029 (tng_trajectory_t tng_data,
17030 const int64_t frame_nr,
17033 int64_t first_frame;
17034 tng_trajectory_frame_set_t frame_set;
17035 tng_function_status stat;
17037 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17038 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
17040 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
17041 if(stat != TNG_SUCCESS)
17043 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
17044 frame_nr, __FILE__, __LINE__);
17048 frame_set = &tng_data->current_trajectory_frame_set;
17049 first_frame = frame_set->first_frame;
17051 if(tng_data->time_per_frame <= 0)
17053 return(TNG_FAILURE);
17056 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
17058 return(TNG_SUCCESS);
17062 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17063 (tng_trajectory_t tng_data,
17065 int64_t **molecule_cnt_list,
17066 tng_molecule_t *mols)
17068 tng_trajectory_frame_set_t frame_set;
17070 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17071 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17073 *n_mols = tng_data->n_molecules;
17075 frame_set = &tng_data->current_trajectory_frame_set;
17076 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17078 *molecule_cnt_list = frame_set->molecule_cnt_list;
17082 *molecule_cnt_list = tng_data->molecule_cnt_list;
17085 *mols = tng_data->molecules;
17087 return(TNG_SUCCESS);
17091 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17092 (tng_trajectory_t tng_data,
17095 tng_molecule_t *mol)
17097 tng_function_status stat;
17099 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17100 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17102 stat = tng_molecule_add(tng_data, name, mol);
17103 if(stat != TNG_SUCCESS)
17107 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17112 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17113 (tng_trajectory_t tng_data,
17114 const tng_molecule_t mol,
17115 int64_t *n_particles,
17120 char ***chain_names,
17121 int64_t **chain_ids)
17129 *n_particles = mol->n_atoms;
17131 *names = malloc(sizeof(char *) * *n_particles);
17132 *types = malloc(sizeof(char *) * *n_particles);
17133 *res_names = malloc(sizeof(char *) * *n_particles);
17134 *chain_names = malloc(sizeof(char *) * *n_particles);
17135 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17136 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17138 for(i = 0; i < *n_particles; i++)
17140 atom = &mol->atoms[i];
17141 res = atom->residue;
17142 chain = res->chain;
17143 (*names)[i] = malloc(strlen(atom->name));
17144 strcpy(*names[i], atom->name);
17145 (*types)[i] = malloc(strlen(atom->atom_type));
17146 strcpy(*types[i], atom->atom_type);
17147 (*res_names)[i] = malloc(strlen(res->name));
17148 strcpy(*res_names[i], res->name);
17149 (*chain_names)[i] = malloc(strlen(chain->name));
17150 strcpy(*chain_names[i], chain->name);
17151 (*res_ids)[i] = res->id;
17152 (*chain_ids)[i] = chain->id;
17155 return(TNG_SUCCESS);
17158 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17159 (tng_trajectory_t tng_data,
17160 tng_molecule_t mol,
17161 const int64_t n_particles,
17162 const char **names,
17163 const char **types,
17164 const char **res_names,
17165 const int64_t *res_ids,
17166 const char **chain_names,
17167 const int64_t *chain_ids)
17171 tng_residue_t residue;
17173 tng_function_status stat;
17175 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17176 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17177 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17178 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17179 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17180 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17181 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17183 for(i = 0; i < n_particles; i++)
17185 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17186 &chain) == TNG_FAILURE)
17188 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17190 if(stat != TNG_SUCCESS)
17195 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17196 &residue) == TNG_FAILURE)
17198 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17200 if(stat != TNG_SUCCESS)
17205 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17206 if(stat != TNG_SUCCESS)
17211 return(TNG_SUCCESS);
17214 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17215 (tng_trajectory_t tng_data,
17216 float **positions, int64_t *stride_length)
17218 int64_t n_frames, n_particles, n_values_per_frame;
17220 tng_function_status stat;
17222 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17223 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17224 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17226 stat = tng_num_frames_get(tng_data, &n_frames);
17227 if(stat != TNG_SUCCESS)
17232 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17233 0, n_frames - 1, TNG_USE_HASH,
17234 (void **)positions,
17237 &n_values_per_frame,
17243 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17244 (tng_trajectory_t tng_data,
17245 float **velocities, int64_t *stride_length)
17247 int64_t n_frames, n_particles, n_values_per_frame;
17249 tng_function_status stat;
17251 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17252 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17253 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17255 stat = tng_num_frames_get(tng_data, &n_frames);
17256 if(stat != TNG_SUCCESS)
17261 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17262 0, n_frames - 1, TNG_USE_HASH,
17263 (void **)velocities,
17266 &n_values_per_frame,
17272 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17273 (tng_trajectory_t tng_data,
17274 float **forces, int64_t *stride_length)
17276 int64_t n_frames, n_particles, n_values_per_frame;
17278 tng_function_status stat;
17280 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17281 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17282 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17284 stat = tng_num_frames_get(tng_data, &n_frames);
17285 if(stat != TNG_SUCCESS)
17290 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17291 0, n_frames - 1, TNG_USE_HASH,
17295 &n_values_per_frame,
17301 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17302 (tng_trajectory_t tng_data,
17304 int64_t *stride_length)
17306 int64_t n_frames, n_values_per_frame;
17308 tng_function_status stat;
17310 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17311 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17312 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17314 stat = tng_num_frames_get(tng_data, &n_frames);
17315 if(stat != TNG_SUCCESS)
17320 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17321 0, n_frames - 1, TNG_USE_HASH,
17322 (void **)box_shape,
17324 &n_values_per_frame,
17330 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17331 (tng_trajectory_t tng_data,
17332 const int64_t block_id,
17335 int64_t *retrieved_frame_number,
17336 double *retrieved_time)
17338 tng_trajectory_frame_set_t frame_set;
17339 tng_particle_data_t data = 0;
17340 tng_function_status stat;
17342 int64_t i, data_size, n_particles;
17346 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17347 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17348 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17349 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17350 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17352 frame_set = &tng_data->current_trajectory_frame_set;
17354 stat = tng_particle_data_find(tng_data, block_id, &data);
17355 if(stat != TNG_SUCCESS)
17357 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17358 file_pos = ftell(tng_data->input_file);
17359 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17361 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17362 file_pos = ftell(tng_data->input_file);
17364 if(stat != TNG_SUCCESS)
17368 stat = tng_particle_data_find(tng_data, block_id, &data);
17369 if(stat != TNG_SUCCESS)
17374 if(data->last_retrieved_frame < 0)
17376 fseek(tng_data->input_file,
17377 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17379 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17380 if(stat != TNG_SUCCESS)
17384 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17385 if(stat != TNG_SUCCESS)
17390 i = data->first_frame_with_data;
17394 if(data->n_frames == 1)
17396 i = data->last_retrieved_frame + 1;
17400 i = data->last_retrieved_frame + data->stride_length;
17402 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17404 stat = tng_frame_set_of_frame_find(tng_data, i);
17405 if(stat != TNG_SUCCESS)
17407 /* If the frame set search found the frame set after the starting
17408 * frame set there is a gap in the frame sets. So, even if the frame
17409 * was not found the next frame with data is still in the found
17411 if(stat == TNG_CRITICAL)
17415 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17417 return(TNG_FAILURE);
17419 i = frame_set->first_frame;
17422 if(data->last_retrieved_frame < frame_set->first_frame)
17424 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17425 if(stat != TNG_SUCCESS)
17431 data->last_retrieved_frame = i;
17432 *retrieved_frame_number = i;
17433 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17435 *retrieved_time = frame_set->first_frame_time +
17436 (i - frame_set->first_frame) *
17437 tng_data->time_per_frame;
17441 *retrieved_time = 0;
17444 if(data->stride_length > 1)
17446 i = (i - data->first_frame_with_data) / data->stride_length;
17450 i = (i - frame_set->first_frame);
17453 tng_num_particles_get(tng_data, &n_particles);
17455 *data_type = data->datatype;
17459 case TNG_CHAR_DATA:
17460 return(TNG_FAILURE);
17462 size = sizeof(int64_t);
17464 case TNG_FLOAT_DATA:
17465 size = sizeof(float);
17467 case TNG_DOUBLE_DATA:
17469 size = sizeof(double);
17472 data_size = size * n_particles * data->n_values_per_frame;
17474 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17475 // i, data_size, size, n_particles, data->n_values_per_frame);
17477 temp = realloc(*values, data_size);
17480 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17481 data_size, __FILE__, __LINE__);
17484 return(TNG_CRITICAL);
17489 memcpy(*values, (char *)data->values + i * data_size, data_size);
17491 return(TNG_SUCCESS);
17494 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17495 (tng_trajectory_t tng_data,
17496 const int64_t block_id,
17499 int64_t *retrieved_frame_number,
17500 double *retrieved_time)
17502 tng_trajectory_frame_set_t frame_set;
17503 tng_non_particle_data_t data = 0;
17504 tng_function_status stat;
17506 int64_t i, data_size;
17510 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17511 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17512 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17513 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17514 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17516 frame_set = &tng_data->current_trajectory_frame_set;
17518 stat = tng_data_find(tng_data, block_id, &data);
17519 if(stat != TNG_SUCCESS)
17521 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17522 file_pos = ftell(tng_data->input_file);
17523 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17525 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17526 file_pos = ftell(tng_data->input_file);
17528 if(stat != TNG_SUCCESS)
17532 stat = tng_data_find(tng_data, block_id, &data);
17533 if(stat != TNG_SUCCESS)
17538 if(data->last_retrieved_frame < 0)
17540 fseek(tng_data->input_file,
17541 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17543 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17544 if(stat != TNG_SUCCESS)
17548 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17549 if(stat != TNG_SUCCESS)
17554 i = data->first_frame_with_data;
17558 if(data->n_frames == 1)
17560 i = data->last_retrieved_frame + 1;
17564 i = data->last_retrieved_frame + data->stride_length;
17566 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17568 stat = tng_frame_set_of_frame_find(tng_data, i);
17569 if(stat != TNG_SUCCESS)
17571 /* If the frame set search found the frame set after the starting
17572 * frame set there is a gap in the frame sets. So, even if the frame
17573 * was not found the next frame with data is still in the found
17575 if(stat == TNG_CRITICAL)
17579 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
17581 return(TNG_FAILURE);
17583 i = frame_set->first_frame;
17586 if(data->last_retrieved_frame < frame_set->first_frame)
17588 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17589 if(stat != TNG_SUCCESS)
17595 data->last_retrieved_frame = i;
17596 *retrieved_frame_number = i;
17597 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17599 *retrieved_time = frame_set->first_frame_time +
17600 (i - frame_set->first_frame) *
17601 tng_data->time_per_frame;
17605 *retrieved_time = 0;
17608 if(data->stride_length > 1)
17610 i = (i - data->first_frame_with_data) / data->stride_length;
17614 i = (i - frame_set->first_frame);
17617 *data_type = data->datatype;
17621 case TNG_CHAR_DATA:
17622 return(TNG_FAILURE);
17624 size = sizeof(int64_t);
17626 case TNG_FLOAT_DATA:
17627 size = sizeof(float);
17629 case TNG_DOUBLE_DATA:
17631 size = sizeof(double);
17634 data_size = size * data->n_values_per_frame;
17636 temp = realloc(*values, data_size);
17639 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17640 data_size, __FILE__, __LINE__);
17643 return(TNG_CRITICAL);
17648 memcpy(*values, (char *)data->values + i * data_size, data_size);
17650 return(TNG_SUCCESS);
17653 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17654 (tng_trajectory_t tng_data,
17655 const int64_t first_frame,
17656 const int64_t last_frame,
17658 int64_t *stride_length)
17660 int64_t n_particles, n_values_per_frame;
17662 tng_function_status stat;
17664 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17665 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17666 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17667 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17669 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17670 first_frame, last_frame,
17672 (void **)positions,
17675 &n_values_per_frame,
17681 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17682 (tng_trajectory_t tng_data,
17683 const int64_t first_frame,
17684 const int64_t last_frame,
17685 float **velocities,
17686 int64_t *stride_length)
17688 int64_t n_particles, n_values_per_frame;
17690 tng_function_status stat;
17692 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17693 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17694 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17695 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17697 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17698 first_frame, last_frame,
17700 (void **)velocities,
17703 &n_values_per_frame,
17709 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17710 (tng_trajectory_t tng_data,
17711 const int64_t first_frame,
17712 const int64_t last_frame,
17714 int64_t *stride_length)
17716 int64_t n_particles, n_values_per_frame;
17718 tng_function_status stat;
17720 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17721 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17722 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17723 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17725 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17726 first_frame, last_frame,
17731 &n_values_per_frame,
17737 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17738 (tng_trajectory_t tng_data,
17739 const int64_t first_frame,
17740 const int64_t last_frame,
17742 int64_t *stride_length)
17744 int64_t n_values_per_frame;
17746 tng_function_status stat;
17748 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17749 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17750 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17751 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17753 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17754 first_frame, last_frame,
17756 (void **)box_shape,
17758 &n_values_per_frame,
17764 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17765 (tng_trajectory_t tng_data,
17767 const int64_t n_values_per_frame,
17768 const int64_t block_id,
17769 const char *block_name,
17770 const char particle_dependency,
17771 const char compression)
17773 tng_trajectory_frame_set_t frame_set;
17774 tng_particle_data_t p_data;
17775 tng_non_particle_data_t np_data;
17776 int64_t n_particles, n_frames;
17777 tng_function_status stat;
17779 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17780 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17784 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17785 i, __FILE__, __LINE__);
17786 return(TNG_FAILURE);
17789 frame_set = &tng_data->current_trajectory_frame_set;
17791 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17793 n_frames = tng_data->frame_set_n_frames;
17795 stat = tng_frame_set_new(tng_data, 0, n_frames);
17796 if(stat != TNG_SUCCESS)
17798 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17805 n_frames = frame_set->n_frames;
17808 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17810 tng_num_particles_get(tng_data, &n_particles);
17811 if(n_particles <= 0)
17813 return(TNG_FAILURE);
17816 if(tng_particle_data_find(tng_data, block_id, &p_data)
17819 stat = tng_particle_data_block_add(tng_data, block_id,
17822 TNG_TRAJECTORY_BLOCK,
17823 n_frames, n_values_per_frame, i,
17826 if(stat != TNG_SUCCESS)
17828 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17829 __FILE__, __LINE__);
17832 p_data = &frame_set->tr_particle_data[frame_set->
17833 n_particle_data_blocks - 1];
17834 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17836 n_values_per_frame);
17837 if(stat != TNG_SUCCESS)
17839 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17840 __FILE__, __LINE__);
17846 if(p_data->stride_length != i)
17848 p_data->stride_length = i;
17849 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17851 n_values_per_frame);
17852 if(stat != TNG_SUCCESS)
17854 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17855 __FILE__, __LINE__);
17863 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17865 stat = tng_data_block_add(tng_data, block_id, block_name,
17866 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17867 n_frames, n_values_per_frame,
17868 i, compression, 0);
17869 if(stat != TNG_SUCCESS)
17871 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17872 __FILE__, __LINE__);
17875 np_data = &frame_set->tr_data[frame_set->
17876 n_data_blocks - 1];
17877 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17878 i, n_values_per_frame);
17879 if(stat != TNG_SUCCESS)
17881 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17882 __FILE__, __LINE__);
17888 if(np_data->stride_length != i)
17890 np_data->stride_length = i;
17891 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17892 i, n_values_per_frame);
17893 if(stat != TNG_SUCCESS)
17895 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17896 __FILE__, __LINE__);
17903 return(TNG_SUCCESS);
17906 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17907 (tng_trajectory_t tng_data,
17909 const int64_t n_values_per_frame,
17910 const int64_t block_id,
17911 const char *block_name,
17912 const char particle_dependency,
17913 const char compression)
17915 tng_trajectory_frame_set_t frame_set;
17916 tng_particle_data_t p_data;
17917 tng_non_particle_data_t np_data;
17918 int64_t n_particles, n_frames;
17919 tng_function_status stat;
17921 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17922 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17926 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17927 i, __FILE__, __LINE__);
17928 return(TNG_FAILURE);
17931 frame_set = &tng_data->current_trajectory_frame_set;
17933 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17935 n_frames = tng_data->frame_set_n_frames;
17937 stat = tng_frame_set_new(tng_data, 0, n_frames);
17938 if(stat != TNG_SUCCESS)
17940 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17947 n_frames = frame_set->n_frames;
17950 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17952 tng_num_particles_get(tng_data, &n_particles);
17954 if(n_particles <= 0)
17956 return(TNG_FAILURE);
17959 if(tng_particle_data_find(tng_data, block_id, &p_data)
17962 stat = tng_particle_data_block_add(tng_data, block_id,
17965 TNG_TRAJECTORY_BLOCK,
17966 n_frames, n_values_per_frame, i,
17969 if(stat != TNG_SUCCESS)
17971 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17972 __FILE__, __LINE__);
17975 p_data = &frame_set->tr_particle_data[frame_set->
17976 n_particle_data_blocks - 1];
17977 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17979 n_values_per_frame);
17980 if(stat != TNG_SUCCESS)
17982 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17983 __FILE__, __LINE__);
17989 p_data->stride_length = i;
17994 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17996 stat = tng_data_block_add(tng_data, block_id, block_name,
17997 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
17998 n_frames, n_values_per_frame,
17999 i, compression, 0);
18000 if(stat != TNG_SUCCESS)
18002 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18003 __FILE__, __LINE__);
18006 np_data = &frame_set->tr_data[frame_set->
18007 n_data_blocks - 1];
18008 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18009 i, n_values_per_frame);
18010 if(stat != TNG_SUCCESS)
18012 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18013 __FILE__, __LINE__);
18019 np_data->stride_length = i;
18023 return(TNG_SUCCESS);
18026 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
18027 (tng_trajectory_t tng_data,
18029 const int64_t n_values_per_frame,
18030 const int64_t block_id,
18031 const char *block_name,
18032 const char particle_dependency,
18033 const char compression)
18035 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
18036 "See documentation. %s: %d", __FILE__, __LINE__);
18037 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
18038 block_id, block_name,
18039 particle_dependency,
18042 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18043 (tng_trajectory_t tng_data,
18046 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18047 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18049 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18050 TNG_TRAJ_POSITIONS,
18052 TNG_PARTICLE_BLOCK_DATA,
18053 TNG_TNG_COMPRESSION));
18056 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18057 (tng_trajectory_t tng_data,
18060 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18061 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18063 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18064 TNG_TRAJ_POSITIONS,
18066 TNG_PARTICLE_BLOCK_DATA,
18067 TNG_TNG_COMPRESSION));
18070 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18071 (tng_trajectory_t tng_data,
18074 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18075 "See documentation. %s: %d", __FILE__, __LINE__);
18076 return(tng_util_pos_write_interval_set(tng_data, i));
18079 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18080 (tng_trajectory_t tng_data,
18083 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18084 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18086 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18087 TNG_TRAJ_VELOCITIES,
18089 TNG_PARTICLE_BLOCK_DATA,
18090 TNG_TNG_COMPRESSION));
18093 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18094 (tng_trajectory_t tng_data,
18097 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18098 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18100 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18101 TNG_TRAJ_VELOCITIES,
18103 TNG_PARTICLE_BLOCK_DATA,
18104 TNG_TNG_COMPRESSION));
18107 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18108 (tng_trajectory_t tng_data,
18111 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18112 "See documentation. %s: %d", __FILE__, __LINE__);
18113 return(tng_util_vel_write_interval_set(tng_data, i));
18116 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18117 (tng_trajectory_t tng_data,
18120 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18121 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18123 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18126 TNG_PARTICLE_BLOCK_DATA,
18127 TNG_GZIP_COMPRESSION));
18130 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18131 (tng_trajectory_t tng_data,
18134 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18135 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18137 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18140 TNG_PARTICLE_BLOCK_DATA,
18141 TNG_GZIP_COMPRESSION));
18144 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18145 (tng_trajectory_t tng_data,
18148 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18149 "See documentation. %s: %d", __FILE__, __LINE__);
18150 return(tng_util_force_write_interval_set(tng_data, i));
18153 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18154 (tng_trajectory_t tng_data,
18157 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18158 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18160 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18161 TNG_TRAJ_BOX_SHAPE,
18163 TNG_NON_PARTICLE_BLOCK_DATA,
18164 TNG_GZIP_COMPRESSION));
18167 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18168 (tng_trajectory_t tng_data,
18171 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18172 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18174 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18175 TNG_TRAJ_BOX_SHAPE,
18177 TNG_NON_PARTICLE_BLOCK_DATA,
18178 TNG_GZIP_COMPRESSION));
18181 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18182 (tng_trajectory_t tng_data,
18185 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18186 "See documentation. %s: %d", __FILE__, __LINE__);
18187 return(tng_util_box_shape_write_interval_set(tng_data, i));
18190 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18191 (tng_trajectory_t tng_data,
18192 const int64_t frame_nr,
18193 const float *values,
18194 const int64_t n_values_per_frame,
18195 const int64_t block_id,
18196 const char *block_name,
18197 const char particle_dependency,
18198 const char compression)
18200 tng_trajectory_frame_set_t frame_set;
18201 tng_particle_data_t p_data;
18202 tng_non_particle_data_t np_data;
18203 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18204 int64_t last_frame;
18205 int is_first_frame_flag = 0;
18206 char block_type_flag;
18207 tng_function_status stat;
18209 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18210 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18211 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18213 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18215 tng_num_particles_get(tng_data, &n_particles);
18216 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18221 return(TNG_FAILURE);
18224 frame_set = &tng_data->current_trajectory_frame_set;
18228 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18229 n_frames = stride_length = 1;
18233 block_type_flag = TNG_TRAJECTORY_BLOCK;
18235 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18237 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18238 if(stat != TNG_SUCCESS)
18240 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18245 last_frame = frame_set->first_frame +
18246 frame_set->n_frames - 1;
18247 if(frame_nr > last_frame)
18249 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18250 if(stat != TNG_SUCCESS)
18252 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18256 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18258 last_frame = frame_nr - 1;
18260 stat = tng_frame_set_new(tng_data, last_frame + 1,
18261 tng_data->frame_set_n_frames);
18262 if(stat != TNG_SUCCESS)
18264 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18269 if(frame_set->n_unwritten_frames == 0)
18271 is_first_frame_flag = 1;
18273 frame_set->n_unwritten_frames = frame_nr -
18274 frame_set->first_frame + 1;
18276 n_frames = frame_set->n_frames;
18279 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18281 if(tng_particle_data_find(tng_data, block_id, &p_data)
18284 stat = tng_particle_data_block_add(tng_data, block_id,
18288 n_frames, n_values_per_frame,
18292 if(stat != TNG_SUCCESS)
18294 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18295 __FILE__, __LINE__);
18298 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18300 p_data = &frame_set->tr_particle_data[frame_set->
18301 n_particle_data_blocks - 1];
18305 p_data = &tng_data->non_tr_particle_data[tng_data->
18306 n_particle_data_blocks - 1];
18308 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18309 stride_length, n_particles,
18310 n_values_per_frame);
18311 if(stat != TNG_SUCCESS)
18313 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18314 __FILE__, __LINE__);
18319 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18321 stride_length = p_data->stride_length;
18323 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18325 p_data->first_frame_with_data = frame_nr;
18330 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18333 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18334 n_values_per_frame, values, sizeof(float) *
18335 n_particles * n_values_per_frame);
18339 memcpy(p_data->values, values, sizeof(float) * n_particles *
18340 n_values_per_frame);
18345 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18347 stat = tng_data_block_add(tng_data, block_id, block_name,
18348 TNG_FLOAT_DATA, block_type_flag,
18349 n_frames, n_values_per_frame,
18350 stride_length, compression, 0);
18351 if(stat != TNG_SUCCESS)
18353 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18354 __FILE__, __LINE__);
18357 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18359 np_data = &frame_set->tr_data[frame_set->
18360 n_data_blocks - 1];
18364 np_data = &tng_data->non_tr_data[tng_data->
18365 n_data_blocks - 1];
18367 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18368 stride_length, n_values_per_frame);
18369 if(stat != TNG_SUCCESS)
18371 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18372 __FILE__, __LINE__);
18377 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18379 stride_length = np_data->stride_length;
18381 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18383 np_data->first_frame_with_data = frame_nr;
18388 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18391 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18392 n_values_per_frame, values, sizeof(float) *
18393 n_values_per_frame);
18397 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18401 return(TNG_SUCCESS);
18404 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18405 (tng_trajectory_t tng_data,
18406 const int64_t frame_nr,
18407 const double *values,
18408 const int64_t n_values_per_frame,
18409 const int64_t block_id,
18410 const char *block_name,
18411 const char particle_dependency,
18412 const char compression)
18414 tng_trajectory_frame_set_t frame_set;
18415 tng_particle_data_t p_data;
18416 tng_non_particle_data_t np_data;
18417 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18418 int64_t last_frame;
18419 int is_first_frame_flag = 0;
18420 char block_type_flag;
18421 tng_function_status stat;
18423 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18424 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18425 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18427 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18429 tng_num_particles_get(tng_data, &n_particles);
18430 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18435 return(TNG_FAILURE);
18438 frame_set = &tng_data->current_trajectory_frame_set;
18442 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18443 n_frames = stride_length = 1;
18447 block_type_flag = TNG_TRAJECTORY_BLOCK;
18449 n_frames = tng_data->frame_set_n_frames;
18451 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18453 stat = tng_frame_set_new(tng_data, 0, n_frames);
18454 if(stat != TNG_SUCCESS)
18456 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18463 n_frames = frame_set->n_frames;
18465 last_frame = frame_set->first_frame +
18466 frame_set->n_frames - 1;
18467 if(frame_nr > last_frame)
18469 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18470 if(stat != TNG_SUCCESS)
18472 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18476 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18478 last_frame = frame_nr - 1;
18480 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18481 if(stat != TNG_SUCCESS)
18483 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18488 if(frame_set->n_unwritten_frames == 0)
18490 is_first_frame_flag = 1;
18492 frame_set->n_unwritten_frames = frame_nr -
18493 frame_set->first_frame + 1;
18496 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18498 if(tng_particle_data_find(tng_data, block_id, &p_data)
18501 stat = tng_particle_data_block_add(tng_data, block_id,
18505 n_frames, n_values_per_frame,
18509 if(stat != TNG_SUCCESS)
18511 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18512 __FILE__, __LINE__);
18515 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18517 p_data = &frame_set->tr_particle_data[frame_set->
18518 n_particle_data_blocks - 1];
18522 p_data = &tng_data->non_tr_particle_data[tng_data->
18523 n_particle_data_blocks - 1];
18525 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18526 stride_length, n_particles,
18527 n_values_per_frame);
18528 if(stat != TNG_SUCCESS)
18530 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18531 __FILE__, __LINE__);
18536 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18538 stride_length = p_data->stride_length;
18540 if(is_first_frame_flag)
18542 p_data->first_frame_with_data = frame_nr;
18547 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18550 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18551 n_values_per_frame, values, sizeof(double) *
18552 n_particles * n_values_per_frame);
18556 memcpy(p_data->values, values, sizeof(double) * n_particles *
18557 n_values_per_frame);
18562 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18564 stat = tng_data_block_add(tng_data, block_id, block_name,
18565 TNG_DOUBLE_DATA, block_type_flag,
18566 n_frames, n_values_per_frame,
18567 stride_length, compression, 0);
18568 if(stat != TNG_SUCCESS)
18570 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18571 __FILE__, __LINE__);
18574 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18576 np_data = &frame_set->tr_data[frame_set->
18577 n_data_blocks - 1];
18581 np_data = &tng_data->non_tr_data[tng_data->
18582 n_data_blocks - 1];
18584 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18585 stride_length, n_values_per_frame);
18586 if(stat != TNG_SUCCESS)
18588 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18589 __FILE__, __LINE__);
18594 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18596 stride_length = np_data->stride_length;
18598 if(is_first_frame_flag)
18600 np_data->first_frame_with_data = frame_nr;
18605 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18608 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18609 n_values_per_frame, values, sizeof(double) *
18610 n_values_per_frame);
18614 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18618 return(TNG_SUCCESS);
18621 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18622 (tng_trajectory_t tng_data,
18623 const int64_t frame_nr,
18624 const float *positions)
18626 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18627 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18628 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18630 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18631 TNG_TRAJ_POSITIONS, "POSITIONS",
18632 TNG_PARTICLE_BLOCK_DATA,
18633 TNG_TNG_COMPRESSION));
18636 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18637 (tng_trajectory_t tng_data,
18638 const int64_t frame_nr,
18639 const double *positions)
18641 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18642 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18643 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18645 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18646 TNG_TRAJ_POSITIONS, "POSITIONS",
18647 TNG_PARTICLE_BLOCK_DATA,
18648 TNG_TNG_COMPRESSION));
18651 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18652 (tng_trajectory_t tng_data,
18653 const int64_t frame_nr,
18654 const float *velocities)
18656 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18657 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18658 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18660 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18661 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18662 TNG_PARTICLE_BLOCK_DATA,
18663 TNG_TNG_COMPRESSION));
18666 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18667 (tng_trajectory_t tng_data,
18668 const int64_t frame_nr,
18669 const double *velocities)
18671 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18672 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18673 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18675 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18676 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18677 TNG_PARTICLE_BLOCK_DATA,
18678 TNG_TNG_COMPRESSION));
18681 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18682 (tng_trajectory_t tng_data,
18683 const int64_t frame_nr,
18684 const float *forces)
18686 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18687 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18688 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18690 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18691 TNG_TRAJ_FORCES, "FORCES",
18692 TNG_PARTICLE_BLOCK_DATA,
18693 TNG_GZIP_COMPRESSION));
18696 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18697 (tng_trajectory_t tng_data,
18698 const int64_t frame_nr,
18699 const double *forces)
18701 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18702 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18703 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18705 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18706 TNG_TRAJ_FORCES, "FORCES",
18707 TNG_PARTICLE_BLOCK_DATA,
18708 TNG_GZIP_COMPRESSION));
18711 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18712 (tng_trajectory_t tng_data,
18713 const int64_t frame_nr,
18714 const float *box_shape)
18716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18717 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18718 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18720 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18721 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18722 TNG_NON_PARTICLE_BLOCK_DATA,
18723 TNG_GZIP_COMPRESSION));
18726 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18727 (tng_trajectory_t tng_data,
18728 const int64_t frame_nr,
18729 const double *box_shape)
18731 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18732 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18733 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18735 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18736 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18737 TNG_NON_PARTICLE_BLOCK_DATA,
18738 TNG_GZIP_COMPRESSION));
18741 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18742 (tng_trajectory_t tng_data,
18743 const int64_t frame_nr,
18745 const float *values,
18746 const int64_t n_values_per_frame,
18747 const int64_t block_id,
18748 const char *block_name,
18749 const char particle_dependency,
18750 const char compression)
18752 tng_trajectory_frame_set_t frame_set;
18753 tng_function_status stat;
18755 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18756 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18757 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18758 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18760 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18761 block_id, block_name,
18762 particle_dependency,
18765 if(stat != TNG_SUCCESS)
18770 frame_set = &tng_data->current_trajectory_frame_set;
18772 /* first_frame_time is -1 when it is not yet set. */
18773 if(frame_set->first_frame_time < -0.1)
18775 if(frame_nr > frame_set->first_frame)
18777 stat = tng_frame_set_first_frame_time_set(tng_data,
18780 frame_set->first_frame) *
18781 tng_data->time_per_frame);
18785 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18791 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18792 (tng_trajectory_t tng_data,
18793 const int64_t frame_nr,
18795 const double *values,
18796 const int64_t n_values_per_frame,
18797 const int64_t block_id,
18798 const char *block_name,
18799 const char particle_dependency,
18800 const char compression)
18802 tng_trajectory_frame_set_t frame_set;
18803 tng_function_status stat;
18805 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18806 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18807 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18808 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18810 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18811 block_id, block_name,
18812 particle_dependency,
18815 if(stat != TNG_SUCCESS)
18820 frame_set = &tng_data->current_trajectory_frame_set;
18822 /* first_frame_time is -1 when it is not yet set. */
18823 if(frame_set->first_frame_time < -0.1)
18825 if(frame_nr > frame_set->first_frame)
18827 stat = tng_frame_set_first_frame_time_set(tng_data,
18830 frame_set->first_frame) *
18831 tng_data->time_per_frame);
18835 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18841 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18842 (tng_trajectory_t tng_data,
18843 const int64_t frame_nr,
18845 const float *positions)
18847 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18848 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18849 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18850 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18852 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18853 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18854 TNG_PARTICLE_BLOCK_DATA,
18855 TNG_TNG_COMPRESSION));
18858 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18859 (tng_trajectory_t tng_data,
18860 const int64_t frame_nr,
18862 const double *positions)
18864 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18865 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18866 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18867 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18869 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18871 TNG_TRAJ_POSITIONS,
18873 TNG_PARTICLE_BLOCK_DATA,
18874 TNG_TNG_COMPRESSION));
18877 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18878 (tng_trajectory_t tng_data,
18879 const int64_t frame_nr,
18881 const float *velocities)
18883 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18884 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18885 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18886 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18888 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18890 TNG_TRAJ_VELOCITIES,
18892 TNG_PARTICLE_BLOCK_DATA,
18893 TNG_TNG_COMPRESSION));
18896 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18897 (tng_trajectory_t tng_data,
18898 const int64_t frame_nr,
18900 const double *velocities)
18902 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18903 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18904 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18905 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18907 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18909 TNG_TRAJ_VELOCITIES,
18911 TNG_PARTICLE_BLOCK_DATA,
18912 TNG_TNG_COMPRESSION));
18915 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18916 (tng_trajectory_t tng_data,
18917 const int64_t frame_nr,
18919 const float *forces)
18921 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18922 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18923 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18924 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18926 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18927 3, TNG_TRAJ_FORCES, "FORCES",
18928 TNG_PARTICLE_BLOCK_DATA,
18929 TNG_GZIP_COMPRESSION));
18932 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18933 (tng_trajectory_t tng_data,
18934 const int64_t frame_nr,
18936 const double *forces)
18938 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18939 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18940 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18941 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18943 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18945 TNG_TRAJ_FORCES, "FORCES",
18946 TNG_PARTICLE_BLOCK_DATA,
18947 TNG_GZIP_COMPRESSION));
18950 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18951 (tng_trajectory_t tng_data,
18952 const int64_t frame_nr,
18954 const float *box_shape)
18956 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18957 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18958 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18959 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18961 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18962 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18963 TNG_NON_PARTICLE_BLOCK_DATA,
18964 TNG_GZIP_COMPRESSION));
18967 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18968 (tng_trajectory_t tng_data,
18969 const int64_t frame_nr,
18971 const double *box_shape)
18973 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18974 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18975 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18976 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18978 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18979 time, box_shape, 9,
18980 TNG_TRAJ_BOX_SHAPE,
18982 TNG_NON_PARTICLE_BLOCK_DATA,
18983 TNG_GZIP_COMPRESSION));
18986 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18987 (tng_trajectory_t tng_data,
18988 const int64_t block_id,
18992 tng_trajectory_frame_set_t frame_set;
18993 tng_particle_data_t p_data = 0;
18994 tng_non_particle_data_t np_data = 0;
18995 tng_function_status stat;
18997 int block_type = -1;
18999 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19000 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
19001 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
19003 frame_set = &tng_data->current_trajectory_frame_set;
19005 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19006 if(stat == TNG_SUCCESS)
19008 block_type = TNG_PARTICLE_BLOCK_DATA;
19012 stat = tng_data_find(tng_data, block_id, &np_data);
19013 if(stat == TNG_SUCCESS)
19015 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19019 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19020 if(stat != TNG_SUCCESS)
19024 stat = tng_particle_data_find(tng_data, block_id, &p_data);
19025 if(stat == TNG_SUCCESS)
19027 block_type = TNG_PARTICLE_BLOCK_DATA;
19031 stat = tng_data_find(tng_data, block_id, &np_data);
19032 if(stat == TNG_SUCCESS)
19034 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19043 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19045 if(p_data->last_retrieved_frame < 0)
19047 i = p_data->first_frame_with_data;
19051 i = p_data->last_retrieved_frame;
19054 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19056 if(np_data->last_retrieved_frame < 0)
19058 i = np_data->first_frame_with_data;
19062 i = np_data->last_retrieved_frame;
19067 return(TNG_FAILURE);
19069 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
19071 stat = tng_frame_set_of_frame_find(tng_data, i);
19072 if(stat != TNG_SUCCESS)
19076 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
19077 if(stat != TNG_SUCCESS)
19079 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19080 __FILE__, __LINE__);
19084 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19086 *codec_id = p_data->codec_id;
19087 *factor = p_data->compression_multiplier;
19089 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
19091 *codec_id = np_data->codec_id;
19092 *factor = np_data->compression_multiplier;
19094 return(TNG_SUCCESS);
19097 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19098 (tng_trajectory_t tng_data,
19099 int64_t current_frame,
19100 const int64_t n_requested_data_block_ids,
19101 const int64_t *requested_data_block_ids,
19102 int64_t *next_frame,
19103 int64_t *n_data_blocks_in_next_frame,
19104 int64_t **data_block_ids_in_next_frame)
19106 tng_trajectory_frame_set_t frame_set;
19107 tng_function_status stat;
19108 tng_particle_data_t p_data;
19109 tng_non_particle_data_t np_data;
19110 tng_gen_block_t block;
19111 int64_t i, j, block_id, *temp;
19112 int64_t data_frame, frame_diff, min_diff;
19113 int64_t size, frame_set_file_pos;
19114 int found, read_all = 0;
19117 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19118 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19119 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19120 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19122 if(n_requested_data_block_ids)
19124 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.");
19125 size = sizeof(int64_t) * n_requested_data_block_ids;
19126 temp = realloc(*data_block_ids_in_next_frame, size);
19129 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19130 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19131 __FILE__, __LINE__);
19132 free(*data_block_ids_in_next_frame);
19133 *data_block_ids_in_next_frame = 0;
19134 return(TNG_CRITICAL);
19136 *data_block_ids_in_next_frame = temp;
19139 frame_set = &tng_data->current_trajectory_frame_set;
19141 current_frame += 1;
19143 if(current_frame < frame_set->first_frame ||
19144 current_frame >= frame_set->first_frame + frame_set->n_frames)
19146 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19147 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19148 if(stat != TNG_SUCCESS)
19150 /* If the frame set search found the frame set after the starting
19151 * frame set there is a gap in the frame sets. So, even if the frame
19152 * was not found the next frame with data is still in the found
19154 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19155 frame_set_file_pos)
19159 current_frame = frame_set->first_frame;
19163 /* Check for data blocks only if they have not already been found. */
19164 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19166 file_pos = ftell(tng_data->input_file);
19167 if(file_pos < tng_data->input_file_len)
19169 tng_block_init(&block);
19170 stat = tng_block_header_read(tng_data, block);
19171 while(file_pos < tng_data->input_file_len &&
19172 stat != TNG_CRITICAL &&
19173 block->id != TNG_TRAJECTORY_FRAME_SET &&
19176 stat = tng_block_read_next(tng_data, block,
19178 if(stat != TNG_CRITICAL)
19180 file_pos = ftell(tng_data->input_file);
19181 if(file_pos < tng_data->input_file_len)
19183 stat = tng_block_header_read(tng_data, block);
19187 tng_block_destroy(&block);
19188 if(stat == TNG_CRITICAL)
19190 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
19191 file_pos, __FILE__, __LINE__);
19200 *n_data_blocks_in_next_frame = 0;
19202 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19204 p_data = &frame_set->tr_particle_data[i];
19205 block_id = p_data->block_id;
19207 if(n_requested_data_block_ids > 0)
19210 for(j = 0; j < n_requested_data_block_ids; j++)
19212 if(block_id == requested_data_block_ids[j])
19224 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19225 p_data->last_retrieved_frame >=
19226 frame_set->first_frame + frame_set->n_frames))
19228 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19229 TNG_USE_HASH, block_id);
19230 if(stat == TNG_CRITICAL)
19232 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19233 __FILE__, __LINE__);
19236 if(stat == TNG_FAILURE)
19241 if(frame_set->first_frame != current_frame &&
19242 p_data->last_retrieved_frame >= 0)
19244 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19248 data_frame = p_data->first_frame_with_data;
19250 frame_diff = data_frame - current_frame;
19255 if(min_diff == -1 || frame_diff <= min_diff)
19257 if(frame_diff < min_diff)
19259 *n_data_blocks_in_next_frame = 1;
19263 *n_data_blocks_in_next_frame += 1;
19265 if(n_requested_data_block_ids <= 0)
19267 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19268 temp = realloc(*data_block_ids_in_next_frame, size);
19271 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19272 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19273 __FILE__, __LINE__);
19274 free(*data_block_ids_in_next_frame);
19275 *data_block_ids_in_next_frame = 0;
19276 return(TNG_CRITICAL);
19278 *data_block_ids_in_next_frame = temp;
19282 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19284 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19286 min_diff = frame_diff;
19289 for(i = 0; i < frame_set->n_data_blocks; i++)
19291 np_data = &frame_set->tr_data[i];
19292 block_id = np_data->block_id;
19294 if(n_requested_data_block_ids > 0)
19297 for(j = 0; j < n_requested_data_block_ids; j++)
19299 if(block_id == requested_data_block_ids[j])
19311 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19312 np_data->last_retrieved_frame >=
19313 frame_set->first_frame + frame_set->n_frames))
19315 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19316 TNG_USE_HASH, block_id);
19317 if(stat == TNG_CRITICAL)
19319 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19320 __FILE__, __LINE__);
19323 if(stat == TNG_FAILURE)
19328 if(frame_set->first_frame != current_frame &&
19329 np_data->last_retrieved_frame >= 0)
19331 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19335 data_frame = np_data->first_frame_with_data;
19337 frame_diff = data_frame - current_frame;
19342 if(min_diff == -1 || frame_diff <= min_diff)
19344 if(frame_diff < min_diff)
19346 *n_data_blocks_in_next_frame = 1;
19350 *n_data_blocks_in_next_frame += 1;
19352 if(n_requested_data_block_ids <= 0)
19354 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19355 temp = realloc(*data_block_ids_in_next_frame, size);
19358 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19359 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19360 __FILE__, __LINE__);
19361 free(*data_block_ids_in_next_frame);
19362 *data_block_ids_in_next_frame = 0;
19363 return(TNG_CRITICAL);
19365 *data_block_ids_in_next_frame = temp;
19369 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19371 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19373 min_diff = frame_diff;
19378 return(TNG_FAILURE);
19380 *next_frame = current_frame + min_diff;
19382 return(TNG_SUCCESS);
19386 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19387 (tng_trajectory_t tng_data,
19388 int64_t *n_data_blocks,
19389 int64_t **data_block_ids,
19390 char ***data_block_names,
19391 int64_t **stride_lengths,
19392 int64_t **n_values_per_frame,
19393 char **block_types,
19394 char **dependencies,
19395 char **compressions)
19397 tng_gen_block_t block;
19398 long orig_file_pos, file_pos;
19400 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19401 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19402 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19403 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19404 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19406 orig_file_pos = ftell(tng_data->input_file);
19408 if(!tng_data->input_file_len)
19410 fseek(tng_data->input_file, 0, SEEK_END);
19411 tng_data->input_file_len = ftell(tng_data->input_file);
19414 fseek(tng_data->input_file, 0, SEEK_SET);
19417 *n_data_blocks = 0;
19419 tng_block_init(&block);
19421 while(file_pos < tng_data->input_file_len &&
19422 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19424 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19428 file_pos += (long)(block->block_contents_size + block->header_contents_size);
19429 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
19432 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
19434 return(TNG_SUCCESS);
19437 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19438 (tng_trajectory_t tng_data,
19439 const int64_t prev_frame)
19441 tng_function_status stat;
19442 FILE *temp = tng_data->input_file;
19444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19445 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19447 tng_data->input_file = tng_data->output_file;
19449 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19450 if(stat != TNG_SUCCESS)
19455 tng_data->current_trajectory_frame_set_output_file_pos =
19456 tng_data->current_trajectory_frame_set_input_file_pos;
19458 tng_data->input_file = temp;
19460 return(TNG_SUCCESS);