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 "../../include/tng_io.h"
26 #include "../../include/md5.h"
27 #include "../../include/compression/tng_compress.h"
28 #include "../include/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,
4766 int64_t algo_find_n_frames;
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 if(block->id == TNG_TRAJ_POSITIONS)
4796 /* If there is only one frame in this frame set and there might be more
4797 * do not store the algorithm as the compression algorithm, but find
4798 * the best one without storing it */
4799 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4801 nalgo = tng_compress_nalgo();
4802 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4803 if(type == TNG_FLOAT_DATA)
4805 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
4814 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
4821 else if(!tng_data->compress_algo_pos)
4825 algo_find_n_frames = 5;
4829 algo_find_n_frames = n_frames;
4832 nalgo = tng_compress_nalgo();
4833 tng_data->compress_algo_pos=malloc(nalgo *
4834 sizeof *tng_data->compress_algo_pos);
4835 if(type == TNG_FLOAT_DATA)
4837 dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
4838 (int)algo_find_n_frames,
4844 if(algo_find_n_frames < n_frames)
4846 dest = tng_compress_pos_float(start_pos, (int)n_particles,
4849 0, tng_data->compress_algo_pos,
4855 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
4856 (int)algo_find_n_frames,
4862 if(algo_find_n_frames < n_frames)
4864 dest = tng_compress_pos(start_pos, (int)n_particles,
4867 tng_data->compress_algo_pos,
4874 if(type == TNG_FLOAT_DATA)
4876 dest = tng_compress_pos_float(start_pos, (int)n_particles,
4879 tng_data->compress_algo_pos, &new_len);
4883 dest = tng_compress_pos(start_pos, (int)n_particles,
4886 tng_data->compress_algo_pos,
4891 else if(block->id == TNG_TRAJ_VELOCITIES)
4893 /* If there is only one frame in this frame set and there might be more
4894 * do not store the algorithm as the compression algorithm, but find
4895 * the best one without storing it */
4896 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4898 nalgo = tng_compress_nalgo();
4899 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4900 if(type == TNG_FLOAT_DATA)
4902 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4911 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4918 else if(!tng_data->compress_algo_vel)
4922 algo_find_n_frames = 5;
4926 algo_find_n_frames = n_frames;
4929 nalgo = tng_compress_nalgo();
4930 tng_data->compress_algo_vel=malloc(nalgo *
4931 sizeof *tng_data->compress_algo_vel);
4933 if(type == TNG_FLOAT_DATA)
4935 dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
4936 (int)algo_find_n_frames,
4941 if(algo_find_n_frames < n_frames)
4943 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4946 0, tng_data->compress_algo_vel,
4952 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4953 (int)algo_find_n_frames,
4958 if(algo_find_n_frames < n_frames)
4960 dest = tng_compress_vel(start_pos, (int)n_particles,
4963 0, tng_data->compress_algo_vel,
4970 if(type == TNG_FLOAT_DATA)
4972 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4981 dest = tng_compress_vel(start_pos, (int)n_particles,
4992 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4993 return(TNG_FAILURE);
4996 offset = (unsigned long)((char *)start_pos - block->block_contents);
5003 block->block_contents_size = new_len + offset;
5005 temp = realloc(block->block_contents, block->block_contents_size);
5008 free(block->block_contents);
5009 block->block_contents = 0;
5010 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5011 block->block_contents_size, __FILE__, __LINE__);
5012 return(TNG_CRITICAL);
5014 block->block_contents = temp;
5017 memcpy(temp + offset, dest, new_len);
5022 fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
5023 return(TNG_FAILURE);
5026 return(TNG_SUCCESS);
5029 static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
5030 tng_gen_block_t block,
5033 const unsigned long uncompressed_len)
5038 unsigned long offset;
5042 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
5044 if(block->id != TNG_TRAJ_POSITIONS &&
5045 block->id != TNG_TRAJ_VELOCITIES)
5047 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
5049 return(TNG_FAILURE);
5051 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
5053 fprintf(stderr, "TNG library: Data type not supported.\n");
5054 return(TNG_FAILURE);
5057 if(type == TNG_FLOAT_DATA)
5059 f_dest = malloc(uncompressed_len);
5062 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5063 uncompressed_len, __FILE__, __LINE__);
5064 return(TNG_CRITICAL);
5066 result = tng_compress_uncompress_float(start_pos, f_dest);
5070 d_dest = malloc(uncompressed_len);
5073 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5074 uncompressed_len, __FILE__, __LINE__);
5075 return(TNG_CRITICAL);
5077 result = tng_compress_uncompress(start_pos, d_dest);
5082 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
5083 return(TNG_FAILURE);
5086 offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
5088 block->block_contents_size = (int64_t)(uncompressed_len + offset);
5090 temp = realloc(block->block_contents, uncompressed_len + offset);
5093 free(block->block_contents);
5094 block->block_contents = 0;
5103 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5104 block->block_contents_size, __FILE__, __LINE__);
5105 return(TNG_CRITICAL);
5108 if(type == TNG_FLOAT_DATA)
5110 memcpy(temp + offset, f_dest, uncompressed_len);
5114 memcpy(temp + offset, d_dest, uncompressed_len);
5117 block->block_contents = temp;
5127 return(TNG_SUCCESS);
5131 static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
5132 tng_gen_block_t block,
5133 void *start_pos, const int len)
5137 unsigned long max_len, stat, offset;
5140 max_len = compressBound(len);
5141 dest = malloc(max_len);
5144 fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
5145 max_len, __FILE__, __LINE__);
5146 return(TNG_CRITICAL);
5149 stat = compress(dest, &max_len, start_pos, len);
5150 if(stat != (unsigned long)Z_OK)
5153 if(stat == (unsigned long)Z_MEM_ERROR)
5155 fprintf(stderr, "TNG library: Not enough memory. ");
5157 else if(stat == (unsigned long)Z_BUF_ERROR)
5159 fprintf(stderr, "TNG library: Destination buffer too small. ");
5161 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
5162 return(TNG_FAILURE);
5165 offset = (char *)start_pos - block->block_contents;
5167 block->block_contents_size = max_len + offset;
5169 temp = realloc(block->block_contents, block->block_contents_size);
5172 free(block->block_contents);
5174 block->block_contents = 0;
5175 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5176 block->block_contents_size, __FILE__, __LINE__);
5177 return(TNG_CRITICAL);
5180 block->block_contents = temp;
5182 memcpy(temp + offset, dest, max_len);
5186 return(TNG_SUCCESS);
5189 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5190 tng_gen_block_t block,
5192 unsigned long uncompressed_len)
5200 offset = (char *)start_pos - (char *)block->block_contents;
5202 dest = malloc(uncompressed_len);
5205 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5206 uncompressed_len, __FILE__, __LINE__);
5207 return(TNG_CRITICAL);
5210 stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
5211 block->block_contents_size - offset);
5216 if(stat == (unsigned long)Z_MEM_ERROR)
5218 fprintf(stderr, "TNG library: Not enough memory. ");
5220 else if(stat == (unsigned long)Z_BUF_ERROR)
5222 fprintf(stderr, "TNG library: Destination buffer too small. ");
5224 else if(stat == (unsigned long)Z_DATA_ERROR)
5226 fprintf(stderr, "TNG library: Data corrupt. ");
5228 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
5230 return(TNG_FAILURE);
5234 block->block_contents_size = uncompressed_len + offset;
5236 temp = realloc(block->block_contents, uncompressed_len + offset);
5239 free(block->block_contents);
5240 block->block_contents = 0;
5242 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5243 block->block_contents_size, __FILE__, __LINE__);
5244 return(TNG_CRITICAL);
5247 memcpy(temp + offset, dest, uncompressed_len);
5249 block->block_contents = temp;
5252 return(TNG_SUCCESS);
5256 /** Allocate memory for storing particle data.
5257 * The allocated block will be refered to by data->values.
5258 * @param tng_data is a trajectory data container.
5259 * @param data is the data struct, which will contain the allocated memory in
5261 * @param n_frames is the number of frames of data to store.
5262 * @param n_particles is the number of particles with data.
5263 * @param n_values_per_frame is the number of data values per particle and
5265 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5266 * error has occured.
5268 static tng_function_status tng_allocate_particle_data_mem
5269 (tng_trajectory_t tng_data,
5270 tng_particle_data_t data,
5272 int64_t stride_length,
5273 const int64_t n_particles,
5274 const int64_t n_values_per_frame)
5277 int64_t i, j, k, size, frame_alloc;
5280 if(n_particles == 0 || n_values_per_frame == 0)
5282 return(TNG_FAILURE);
5285 if(data->strings && data->datatype == TNG_CHAR_DATA)
5287 for(i = 0; i < data->n_frames; i++)
5289 for(j = 0; j < n_particles; j++)
5291 for(k = 0; k < data->n_values_per_frame; k++)
5293 if(data->strings[i][j][k])
5295 free(data->strings[i][j][k]);
5298 free(data->strings[i][j]);
5300 free(data->strings[i]);
5302 free(data->strings);
5304 data->n_frames = n_frames;
5305 n_frames = tng_max_i64(1, n_frames);
5306 data->stride_length = tng_max_i64(1, stride_length);
5307 data->n_values_per_frame = n_values_per_frame;
5308 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5310 if(data->datatype == TNG_CHAR_DATA)
5312 data->strings = malloc(sizeof(char ***) * frame_alloc);
5313 for(i = 0; i < frame_alloc; i++)
5315 data->strings[i] = malloc(sizeof(char **) *
5317 if(!data->strings[i])
5319 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5320 sizeof(union data_values *) * n_particles,
5321 __FILE__, __LINE__);
5322 return(TNG_CRITICAL);
5324 for(j = 0; j < n_particles; j++)
5326 data->strings[i][j] = malloc(sizeof(char *) *
5327 n_values_per_frame);
5328 if(!data->strings[i][j])
5330 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5331 sizeof(union data_values) * n_values_per_frame,
5332 __FILE__, __LINE__);
5333 return(TNG_CRITICAL);
5335 for(k = 0; k < n_values_per_frame; k++)
5337 data->strings[i][j][k] = 0;
5344 switch(data->datatype)
5347 size = sizeof(int64_t);
5349 case TNG_FLOAT_DATA:
5350 size = sizeof(float);
5352 case TNG_DOUBLE_DATA:
5354 size = sizeof(double);
5357 values = realloc(data->values,
5358 size * frame_alloc *
5359 n_particles * n_values_per_frame);
5362 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5363 size * frame_alloc *
5364 n_particles * n_values_per_frame,
5365 __FILE__, __LINE__);
5368 return(TNG_CRITICAL);
5370 data->values = values;
5372 return(TNG_SUCCESS);
5375 static tng_function_status tng_particle_data_find
5376 (tng_trajectory_t tng_data,
5378 tng_particle_data_t *data)
5380 int64_t block_index, i;
5381 tng_trajectory_frame_set_t frame_set = &tng_data->
5382 current_trajectory_frame_set;
5383 char block_type_flag;
5385 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5386 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5388 block_type_flag = TNG_TRAJECTORY_BLOCK;
5392 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5396 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5398 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
5400 *data = &frame_set->tr_particle_data[i];
5401 if((*data)->block_id == id)
5410 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
5412 *data = &tng_data->non_tr_particle_data[i];
5413 if((*data)->block_id == id)
5420 if(block_index == -1)
5422 return(TNG_FAILURE);
5424 return(TNG_SUCCESS);
5427 static tng_function_status tng_data_find
5428 (tng_trajectory_t tng_data,
5430 tng_non_particle_data_t *data)
5432 int64_t block_index, i;
5433 tng_trajectory_frame_set_t frame_set = &tng_data->
5434 current_trajectory_frame_set;
5435 char block_type_flag;
5437 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
5438 tng_data->current_trajectory_frame_set_output_file_pos > 0)
5440 block_type_flag = TNG_TRAJECTORY_BLOCK;
5444 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5448 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5450 for(i = 0; i < frame_set->n_data_blocks; i++)
5452 *data = &frame_set->tr_data[i];
5453 if((*data)->block_id == id)
5459 if(block_index == -1)
5461 for(i = 0; i < tng_data->n_data_blocks; i++)
5463 *data = &tng_data->non_tr_data[i];
5464 if((*data)->block_id == id)
5474 for(i = 0; i < tng_data->n_data_blocks; i++)
5476 *data = &tng_data->non_tr_data[i];
5477 if((*data)->block_id == id)
5484 if(block_index == -1)
5486 return(TNG_FAILURE);
5488 return(TNG_SUCCESS);
5491 static tng_function_status tng_data_block_len_calculate
5492 (const tng_trajectory_t tng_data,
5493 const tng_particle_data_t data,
5494 const tng_bool is_particle_data,
5495 const int64_t n_frames,
5496 const int64_t frame_step,
5497 const int64_t stride_length,
5498 const int64_t num_first_particle,
5499 const int64_t n_particles,
5500 const char dependency,
5501 int64_t *data_start_pos,
5506 char ***first_dim_values, **second_dim_values;
5511 return(TNG_SUCCESS);
5514 switch(data->datatype)
5520 size = sizeof(int64_t);
5522 case TNG_FLOAT_DATA:
5523 size = sizeof(float);
5525 case TNG_DOUBLE_DATA:
5527 size = sizeof(double);
5530 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5531 sizeof(data->codec_id);
5532 if(is_particle_data)
5534 *len += sizeof(num_first_particle) + sizeof(n_particles);
5537 if(stride_length > 1)
5539 *len += sizeof(data->first_frame_with_data) +
5540 sizeof(data->stride_length);
5543 if(data->codec_id != TNG_UNCOMPRESSED)
5545 *len += sizeof(data->compression_multiplier);
5548 if(dependency & TNG_FRAME_DEPENDENT)
5550 *len += sizeof(char);
5553 *data_start_pos = *len;
5555 if(data->datatype == TNG_CHAR_DATA)
5557 if(is_particle_data)
5559 for(i = 0; i < n_frames; i++)
5561 first_dim_values = data->strings[i];
5562 for(j = num_first_particle; j < num_first_particle + n_particles;
5565 second_dim_values = first_dim_values[j];
5566 for(k = 0; k < data->n_values_per_frame; k++)
5568 *len += strlen(second_dim_values[k]) + 1;
5575 for(i = 0; i < n_frames; i++)
5577 second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
5578 for(j = 0; j < data->n_values_per_frame; j++)
5580 *len += strlen(second_dim_values[j]) + 1;
5587 *len += size * frame_step * n_particles * data->n_values_per_frame;
5590 return(TNG_SUCCESS);
5593 /** Read the values of a particle data block
5594 * @param tng_data is a trajectory data container.
5595 * @param block is the block to store the data (should already contain
5596 * the block headers and the block contents).
5597 * @param offset is the reading offset to point at the place where the actual
5598 * values are stored, starting from the beginning of the block_contents. The
5599 * offset is changed during the reading.
5600 * @param datatype is the type of data of the data block (char, int, float or
5602 * @param num_first_particle is the number of the first particle in the data
5603 * block. This should be the same as in the corresponding particle mapping
5605 * @param n_particles is the number of particles in the data block. This should
5606 * be the same as in the corresponding particle mapping block.
5607 * @param first_frame_with_data is the frame number of the first frame with data
5608 * in this data block.
5609 * @param stride_length is the number of frames between each data entry.
5610 * @param n_frames is the number of frames in this data block.
5611 * @param n_values is the number of values per particle and frame stored in this
5613 * @param codec_id is the ID of the codec to compress the data.
5614 * @param multiplier is the multiplication factor applied to each data value
5615 * before compression. This factor is applied since some compression algorithms
5616 * work only on integers.
5617 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5618 * error has occured.
5620 static tng_function_status tng_particle_data_read
5621 (tng_trajectory_t tng_data,
5622 tng_gen_block_t block,
5624 const char datatype,
5625 const int64_t num_first_particle,
5626 const int64_t n_particles,
5627 const int64_t first_frame_with_data,
5628 const int64_t stride_length,
5630 const int64_t n_values,
5631 const int64_t codec_id,
5632 const double multiplier)
5634 int64_t i, j, k, tot_n_particles, n_frames_div;
5636 unsigned long data_size;
5637 char ***first_dim_values, **second_dim_values;
5638 tng_particle_data_t data;
5639 tng_trajectory_frame_set_t frame_set =
5640 &tng_data->current_trajectory_frame_set;
5641 char block_type_flag;
5643 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
5651 size = sizeof(int64_t);
5653 case TNG_FLOAT_DATA:
5654 size = sizeof(float);
5656 case TNG_DOUBLE_DATA:
5658 size = sizeof(double);
5661 /* If the block does not exist, create it */
5662 if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
5664 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5666 block_type_flag = TNG_TRAJECTORY_BLOCK;
5670 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5673 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5676 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
5677 __FILE__, __LINE__);
5678 return(TNG_CRITICAL);
5680 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5682 data = &frame_set->tr_particle_data[frame_set->
5683 n_particle_data_blocks - 1];
5687 data = &tng_data->non_tr_particle_data[tng_data->
5688 n_particle_data_blocks - 1];
5690 data->block_id = block->id;
5692 data->block_name = malloc(strlen(block->name) + 1);
5693 if(!data->block_name)
5695 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5696 (int)strlen(block->name)+1, __FILE__, __LINE__);
5697 return(TNG_CRITICAL);
5699 strcpy(data->block_name, block->name);
5701 data->datatype = datatype;
5704 /* FIXME: Memory leak from strings. */
5707 data->codec_id = codec_id;
5708 data->compression_multiplier = multiplier;
5709 data->last_retrieved_frame = -1;
5712 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5713 tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
5714 tng_data->var_num_atoms_flag)
5716 tot_n_particles = frame_set->n_particles;
5720 tot_n_particles = tng_data->n_particles;
5723 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5725 if(codec_id != TNG_UNCOMPRESSED)
5727 data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
5730 case TNG_XTC_COMPRESSION:
5731 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5733 case TNG_TNG_COMPRESSION:
5734 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5735 if(tng_uncompress(tng_data, block, datatype,
5736 block->block_contents + *offset,
5737 data_size) != TNG_SUCCESS)
5739 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5740 __FILE__, __LINE__);
5741 return(TNG_CRITICAL);
5743 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5746 case TNG_GZIP_COMPRESSION:
5747 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5748 if(tng_gzip_uncompress(tng_data, block,
5749 block->block_contents + *offset,
5750 data_size) != TNG_SUCCESS)
5752 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5754 return(TNG_CRITICAL);
5756 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5761 /* Allocate memory */
5762 if(!data->values || data->n_frames != n_frames ||
5763 data->n_values_per_frame != n_values)
5765 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
5767 tot_n_particles, n_values) !=
5770 fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5771 __FILE__, __LINE__);
5772 return(TNG_CRITICAL);
5776 data->first_frame_with_data = first_frame_with_data;
5778 if(datatype == TNG_CHAR_DATA)
5780 for(i = 0; i < n_frames_div; i++)
5782 first_dim_values = data->strings[i];
5783 for(j = num_first_particle; j < num_first_particle + n_particles;
5786 second_dim_values = first_dim_values[j];
5787 for(k = 0; k < n_values; k++)
5789 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
5791 if(second_dim_values[k])
5793 free(second_dim_values[k]);
5795 second_dim_values[k] = malloc(len);
5796 if(!second_dim_values[k])
5798 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5799 len, __FILE__, __LINE__);
5800 return(TNG_CRITICAL);
5802 strncpy(second_dim_values[k],
5803 block->block_contents+*offset, len);
5811 memcpy((char *)data->values + n_frames_div * size * n_values *
5813 block->block_contents + *offset,
5814 block->block_contents_size - *offset);
5817 case TNG_FLOAT_DATA:
5818 if(tng_data->input_endianness_swap_func_32)
5820 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5822 if(tng_data->input_endianness_swap_func_32(tng_data,
5823 (int32_t *)((char *)data->values + i))
5826 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5827 __FILE__, __LINE__);
5833 case TNG_DOUBLE_DATA:
5834 if(tng_data->input_endianness_swap_func_64)
5836 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
5838 if(tng_data->input_endianness_swap_func_64(tng_data,
5839 (int64_t *)((char *)data->values + i))
5842 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5843 __FILE__, __LINE__);
5852 return(TNG_SUCCESS);
5855 /** Write a particle data block
5856 * @param tng_data is a trajectory data container.
5857 * @param block is the block to store the data (should already contain
5858 * the block headers and the block contents).
5859 * @param block_index is the index number of the data block in the frame set.
5860 * @param mapping is the particle mapping that is relevant for the data block.
5861 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5862 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5863 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5864 * error has occured.
5866 static tng_function_status tng_particle_data_block_write
5867 (tng_trajectory_t tng_data,
5868 tng_gen_block_t block,
5869 const int64_t block_index,
5870 const tng_particle_mapping_t mapping,
5871 const char hash_mode)
5873 int64_t n_particles, num_first_particle, n_frames, stride_length;
5874 int64_t frame_step, data_start_pos;
5877 size_t len, offset = 0;
5878 char dependency, temp, *temp_name;
5880 char ***first_dim_values, **second_dim_values;
5881 tng_trajectory_frame_set_t frame_set;
5882 tng_function_status stat;
5884 tng_particle_data_t data;
5885 char block_type_flag;
5887 frame_set = &tng_data->current_trajectory_frame_set;
5889 /* If we have already started writing frame sets it is too late to write
5890 * non-trajectory data blocks */
5891 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5893 block_type_flag = TNG_TRAJECTORY_BLOCK;
5897 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5900 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5902 return(TNG_CRITICAL);
5905 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5907 data = &frame_set->tr_particle_data[block_index];
5909 /* If this data block has not had any data added in this frame set
5910 * do not write it. */
5911 if(data->first_frame_with_data < frame_set->first_frame)
5913 return(TNG_SUCCESS);
5916 stride_length = tng_max_i64(1, data->stride_length);
5920 data = &tng_data->non_tr_particle_data[block_index];
5924 switch(data->datatype)
5930 size = sizeof(int64_t);
5932 case TNG_FLOAT_DATA:
5933 size = sizeof(float);
5935 case TNG_DOUBLE_DATA:
5937 size = sizeof(double);
5940 len = strlen(data->block_name) + 1;
5942 if(!block->name || strlen(block->name) < len)
5944 temp_name = realloc(block->name, len);
5947 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5948 __FILE__, __LINE__);
5951 return(TNG_CRITICAL);
5953 block->name = temp_name;
5955 strncpy(block->name, data->block_name, len);
5956 block->id = data->block_id;
5958 /* If writing frame independent data data->n_frames is 0, but n_frames
5959 is used for the loop writing the data (and reserving memory) and needs
5961 n_frames = tng_max_i64(1, data->n_frames);
5963 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5965 /* If the frame set is finished before writing the full number of frames
5966 make sure the data block is not longer than the frame set. */
5967 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5969 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5972 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5973 n_frames / stride_length;
5975 /* TNG compression will use compression precision to get integers from
5976 * floating point data. The compression multiplier stores that information
5977 * to be able to return the precision of the compressed data. */
5978 if(data->codec_id == TNG_TNG_COMPRESSION)
5980 data->compression_multiplier = tng_data->compression_precision;
5982 /* Uncompressed data blocks do not use compression multipliers at all.
5983 * GZip compression does not need it either. */
5984 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5986 data->compression_multiplier = 1.0;
5989 if(mapping && mapping->n_particles != 0)
5991 n_particles = mapping->n_particles;
5992 num_first_particle = mapping->num_first_particle;
5996 num_first_particle = 0;
5997 if(tng_data->var_num_atoms_flag)
5999 n_particles = frame_set->n_particles;
6003 n_particles = tng_data->n_particles;
6007 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6009 dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
6013 dependency = TNG_PARTICLE_DEPENDENT;
6016 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
6017 frame_step, stride_length, num_first_particle,
6018 n_particles, dependency, &data_start_pos,
6019 &block->block_contents_size) != TNG_SUCCESS)
6021 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6022 __FILE__, __LINE__);
6023 return(TNG_CRITICAL);
6026 if(block->block_contents)
6028 free(block->block_contents);
6030 block->block_contents = malloc(block->block_contents_size);
6031 if(!block->block_contents)
6033 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6034 block->block_contents_size, __FILE__, __LINE__);
6035 return(TNG_CRITICAL);
6039 memcpy(block->block_contents, &data->datatype, sizeof(char));
6040 offset += sizeof(char);
6042 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6043 offset += sizeof(char);
6045 if(dependency & TNG_FRAME_DEPENDENT)
6047 if(stride_length > 1)
6055 memcpy(block->block_contents+offset, &temp, sizeof(char));
6056 offset += sizeof(char);
6059 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6060 sizeof(data->n_values_per_frame));
6061 if(tng_data->output_endianness_swap_func_64)
6063 if(tng_data->output_endianness_swap_func_64(tng_data,
6064 (int64_t *)block->header_contents+offset)
6067 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6068 __FILE__, __LINE__);
6071 offset += sizeof(data->n_values_per_frame);
6073 memcpy(block->block_contents+offset, &data->codec_id,
6074 sizeof(data->codec_id));
6075 if(tng_data->output_endianness_swap_func_64)
6077 if(tng_data->output_endianness_swap_func_64(tng_data,
6078 (int64_t *)block->header_contents+offset)
6081 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6082 __FILE__, __LINE__);
6085 offset += sizeof(data->codec_id);
6087 if(data->codec_id != TNG_UNCOMPRESSED)
6089 memcpy(block->block_contents+offset, &data->compression_multiplier,
6090 sizeof(data->compression_multiplier));
6091 if(tng_data->output_endianness_swap_func_64)
6093 if(tng_data->output_endianness_swap_func_64(tng_data,
6094 (int64_t *)block->header_contents+offset)
6097 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6098 __FILE__, __LINE__);
6101 offset += sizeof(data->compression_multiplier);
6104 if(data->n_frames > 0 && stride_length > 1)
6106 /* FIXME: first_frame_with_data is not reliably set */
6107 if(data->first_frame_with_data == 0)
6109 data->first_frame_with_data = frame_set->first_frame;
6111 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6112 sizeof(data->first_frame_with_data));
6113 if(tng_data->output_endianness_swap_func_64)
6115 if(tng_data->output_endianness_swap_func_64(tng_data,
6116 (int64_t *)block->header_contents+offset)
6119 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6120 __FILE__, __LINE__);
6123 offset += sizeof(data->first_frame_with_data);
6125 memcpy(block->block_contents+offset, &stride_length,
6126 sizeof(stride_length));
6127 if(tng_data->output_endianness_swap_func_64)
6129 if(tng_data->output_endianness_swap_func_64(tng_data,
6130 (int64_t *)block->header_contents+offset)
6133 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6134 __FILE__, __LINE__);
6137 offset += sizeof(stride_length);
6141 memcpy(block->block_contents+offset, &num_first_particle,
6142 sizeof(num_first_particle));
6143 if(tng_data->output_endianness_swap_func_64)
6145 if(tng_data->output_endianness_swap_func_64(tng_data,
6146 (int64_t *)block->header_contents+offset)
6149 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6150 __FILE__, __LINE__);
6153 offset += sizeof(num_first_particle);
6155 memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
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(n_particles);
6168 if(data->datatype == TNG_CHAR_DATA)
6172 for(i = 0; i < frame_step; i++)
6174 first_dim_values = data->strings[i];
6175 for(j = num_first_particle; j < num_first_particle + n_particles;
6178 second_dim_values = first_dim_values[j];
6179 for(k = 0; k < data->n_values_per_frame; k++)
6181 len = (unsigned int)strlen(second_dim_values[k]) + 1;
6182 strncpy(block->block_contents+offset,
6183 second_dim_values[k], len);
6190 else if(data->values)
6192 memcpy(block->block_contents + offset, data->values,
6193 block->block_contents_size - offset);
6195 switch(data->datatype)
6197 case TNG_FLOAT_DATA:
6198 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6199 data->codec_id == TNG_TNG_COMPRESSION)
6201 if(tng_data->input_endianness_swap_func_32)
6203 for(i = offset; i < block->block_contents_size; i+=size)
6205 if(tng_data->input_endianness_swap_func_32(tng_data,
6206 (int32_t *)(block->block_contents + i))
6209 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6210 __FILE__, __LINE__);
6217 multiplier = data->compression_multiplier;
6218 if(fabs(multiplier - 1.0) > 0.00001 ||
6219 tng_data->input_endianness_swap_func_32)
6221 for(i = offset; i < block->block_contents_size; i+=size)
6223 *(float *)(block->block_contents + i) *= (float)multiplier;
6224 if(tng_data->input_endianness_swap_func_32 &&
6225 tng_data->input_endianness_swap_func_32(tng_data,
6226 (int32_t *)(block->block_contents + i))
6229 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6230 __FILE__, __LINE__);
6237 if(tng_data->input_endianness_swap_func_64)
6239 for(i = offset; i < block->block_contents_size; i+=size)
6241 if(tng_data->input_endianness_swap_func_64(tng_data,
6242 (int64_t *)(block->block_contents + i))
6245 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6246 __FILE__, __LINE__);
6251 case TNG_DOUBLE_DATA:
6252 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6253 data->codec_id == TNG_TNG_COMPRESSION)
6255 if(tng_data->input_endianness_swap_func_64)
6257 for(i = offset; i < block->block_contents_size; i+=size)
6259 if(tng_data->input_endianness_swap_func_64(tng_data,
6260 (int64_t *)(block->block_contents + i))
6263 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6264 __FILE__, __LINE__);
6271 multiplier = data->compression_multiplier;
6272 if(fabs(multiplier - 1.0) > 0.00001 ||
6273 tng_data->input_endianness_swap_func_64)
6275 for(i = offset; i < block->block_contents_size; i+=size)
6277 *(double *)(block->block_contents + i) *= multiplier;
6278 if(tng_data->input_endianness_swap_func_64 &&
6279 tng_data->input_endianness_swap_func_64(tng_data,
6280 (int64_t *)(block->block_contents + i))
6283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6284 __FILE__, __LINE__);
6296 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
6299 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6300 frame_set->n_unwritten_frames = 0;
6302 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
6304 switch(data->codec_id)
6306 case TNG_XTC_COMPRESSION:
6307 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6308 data->codec_id = TNG_UNCOMPRESSED;
6310 case TNG_TNG_COMPRESSION:
6311 stat = tng_compress(tng_data, block, frame_step,
6312 n_particles, data->datatype,
6313 block->block_contents + data_start_pos);
6314 if(stat != TNG_SUCCESS)
6316 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6317 __FILE__, __LINE__);
6318 if(stat == TNG_CRITICAL)
6320 return(TNG_CRITICAL);
6322 /* Set the data again, but with no compression (to write only
6323 * the relevant data) */
6324 data->codec_id = TNG_UNCOMPRESSED;
6325 stat = tng_particle_data_block_write(tng_data, block,
6326 block_index, mapping,
6332 case TNG_GZIP_COMPRESSION:
6333 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6334 stat = tng_gzip_compress(tng_data, block,
6335 block->block_contents + data_start_pos,
6336 block->block_contents_size - data_start_pos);
6337 if(stat != TNG_SUCCESS)
6339 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6341 if(stat == TNG_CRITICAL)
6343 return(TNG_CRITICAL);
6345 /* Set the data again, but with no compression (to write only
6346 * the relevant data) */
6347 data->codec_id = TNG_UNCOMPRESSED;
6348 stat = tng_particle_data_block_write(tng_data, block,
6349 block_index, mapping,
6353 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6359 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
6361 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
6362 tng_data->output_file_path, __FILE__, __LINE__);
6363 return(TNG_CRITICAL);
6366 if(fwrite(block->block_contents, block->block_contents_size, 1,
6367 tng_data->output_file) != 1)
6369 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6371 return(TNG_CRITICAL);
6374 return(TNG_SUCCESS);
6378 /** Create a non-particle data block
6379 * @param tng_data is a trajectory data container.
6380 * @param block_type_flag specifies if this is a trajectory block or a
6381 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6382 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6383 * error has occured.
6385 static tng_function_status tng_data_block_create
6386 (tng_trajectory_t tng_data,
6387 const char block_type_flag)
6389 tng_trajectory_frame_set_t frame_set =
6390 &tng_data->current_trajectory_frame_set;
6392 tng_non_particle_data_t data;
6394 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6396 frame_set->n_data_blocks++;
6397 data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
6398 frame_set->n_data_blocks);
6401 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6402 sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
6403 __FILE__, __LINE__);
6404 free(frame_set->tr_data);
6405 frame_set->tr_data = 0;
6406 return(TNG_CRITICAL);
6408 frame_set->tr_data = data;
6412 tng_data->n_data_blocks++;
6413 data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
6414 tng_data->n_data_blocks);
6417 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6418 sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
6419 __FILE__, __LINE__);
6420 free(tng_data->non_tr_data);
6421 tng_data->non_tr_data = 0;
6422 return(TNG_CRITICAL);
6424 tng_data->non_tr_data = data;
6427 return(TNG_SUCCESS);
6431 /** Allocate memory for storing non-particle data.
6432 * The allocated block will be refered to by data->values.
6433 * @param tng_data is a trajectory data container.
6434 * @param data is the data struct, which will contain the allocated memory in
6436 * @param n_frames is the number of frames of data to store.
6437 * @param n_values_per_frame is the number of data values per frame.
6438 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6439 * error has occured.
6441 static tng_function_status tng_allocate_data_mem
6442 (tng_trajectory_t tng_data,
6443 tng_non_particle_data_t data,
6445 int64_t stride_length,
6446 const int64_t n_values_per_frame)
6449 int64_t i, j, size, frame_alloc;
6452 if(n_values_per_frame == 0)
6454 return(TNG_FAILURE);
6457 if(data->strings && data->datatype == TNG_CHAR_DATA)
6459 for(i = 0; i < data->n_frames; i++)
6461 for(j = 0; j < data->n_values_per_frame; j++)
6463 if(data->strings[i][j])
6465 free(data->strings[i][j]);
6466 data->strings[i][j] = 0;
6469 free(data->strings[i]);
6470 data->strings[i] = 0;
6472 free(data->strings);
6474 data->n_frames = n_frames;
6475 data->stride_length = tng_max_i64(1, stride_length);
6476 n_frames = tng_max_i64(1, n_frames);
6477 data->n_values_per_frame = n_values_per_frame;
6478 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6480 if(data->datatype == TNG_CHAR_DATA)
6482 data->strings = malloc(sizeof(char **) * frame_alloc);
6483 for(i = 0; i < frame_alloc; i++)
6485 data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
6486 if(!data->strings[i])
6488 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6490 __FILE__, __LINE__);
6491 return(TNG_CRITICAL);
6493 for(j = 0; j < n_values_per_frame; j++)
6495 data->strings[i][j] = 0;
6501 switch(data->datatype)
6504 size = sizeof(int64_t);
6506 case TNG_FLOAT_DATA:
6507 size = sizeof(float);
6509 case TNG_DOUBLE_DATA:
6511 size = sizeof(double);
6514 values = realloc(data->values,
6515 size * frame_alloc *
6516 n_values_per_frame);
6519 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6520 size * frame_alloc *
6522 __FILE__, __LINE__);
6525 return(TNG_CRITICAL);
6527 data->values = values;
6530 return(TNG_SUCCESS);
6533 /** Read the values of a non-particle data block
6534 * @param tng_data is a trajectory data container.
6535 * @param block is the block to store the data (should already contain
6536 * the block headers and the block contents).
6537 * @param offset is the reading offset to point at the place where the actual
6538 * values are stored, starting from the beginning of the block_contents. The
6539 * offset is changed during the reading.
6540 * @param datatype is the type of data of the data block (char, int, float or
6542 * @param first_frame_with_data is the frame number of the first frame with data
6543 * in this data block.
6544 * @param stride_length is the number of frames between each data entry.
6545 * @param n_frames is the number of frames in this data block.
6546 * @param n_values is the number of values per frame stored in this data block.
6547 * @param codec_id is the ID of the codec to compress the data.
6548 * @param multiplier is the multiplication factor applied to each data value
6549 * before compression. This factor is applied since some compression algorithms
6550 * work only on integers.
6551 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6552 * error has occured.
6554 static tng_function_status tng_data_read(tng_trajectory_t tng_data,
6555 tng_gen_block_t block,
6557 const char datatype,
6558 const int64_t first_frame_with_data,
6559 const int64_t stride_length,
6561 const int64_t n_values,
6562 const int64_t codec_id,
6563 const double multiplier)
6565 int64_t i, j, n_frames_div;
6568 unsigned long data_size;
6570 tng_non_particle_data_t data;
6571 tng_trajectory_frame_set_t frame_set =
6572 &tng_data->current_trajectory_frame_set;
6573 char block_type_flag;
6575 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
6577 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6585 size = sizeof(int64_t);
6587 case TNG_FLOAT_DATA:
6588 size = sizeof(float);
6590 case TNG_DOUBLE_DATA:
6592 size = sizeof(double);
6595 /* If the block does not exist, create it */
6596 if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
6598 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
6600 block_type_flag = TNG_TRAJECTORY_BLOCK;
6604 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6607 if(tng_data_block_create(tng_data, block_type_flag) !=
6610 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
6611 __FILE__, __LINE__);
6612 return(TNG_CRITICAL);
6614 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6616 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
6620 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
6622 data->block_id = block->id;
6624 data->block_name = malloc(strlen(block->name) + 1);
6625 if(!data->block_name)
6627 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6628 (int)strlen(block->name)+1, __FILE__, __LINE__);
6629 return(TNG_CRITICAL);
6631 strcpy(data->block_name, block->name);
6633 data->datatype = datatype;
6636 /* FIXME: Memory leak from strings. */
6639 data->codec_id = codec_id;
6640 data->compression_multiplier = multiplier;
6641 data->last_retrieved_frame = -1;
6644 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
6646 if(codec_id != TNG_UNCOMPRESSED)
6651 case TNG_GZIP_COMPRESSION:
6652 data_size = n_frames_div * size * n_values;
6653 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6654 if(tng_gzip_uncompress(tng_data, block,
6655 block->block_contents + *offset,
6656 data_size) != TNG_SUCCESS)
6658 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
6660 return(TNG_CRITICAL);
6662 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6668 /* Allocate memory */
6669 if(!data->values || data->n_frames != n_frames ||
6670 data->n_values_per_frame != n_values)
6672 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
6676 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
6677 __FILE__, __LINE__);
6678 return(TNG_CRITICAL);
6682 data->first_frame_with_data = first_frame_with_data;
6684 if(datatype == TNG_CHAR_DATA)
6686 for(i = 0; i < n_frames_div; i++)
6688 for(j = 0; j < n_values; j++)
6690 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
6692 if(data->strings[i][j])
6694 free(data->strings[i][j]);
6696 data->strings[i][j] = malloc(len);
6697 if(!data->strings[i][j])
6699 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6700 len, __FILE__, __LINE__);
6701 return(TNG_CRITICAL);
6703 strncpy(data->strings[i][j], block->block_contents+*offset,
6711 memcpy(data->values, block->block_contents + *offset,
6712 block->block_contents_size - *offset);
6715 case TNG_FLOAT_DATA:
6716 if(tng_data->input_endianness_swap_func_32)
6718 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6720 if(tng_data->input_endianness_swap_func_32(tng_data,
6721 (int32_t *)((char *)data->values + i))
6724 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6725 __FILE__, __LINE__);
6731 case TNG_DOUBLE_DATA:
6732 if(tng_data->input_endianness_swap_func_64)
6734 for(i = 0; i < (block->block_contents_size - *offset); i+=size)
6736 if(tng_data->input_endianness_swap_func_64(tng_data,
6737 (int64_t *)((char *)data->values + i))
6740 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6741 __FILE__, __LINE__);
6750 return(TNG_SUCCESS);
6753 /** Write a non-particle data block
6754 * @param tng_data is a trajectory data container.
6755 * @param block is the block to store the data (should already contain
6756 * the block headers and the block contents).
6757 * @param block_index is the index number of the data block in the frame set.
6758 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6759 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6760 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6761 * error has occured.
6763 static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
6764 tng_gen_block_t block,
6765 const int64_t block_index,
6766 const char hash_mode)
6768 int64_t n_frames, stride_length, frame_step, data_start_pos;
6770 int offset = 0, size;
6773 tng_function_status stat;
6775 char temp, dependency, *temp_name;
6777 tng_trajectory_frame_set_t frame_set =
6778 &tng_data->current_trajectory_frame_set;
6780 tng_non_particle_data_t data;
6781 char block_type_flag;
6783 /* If we have already started writing frame sets it is too late to write
6784 * non-trajectory data blocks */
6785 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
6787 block_type_flag = TNG_TRAJECTORY_BLOCK;
6791 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6794 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6796 return(TNG_CRITICAL);
6799 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6801 data = &frame_set->tr_data[block_index];
6803 /* If this data block has not had any data added in this frame set
6804 * do not write it. */
6805 if(data->first_frame_with_data < frame_set->first_frame)
6807 return(TNG_SUCCESS);
6810 stride_length = tng_max_i64(1, data->stride_length);
6814 data = &tng_data->non_tr_data[block_index];
6818 switch(data->datatype)
6824 size = sizeof(int64_t);
6826 case TNG_FLOAT_DATA:
6827 size = sizeof(float);
6829 case TNG_DOUBLE_DATA:
6831 size = sizeof(double);
6834 len = (unsigned int)strlen(data->block_name) + 1;
6836 if(!block->name || strlen(block->name) < len)
6838 temp_name = realloc(block->name, len);
6841 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6842 __FILE__, __LINE__);
6845 return(TNG_CRITICAL);
6847 block->name = temp_name;
6849 strncpy(block->name, data->block_name, len);
6850 block->id = data->block_id;
6852 /* If writing frame independent data data->n_frames is 0, but n_frames
6853 is used for the loop writing the data (and reserving memory) and needs
6855 n_frames = tng_max_i64(1, data->n_frames);
6857 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
6859 /* If the frame set is finished before writing the full number of frames
6860 make sure the data block is not longer than the frame set. */
6861 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
6863 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
6866 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
6867 n_frames / stride_length;
6869 /* TNG compression will use compression precision to get integers from
6870 * floating point data. The compression multiplier stores that information
6871 * to be able to return the precision of the compressed data. */
6872 if(data->codec_id == TNG_TNG_COMPRESSION)
6874 data->compression_multiplier = tng_data->compression_precision;
6876 /* Uncompressed data blocks do not use compression multipliers at all.
6877 * GZip compression does not need it either. */
6878 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6880 data->compression_multiplier = 1.0;
6883 if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
6885 dependency = TNG_FRAME_DEPENDENT;
6892 if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
6893 frame_step, stride_length, 0,
6894 1, dependency, &data_start_pos,
6895 &block->block_contents_size) != TNG_SUCCESS)
6897 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6898 __FILE__, __LINE__);
6899 return(TNG_CRITICAL);
6902 if(block->block_contents)
6904 free(block->block_contents);
6906 block->block_contents = malloc(block->block_contents_size);
6907 if(!block->block_contents)
6909 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6910 block->block_contents_size, __FILE__, __LINE__);
6911 return(TNG_CRITICAL);
6915 memcpy(block->block_contents, &data->datatype, sizeof(char));
6916 offset += sizeof(char);
6918 memcpy(block->block_contents+offset, &dependency, sizeof(char));
6919 offset += sizeof(char);
6921 if(dependency & TNG_FRAME_DEPENDENT)
6923 if(stride_length > 1)
6931 memcpy(block->block_contents+offset, &temp, sizeof(char));
6932 offset += sizeof(char);
6935 memcpy(block->block_contents+offset, &data->n_values_per_frame,
6936 sizeof(data->n_values_per_frame));
6937 if(tng_data->output_endianness_swap_func_64)
6939 if(tng_data->output_endianness_swap_func_64(tng_data,
6940 (int64_t *)block->header_contents+offset)
6943 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6944 __FILE__, __LINE__);
6947 offset += sizeof(data->n_values_per_frame);
6949 memcpy(block->block_contents+offset, &data->codec_id,
6950 sizeof(data->codec_id));
6951 if(tng_data->output_endianness_swap_func_64)
6953 if(tng_data->output_endianness_swap_func_64(tng_data,
6954 (int64_t *)block->header_contents+offset)
6957 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6958 __FILE__, __LINE__);
6961 offset += sizeof(data->codec_id);
6963 if(data->codec_id != TNG_UNCOMPRESSED)
6965 memcpy(block->block_contents+offset, &data->compression_multiplier,
6966 sizeof(data->compression_multiplier));
6967 if(tng_data->output_endianness_swap_func_64)
6969 if(tng_data->output_endianness_swap_func_64(tng_data,
6970 (int64_t *)block->header_contents+offset)
6973 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6974 __FILE__, __LINE__);
6977 offset += sizeof(data->compression_multiplier);
6980 if(data->n_frames > 0 && stride_length > 1)
6982 /* FIXME: first_frame_with_data is not reliably set */
6983 if(data->first_frame_with_data == 0)
6985 data->first_frame_with_data = frame_set->first_frame;
6987 memcpy(block->block_contents+offset, &data->first_frame_with_data,
6988 sizeof(data->first_frame_with_data));
6989 if(tng_data->output_endianness_swap_func_64)
6991 if(tng_data->output_endianness_swap_func_64(tng_data,
6992 (int64_t *)block->header_contents+offset)
6995 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6996 __FILE__, __LINE__);
6999 offset += sizeof(data->first_frame_with_data);
7001 memcpy(block->block_contents+offset, &stride_length,
7002 sizeof(data->stride_length));
7003 if(tng_data->output_endianness_swap_func_64)
7005 if(tng_data->output_endianness_swap_func_64(tng_data,
7006 (int64_t *)block->header_contents+offset)
7009 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7010 __FILE__, __LINE__);
7013 offset += sizeof(data->stride_length);
7016 if(data->datatype == TNG_CHAR_DATA)
7020 for(i = 0; i < frame_step; i++)
7022 for(j = 0; j < data->n_values_per_frame; j++)
7024 len = (unsigned int)strlen(data->strings[i][j]) + 1;
7025 strncpy(block->block_contents+offset, data->strings[i][j],
7032 else if(data->values)
7034 memcpy(block->block_contents + offset, data->values,
7035 block->block_contents_size - offset);
7036 switch(data->datatype)
7038 case TNG_FLOAT_DATA:
7039 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7040 data->codec_id == TNG_TNG_COMPRESSION)
7042 if(tng_data->input_endianness_swap_func_32)
7044 for(i = offset; i < block->block_contents_size; i+=size)
7046 if(tng_data->input_endianness_swap_func_32(tng_data,
7047 (int32_t *)(block->block_contents + i))
7050 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7051 __FILE__, __LINE__);
7058 multiplier = data->compression_multiplier;
7059 if(fabs(multiplier - 1.0) > 0.00001 ||
7060 tng_data->input_endianness_swap_func_32)
7062 for(i = offset; block->block_contents_size; i+=size)
7064 *(float *)(block->block_contents + i) *= (float)multiplier;
7065 if(tng_data->input_endianness_swap_func_32 &&
7066 tng_data->input_endianness_swap_func_32(tng_data,
7067 (int32_t *)(block->block_contents + i))
7070 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7071 __FILE__, __LINE__);
7078 if(tng_data->input_endianness_swap_func_64)
7080 for(i = offset; i < block->block_contents_size; i+=size)
7082 if(tng_data->input_endianness_swap_func_64(tng_data,
7083 (int64_t *)(block->block_contents + i))
7086 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7087 __FILE__, __LINE__);
7092 case TNG_DOUBLE_DATA:
7093 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
7094 data->codec_id == TNG_TNG_COMPRESSION)
7096 if(tng_data->input_endianness_swap_func_64)
7098 for(i = offset; i < block->block_contents_size; i+=size)
7100 if(tng_data->input_endianness_swap_func_64(tng_data,
7101 (int64_t *)(block->block_contents + i))
7104 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7105 __FILE__, __LINE__);
7112 multiplier = data->compression_multiplier;
7113 if(fabs(multiplier - 1.0) > 0.00001 ||
7114 tng_data->input_endianness_swap_func_64)
7116 for(i = offset; i < block->block_contents_size; i+=size)
7118 *(double *)(block->block_contents + i) *= multiplier;
7119 if(tng_data->input_endianness_swap_func_64 &&
7120 tng_data->input_endianness_swap_func_64(tng_data,
7121 (int64_t *)(block->block_contents + i))
7124 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7125 __FILE__, __LINE__);
7137 memset(block->block_contents+offset, 0, block->block_contents_size - offset);
7140 frame_set->n_written_frames += frame_set->n_unwritten_frames;
7141 frame_set->n_unwritten_frames = 0;
7143 if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
7145 switch(data->codec_id)
7148 case TNG_GZIP_COMPRESSION:
7149 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7150 stat = tng_gzip_compress(tng_data, block,
7151 block->block_contents + data_start_pos,
7152 block->block_contents_size - data_start_pos);
7153 if(stat != TNG_SUCCESS)
7155 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
7157 if(stat == TNG_CRITICAL)
7159 return(TNG_CRITICAL);
7161 data->codec_id = TNG_UNCOMPRESSED;
7163 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7169 if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
7171 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
7172 tng_data->output_file_path, __FILE__, __LINE__);
7173 return(TNG_CRITICAL);
7176 if(fwrite(block->block_contents, block->block_contents_size, 1,
7177 tng_data->output_file) != 1)
7179 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
7180 __FILE__, __LINE__);
7181 return(TNG_CRITICAL);
7184 return(TNG_SUCCESS);
7187 /** Read the meta information of a data block (particle or non-particle data).
7188 * @param tng_data is a trajectory data container.
7189 * @param block is the block to store the data (should already contain
7190 * the block headers).
7191 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7192 * error has occured.
7194 static tng_function_status tng_data_block_meta_information_read
7195 (tng_trajectory_t tng_data,
7196 tng_gen_block_t block,
7203 int64_t *first_frame_with_data,
7204 int64_t *stride_length,
7206 int64_t *num_first_particle,
7207 int64_t *block_n_particles,
7213 if(block->block_contents)
7215 contents = block->block_contents;
7219 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7220 contents = malloc(meta_size);
7223 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7224 meta_size, __FILE__, __LINE__);
7227 if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
7229 fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
7231 return(TNG_CRITICAL);
7235 memcpy(datatype, contents+*offset,
7237 *offset += sizeof(*datatype);
7239 memcpy(dependency, contents+*offset,
7240 sizeof(*dependency));
7241 *offset += sizeof(*dependency);
7243 if(*dependency & TNG_FRAME_DEPENDENT)
7245 memcpy(sparse_data, contents+*offset,
7246 sizeof(*sparse_data));
7247 *offset += sizeof(*sparse_data);
7250 memcpy(n_values, contents+*offset,
7252 if(tng_data->input_endianness_swap_func_64)
7254 if(tng_data->input_endianness_swap_func_64(tng_data,
7258 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7259 __FILE__, __LINE__);
7262 *offset += sizeof(*n_values);
7264 memcpy(codec_id, contents+*offset,
7266 if(tng_data->input_endianness_swap_func_64)
7268 if(tng_data->input_endianness_swap_func_64(tng_data,
7272 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7273 __FILE__, __LINE__);
7276 *offset += sizeof(*codec_id);
7278 if(*codec_id != TNG_UNCOMPRESSED)
7280 memcpy(multiplier, contents+*offset,
7281 sizeof(*multiplier));
7282 if(tng_data->input_endianness_swap_func_64)
7284 if(tng_data->input_endianness_swap_func_64(tng_data,
7285 (int64_t *) multiplier)
7288 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7289 __FILE__, __LINE__);
7292 *offset += sizeof(*multiplier);
7299 if(*dependency & TNG_FRAME_DEPENDENT)
7303 memcpy(first_frame_with_data, contents+*offset,
7304 sizeof(*first_frame_with_data));
7305 if(tng_data->input_endianness_swap_func_64)
7307 if(tng_data->input_endianness_swap_func_64(tng_data,
7308 first_frame_with_data)
7311 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7312 __FILE__, __LINE__);
7315 *offset += sizeof(*first_frame_with_data);
7317 memcpy(stride_length, contents+*offset,
7318 sizeof(*stride_length));
7319 if(tng_data->input_endianness_swap_func_64)
7321 if(tng_data->input_endianness_swap_func_64(tng_data,
7325 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7326 __FILE__, __LINE__);
7329 *offset += sizeof(*stride_length);
7330 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
7331 (*first_frame_with_data -
7332 tng_data->current_trajectory_frame_set.first_frame);
7336 *first_frame_with_data = 0;
7338 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7343 *first_frame_with_data = 0;
7348 if (*dependency & TNG_PARTICLE_DEPENDENT)
7350 memcpy(num_first_particle, contents+*offset,
7351 sizeof(*num_first_particle));
7352 if(tng_data->input_endianness_swap_func_64)
7354 if(tng_data->input_endianness_swap_func_64(tng_data,
7358 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7359 __FILE__, __LINE__);
7362 *offset += sizeof(*num_first_particle);
7364 memcpy(block_n_particles, contents+*offset,
7365 sizeof(*block_n_particles));
7366 if(tng_data->input_endianness_swap_func_64)
7368 if(tng_data->input_endianness_swap_func_64(tng_data,
7372 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7373 __FILE__, __LINE__);
7376 *offset += sizeof(*block_n_particles);
7379 if(!block->block_contents)
7383 return(TNG_SUCCESS);
7386 /** Read the contents of a data block (particle or non-particle data).
7387 * @param tng_data is a trajectory data container.
7388 * @param block is the block to store the data (should already contain
7389 * the block headers).
7390 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7391 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7392 * compared to the md5 hash of the read contents to ensure valid data.
7393 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7394 * error has occured.
7396 static tng_function_status tng_data_block_contents_read
7397 (tng_trajectory_t tng_data,
7398 tng_gen_block_t block,
7399 const char hash_mode)
7401 int64_t n_values, codec_id, n_frames, first_frame_with_data;
7402 int64_t stride_length, block_n_particles, num_first_particle;
7404 char datatype, dependency, sparse_data;
7408 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
7410 return(TNG_CRITICAL);
7413 if(block->block_contents)
7415 free(block->block_contents);
7418 block->block_contents = malloc(block->block_contents_size);
7419 if(!block->block_contents)
7421 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7422 block->block_contents_size, __FILE__, __LINE__);
7423 return(TNG_CRITICAL);
7426 /* Read the whole block into block_contents to be able to write it to
7427 * disk even if it cannot be interpreted. */
7428 if(fread(block->block_contents, block->block_contents_size, 1,
7429 tng_data->input_file) == 0)
7431 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
7432 return(TNG_CRITICAL);
7435 /* FIXME: Does not check if the size of the contents matches the expected
7436 * size or if the contents can be read. */
7438 if(hash_mode == TNG_USE_HASH)
7440 tng_md5_hash_match_verify(block, &same_hash);
7441 if(same_hash != TNG_TRUE)
7443 fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7444 block->name, __FILE__, __LINE__);
7445 /* return(TNG_FAILURE); */
7449 if(tng_data_block_meta_information_read(tng_data, block,
7451 &dependency, &sparse_data,
7452 &n_values, &codec_id,
7453 &first_frame_with_data,
7454 &stride_length, &n_frames,
7455 &num_first_particle,
7457 &multiplier) == TNG_CRITICAL)
7459 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7460 block->name, __FILE__, __LINE__);
7461 return(TNG_CRITICAL);
7464 if (dependency & TNG_PARTICLE_DEPENDENT)
7466 return(tng_particle_data_read(tng_data, block,
7470 first_frame_with_data,
7473 codec_id, multiplier));
7477 return(tng_data_read(tng_data, block,
7479 first_frame_with_data,
7482 codec_id, multiplier));
7487 // ** Move the blocks in a frame set so that there is no unused space between
7488 // * them. This can only be done on the last frame set in the file and should
7489 // * be done e.g. if the last frame set in the file has fewer frames than
7490 // * default or after compressing data blocks in a frame set.
7491 // * @param tng_data is a trajectory data container.
7492 // * @details the current_trajectory_frame_set is the one that will be modified.
7493 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7494 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7495 // * FIXME: This function is not finished!!!
7497 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7499 // tng_gen_block_t block;
7500 // tng_trajectory_frame_set_t frame_set;
7501 // FILE *temp = tng_data->input_file;
7502 // int64_t pos, contents_start_pos, output_file_len;
7504 // frame_set = &tng_data->current_trajectory_frame_set;
7506 // if(frame_set->n_written_frames == frame_set->n_frames)
7508 // return(TNG_SUCCESS);
7511 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7512 // tng_data->last_trajectory_frame_set_output_file_pos)
7516 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7518 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7519 // __FILE__, __LINE__);
7520 // return(TNG_CRITICAL);
7523 // tng_block_init(&block);
7524 // // output_file_pos = ftell(tng_data->output_file);
7526 // tng_data->input_file = tng_data->output_file;
7528 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7530 // fseek(tng_data->output_file, pos, SEEK_SET);
7531 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7533 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7534 // __FILE__, __LINE__);
7535 // tng_data->input_file = temp;
7536 // tng_block_destroy(&block);
7537 // return(TNG_CRITICAL);
7540 // contents_start_pos = ftell(tng_data->output_file);
7542 // fseek(tng_data->output_file, 0, SEEK_END);
7543 // output_file_len = ftell(tng_data->output_file);
7544 // pos = contents_start_pos + block->block_contents_size;
7545 // fseek(tng_data->output_file, pos,
7548 // while(pos < output_file_len)
7550 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7552 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7553 // __FILE__, __LINE__);
7554 // tng_data->input_file = temp;
7555 // tng_block_destroy(&block);
7556 // return(TNG_CRITICAL);
7558 // pos += block->header_contents_size + block->block_contents_size;
7559 // fseek(tng_data->output_file, pos, SEEK_SET);
7562 // return(TNG_SUCCESS);
7565 /** Finish writing the current frame set. Update the number of frames
7566 * and the hashes of the frame set and all its data blocks (if hash_mode
7568 * @param tng_data is a trajectory data container.
7569 * @param hash_mode specifies whether to update the block md5 hash when
7570 * updating the pointers.
7571 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7572 * error has occured.
7574 static tng_function_status tng_frame_set_finalize
7575 (tng_trajectory_t tng_data, const char hash_mode)
7577 tng_gen_block_t block;
7578 tng_trajectory_frame_set_t frame_set;
7579 FILE *temp = tng_data->input_file;
7580 int64_t pos, contents_start_pos, output_file_len;
7582 frame_set = &tng_data->current_trajectory_frame_set;
7584 if(frame_set->n_written_frames == frame_set->n_frames)
7586 return(TNG_SUCCESS);
7589 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7591 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7592 __FILE__, __LINE__);
7593 return(TNG_CRITICAL);
7596 tng_block_init(&block);
7597 /* output_file_pos = ftell(tng_data->output_file); */
7599 tng_data->input_file = tng_data->output_file;
7601 pos = tng_data->current_trajectory_frame_set_output_file_pos;
7603 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7605 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7607 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7608 __FILE__, __LINE__);
7609 tng_data->input_file = temp;
7610 tng_block_destroy(&block);
7611 return(TNG_CRITICAL);
7614 contents_start_pos = ftell(tng_data->output_file);
7616 fseek(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
7617 if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
7618 1, tng_data->output_file) != 1)
7620 tng_data->input_file = temp;
7621 tng_block_destroy(&block);
7622 return(TNG_CRITICAL);
7626 if(hash_mode == TNG_USE_HASH)
7628 tng_md5_hash_update(tng_data, block, pos,
7629 pos + block->header_contents_size);
7632 fseek(tng_data->output_file, 0, SEEK_END);
7633 output_file_len = ftell(tng_data->output_file);
7634 pos = contents_start_pos + block->block_contents_size;
7635 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7637 while(pos < output_file_len)
7639 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7641 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7642 __FILE__, __LINE__);
7643 tng_data->input_file = temp;
7644 tng_block_destroy(&block);
7645 return(TNG_CRITICAL);
7648 if(hash_mode == TNG_USE_HASH)
7650 tng_md5_hash_update(tng_data, block, pos,
7651 pos + block->header_contents_size);
7653 pos += block->header_contents_size + block->block_contents_size;
7654 fseek(tng_data->output_file, (long)pos, SEEK_SET);
7657 tng_data->input_file = temp;
7658 tng_block_destroy(&block);
7659 return(TNG_SUCCESS);
7663 // ** Sets the name of a file contents block
7664 // * @param tng_data is a trajectory data container.
7665 // * @param block is the block, of which to change names.
7666 // * @param new_name is the new name of the block.
7667 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7668 // * error has occured.
7670 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7671 // tng_gen_block_t block,
7672 // const char *new_name)
7676 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7678 // * If the currently stored string length is not enough to store the new
7679 // * string it is freed and reallocated. *
7680 // if(block->name && strlen(block->name) < len)
7682 // free(block->name);
7687 // block->name = malloc(len);
7690 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7691 // __FILE__, __LINE__);
7692 // return(TNG_CRITICAL);
7696 // strncpy(block->name, new_name, len);
7698 // return(TNG_SUCCESS);
7702 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
7703 const tng_atom_t atom,
7704 tng_residue_t *residue)
7708 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7710 *residue = atom->residue;
7712 return(TNG_SUCCESS);
7715 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
7716 const tng_atom_t atom,
7721 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7722 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7724 strncpy(name, atom->name, max_len - 1);
7725 name[max_len - 1] = 0;
7727 if(strlen(atom->name) > (unsigned int)max_len - 1)
7729 return(TNG_FAILURE);
7731 return(TNG_SUCCESS);
7734 tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
7736 const char *new_name)
7741 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7742 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7744 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7746 /* If the currently stored string length is not enough to store the new
7747 * string it is freed and reallocated. */
7748 if(atom->name && strlen(atom->name) < len)
7755 atom->name = malloc(len);
7758 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7759 __FILE__, __LINE__);
7760 return(TNG_CRITICAL);
7764 strncpy(atom->name, new_name, len);
7766 return(TNG_SUCCESS);
7769 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
7770 const tng_atom_t atom,
7775 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
7776 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
7778 strncpy(type, atom->atom_type, max_len - 1);
7779 type[max_len - 1] = 0;
7781 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
7783 return(TNG_FAILURE);
7785 return(TNG_SUCCESS);
7788 tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
7790 const char *new_type)
7795 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7796 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
7798 len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
7800 /* If the currently stored string length is not enough to store the new
7801 * string it is freed and reallocated. */
7802 if(atom->atom_type && strlen(atom->atom_type) < len)
7804 free(atom->atom_type);
7805 atom->atom_type = 0;
7807 if(!atom->atom_type)
7809 atom->atom_type = malloc(len);
7810 if(!atom->atom_type)
7812 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7813 __FILE__, __LINE__);
7814 return(TNG_CRITICAL);
7818 strncpy(atom->atom_type, new_type, len);
7820 return(TNG_SUCCESS);
7823 /** Initialise an atom struct
7824 * @param atom is the atom to initialise.
7825 * @return TNG_SUCCESS (0) if successful.
7827 static tng_function_status tng_atom_init(tng_atom_t atom)
7830 atom->atom_type = 0;
7832 return(TNG_SUCCESS);
7835 /** Free the memory in an atom struct
7836 * @param atom is the atom to destroy.
7837 * @return TNG_SUCCESS (0) if successful.
7839 static tng_function_status tng_atom_destroy(tng_atom_t atom)
7848 free(atom->atom_type);
7849 atom->atom_type = 0;
7852 return(TNG_SUCCESS);
7855 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7856 (tng_trajectory_t tng_data,
7858 tng_molecule_t *molecule)
7862 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7863 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7865 /* Set ID to the ID of the last molecule + 1 */
7866 if(tng_data->n_molecules)
7868 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7875 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
7878 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7879 (tng_trajectory_t tng_data,
7882 tng_molecule_t *molecule)
7884 tng_molecule_t new_molecules;
7885 int64_t *new_molecule_cnt_list;
7886 tng_function_status stat = TNG_SUCCESS;
7888 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7889 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7891 new_molecules = realloc(tng_data->molecules,
7892 sizeof(struct tng_molecule) *
7893 (tng_data->n_molecules + 1));
7897 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7898 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7899 __FILE__, __LINE__);
7900 free(tng_data->molecules);
7901 tng_data->molecules = 0;
7902 return(TNG_CRITICAL);
7905 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7907 (tng_data->n_molecules + 1));
7909 if(!new_molecule_cnt_list)
7911 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7912 sizeof(int64_t) * (tng_data->n_molecules + 1),
7913 __FILE__, __LINE__);
7914 free(tng_data->molecule_cnt_list);
7915 tng_data->molecule_cnt_list = 0;
7916 free(new_molecules);
7917 return(TNG_CRITICAL);
7920 tng_data->molecules = new_molecules;
7921 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7923 *molecule = &new_molecules[tng_data->n_molecules];
7925 tng_molecule_init(tng_data, *molecule);
7926 tng_molecule_name_set(tng_data, *molecule, name);
7928 /* FIXME: Should this be a function argument instead? */
7929 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7931 (*molecule)->id = id;
7933 tng_data->n_molecules++;
7938 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
7939 (tng_trajectory_t tng_data,
7940 tng_molecule_t *molecule_p)
7942 int64_t *new_molecule_cnt_list, id;
7943 tng_molecule_t new_molecules, molecule;
7945 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7947 /* Set ID to the ID of the last molecule + 1 */
7948 if(tng_data->n_molecules)
7950 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7957 new_molecules = realloc(tng_data->molecules,
7958 sizeof(struct tng_molecule) *
7959 (tng_data->n_molecules + 1));
7963 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7964 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7965 __FILE__, __LINE__);
7966 free(tng_data->molecules);
7967 tng_data->molecules = 0;
7968 return(TNG_CRITICAL);
7971 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7973 (tng_data->n_molecules + 1));
7975 if(!new_molecule_cnt_list)
7977 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
7978 sizeof(int64_t) * (tng_data->n_molecules + 1),
7979 __FILE__, __LINE__);
7980 free(tng_data->molecule_cnt_list);
7981 tng_data->molecule_cnt_list = 0;
7982 free(new_molecules);
7983 return(TNG_CRITICAL);
7986 molecule = *molecule_p;
7988 tng_data->molecules = new_molecules;
7989 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7991 new_molecules[tng_data->n_molecules] = *molecule;
7993 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7997 molecule = &new_molecules[tng_data->n_molecules];
7999 *molecule_p = molecule;
8003 tng_data->n_molecules++;
8005 return(TNG_SUCCESS);
8008 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
8009 const tng_molecule_t molecule,
8014 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8015 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8017 strncpy(name, molecule->name, max_len - 1);
8018 name[max_len - 1] = 0;
8020 if(strlen(molecule->name) > (unsigned int)max_len - 1)
8022 return(TNG_FAILURE);
8024 return(TNG_SUCCESS);
8027 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8028 (tng_trajectory_t tng_data,
8029 tng_molecule_t molecule,
8030 const char *new_name)
8035 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8036 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8038 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8040 /* If the currently stored string length is not enough to store the new
8041 * string it is freed and reallocated. */
8042 if(molecule->name && strlen(molecule->name) < len)
8044 free(molecule->name);
8049 molecule->name = malloc(len);
8052 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8053 __FILE__, __LINE__);
8054 return(TNG_CRITICAL);
8058 strncpy(molecule->name, new_name, len);
8060 return(TNG_SUCCESS);
8063 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8064 (const tng_trajectory_t tng_data,
8065 const tng_molecule_t molecule,
8068 int64_t i, index = -1;
8070 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8071 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
8073 for(i = 0; i < tng_data->n_molecules; i++)
8075 if(&tng_data->molecules[i] == molecule)
8083 return(TNG_FAILURE);
8085 *cnt = tng_data->molecule_cnt_list[index];
8087 return(TNG_SUCCESS);
8090 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8091 (tng_trajectory_t tng_data,
8092 tng_molecule_t molecule,
8095 int64_t i, old_cnt, index = -1;
8097 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8099 for(i = 0; i < tng_data->n_molecules; i++)
8101 if(&tng_data->molecules[i] == molecule)
8109 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8110 __FILE__, __LINE__);
8111 return(TNG_FAILURE);
8113 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
8115 old_cnt = tng_data->molecule_cnt_list[index];
8116 tng_data->molecule_cnt_list[index] = cnt;
8118 tng_data->n_particles += (cnt-old_cnt) *
8119 tng_data->molecules[index].n_atoms;
8123 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
8124 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
8126 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
8127 tng_data->molecules[index].n_atoms;
8130 return(TNG_SUCCESS);
8133 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8134 (tng_trajectory_t tng_data,
8137 tng_molecule_t *molecule)
8139 int64_t i, n_molecules;
8141 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8142 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8143 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8145 n_molecules = tng_data->n_molecules;
8147 for(i = n_molecules - 1; i >= 0; i--)
8149 *molecule = &tng_data->molecules[i];
8150 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
8152 if(nr == -1 || nr == (*molecule)->id)
8154 return(TNG_SUCCESS);
8161 return(TNG_FAILURE);
8164 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8165 (tng_trajectory_t tng_data,
8167 tng_molecule_t *molecule)
8169 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8170 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8172 if(index >= tng_data->n_molecules)
8175 return(TNG_FAILURE);
8177 *molecule = &tng_data->molecules[index];
8178 return(TNG_SUCCESS);
8181 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
8182 tng_trajectory_t tng_data_dest)
8184 tng_molecule_t molecule, molecule_temp;
8185 tng_chain_t chain, chain_temp;
8186 tng_residue_t residue, residue_temp;
8187 tng_atom_t atom, atom_temp;
8188 tng_bond_t bond_temp;
8189 tng_function_status stat;
8190 int64_t i, j, k, l, *list_temp;
8192 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
8193 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
8195 for(i = 0; i < tng_data_dest->n_molecules; i++)
8197 molecule = &tng_data_dest->molecules[i];
8198 tng_molecule_destroy(tng_data_dest, molecule);
8201 tng_data_dest->n_molecules = 0;
8202 tng_data_dest->n_particles = 0;
8204 molecule_temp = realloc(tng_data_dest->molecules,
8205 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
8208 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8209 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
8210 __FILE__, __LINE__);
8211 free(tng_data_dest->molecules);
8212 tng_data_dest->molecules = 0;
8213 return(TNG_CRITICAL);
8215 list_temp = realloc(tng_data_dest->molecule_cnt_list,
8216 sizeof(int64_t) * tng_data_src->n_molecules);
8219 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8220 sizeof(int64_t) * tng_data_src->n_molecules,
8221 __FILE__, __LINE__);
8222 free(tng_data_dest->molecule_cnt_list);
8223 tng_data_dest->molecule_cnt_list = 0;
8224 free(molecule_temp);
8225 return(TNG_CRITICAL);
8228 tng_data_dest->molecules = molecule_temp;
8229 tng_data_dest->molecule_cnt_list = list_temp;
8231 for(i = 0; i < tng_data_src->n_molecules; i++)
8233 molecule = &tng_data_src->molecules[i];
8234 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
8236 if(stat != TNG_SUCCESS)
8238 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8239 __FILE__, __LINE__);
8242 molecule_temp->quaternary_str = molecule->quaternary_str;
8243 for(j = 0; j < molecule->n_chains; j++)
8245 chain = &molecule->chains[j];
8246 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
8247 chain->name, chain->id,
8249 if(stat != TNG_SUCCESS)
8251 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8252 __FILE__, __LINE__);
8255 for(k = 0; k < chain->n_residues; k++)
8257 residue = &chain->residues[k];
8258 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
8259 residue->name, residue->id,
8261 if(stat != TNG_SUCCESS)
8263 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8264 __FILE__, __LINE__);
8267 for(l = 0; l < residue->n_atoms; l++)
8269 atom = &molecule->atoms[residue->atoms_offset + l];
8270 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
8271 atom->name, atom->atom_type,
8272 atom->id, &atom_temp);
8273 if(stat != TNG_SUCCESS)
8275 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8276 __FILE__, __LINE__);
8282 molecule_temp->n_bonds = molecule->n_bonds;
8283 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8287 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8288 sizeof(struct tng_bond) * molecule->n_bonds,
8289 __FILE__, __LINE__);
8290 free(molecule_temp->bonds);
8291 molecule_temp->n_bonds = 0;
8292 return(TNG_CRITICAL);
8294 molecule_temp->bonds = bond_temp;
8295 for(j = 0; j < molecule->n_bonds; j++)
8297 molecule_temp->bonds[j] = molecule->bonds[j];
8299 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
8300 tng_data_src->molecule_cnt_list[i]);
8301 if(stat != TNG_SUCCESS)
8303 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
8304 __FILE__, __LINE__);
8308 return(TNG_SUCCESS);
8311 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8312 (const tng_trajectory_t tng_data,
8313 const tng_molecule_t molecule,
8317 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8318 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8320 *n = molecule->n_chains;
8322 return(TNG_SUCCESS);
8325 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8326 (tng_trajectory_t tng_data,
8327 tng_molecule_t molecule,
8332 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8333 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8335 if(index >= molecule->n_chains)
8338 return(TNG_FAILURE);
8340 *chain = &molecule->chains[index];
8341 return(TNG_SUCCESS);
8344 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8345 (const tng_trajectory_t tng_data,
8346 const tng_molecule_t molecule,
8350 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8351 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8353 *n = molecule->n_residues;
8355 return(TNG_SUCCESS);
8358 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8359 (const tng_trajectory_t tng_data,
8360 const tng_molecule_t molecule,
8361 const int64_t index,
8362 tng_residue_t *residue)
8365 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8366 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8368 if(index >= molecule->n_residues)
8371 return(TNG_FAILURE);
8373 *residue = &molecule->residues[index];
8374 return(TNG_SUCCESS);
8377 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8378 (const tng_trajectory_t tng_data,
8379 const tng_molecule_t molecule,
8383 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
8384 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8386 *n = molecule->n_atoms;
8388 return(TNG_SUCCESS);
8391 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8392 (const tng_trajectory_t tng_data,
8393 const tng_molecule_t molecule,
8394 const int64_t index,
8398 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
8399 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8401 if(index >= molecule->n_atoms)
8404 return(TNG_FAILURE);
8406 *atom = &molecule->atoms[index];
8407 return(TNG_SUCCESS);
8410 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8411 (tng_trajectory_t tng_data,
8412 tng_molecule_t molecule,
8417 int64_t i, n_chains;
8420 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8421 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8423 n_chains = molecule->n_chains;
8425 for(i = n_chains - 1; i >= 0; i--)
8427 *chain = &molecule->chains[i];
8428 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
8430 if(nr == -1 || nr == (*chain)->id)
8432 return(TNG_SUCCESS);
8439 return(TNG_FAILURE);
8442 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8443 (tng_trajectory_t tng_data,
8444 tng_molecule_t molecule,
8450 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8451 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8453 /* Set ID to the ID of the last chain + 1 */
8454 if(molecule->n_chains)
8456 id = molecule->chains[molecule->n_chains-1].id + 1;
8463 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8467 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8468 (tng_trajectory_t tng_data,
8469 tng_molecule_t molecule,
8474 tng_chain_t new_chains;
8475 tng_function_status stat = TNG_SUCCESS;
8477 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8478 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8480 new_chains = realloc(molecule->chains,
8481 sizeof(struct tng_chain) *
8482 (molecule->n_chains + 1));
8486 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8487 sizeof(struct tng_chain) * (molecule->n_chains + 1),
8488 __FILE__, __LINE__);
8489 free(molecule->chains);
8490 molecule->chains = 0;
8491 return(TNG_CRITICAL);
8494 molecule->chains = new_chains;
8496 *chain = &new_chains[molecule->n_chains];
8499 tng_chain_name_set(tng_data, *chain, name);
8501 (*chain)->molecule = molecule;
8502 (*chain)->n_residues = 0;
8504 molecule->n_chains++;
8511 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8512 (const tng_trajectory_t tng_data,
8513 tng_molecule_t molecule,
8514 const int64_t from_atom_id,
8515 const int64_t to_atom_id,
8518 tng_bond_t new_bonds;
8521 new_bonds = realloc(molecule->bonds,
8522 sizeof(struct tng_bond) *
8523 (molecule->n_bonds + 1));
8527 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8528 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
8529 __FILE__, __LINE__);
8531 free(molecule->bonds);
8532 molecule->bonds = 0;
8533 return(TNG_CRITICAL);
8536 molecule->bonds = new_bonds;
8538 *bond = &new_bonds[molecule->n_bonds];
8540 (*bond)->from_atom_id = from_atom_id;
8541 (*bond)->to_atom_id = to_atom_id;
8543 molecule->n_bonds++;
8545 return(TNG_SUCCESS);
8548 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8549 (tng_trajectory_t tng_data,
8550 tng_molecule_t molecule,
8558 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8560 n_atoms = molecule->n_atoms;
8562 for(i = n_atoms - 1; i >= 0; i--)
8564 *atom = &molecule->atoms[i];
8565 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
8567 if(id == -1 || id == (*atom)->id)
8569 return(TNG_SUCCESS);
8576 return(TNG_FAILURE);
8579 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8580 const tng_chain_t chain,
8585 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8586 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8588 strncpy(name, chain->name, max_len - 1);
8589 name[max_len - 1] = 0;
8591 if(strlen(chain->name) > (unsigned int)max_len - 1)
8593 return(TNG_FAILURE);
8595 return(TNG_SUCCESS);
8598 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8599 (tng_trajectory_t tng_data,
8601 const char *new_name)
8606 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
8608 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8610 /* If the currently stored string length is not enough to store the new
8611 * string it is freed and reallocated. */
8612 if(chain->name && strlen(chain->name) < len)
8619 chain->name = malloc(len);
8622 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8623 __FILE__, __LINE__);
8624 return(TNG_CRITICAL);
8628 strncpy(chain->name, new_name, len);
8630 return(TNG_SUCCESS);
8633 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8634 (const tng_trajectory_t tng_data,
8635 const tng_chain_t chain,
8639 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
8640 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8642 *n = chain->n_residues;
8644 return(TNG_SUCCESS);
8647 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8648 (const tng_trajectory_t tng_data,
8649 const tng_chain_t chain,
8650 const int64_t index,
8651 tng_residue_t *residue)
8654 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
8655 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8657 if(index >= chain->n_residues)
8660 return(TNG_FAILURE);
8662 *residue = &chain->residues[index];
8663 return(TNG_SUCCESS);
8666 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8667 (tng_trajectory_t tng_data,
8671 tng_residue_t *residue)
8673 int64_t i, n_residues;
8676 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8678 n_residues = chain->n_residues;
8680 for(i = n_residues - 1; i >= 0; i--)
8682 *residue = &chain->residues[i];
8683 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
8685 if(id == -1 || id == (*residue)->id)
8687 return(TNG_SUCCESS);
8694 return(TNG_FAILURE);
8697 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8698 (tng_trajectory_t tng_data,
8701 tng_residue_t *residue)
8705 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8706 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8708 /* Set ID to the ID of the last residue + 1 */
8709 if(chain->n_residues)
8711 id = chain->residues[chain->n_residues-1].id + 1;
8718 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8722 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8723 (tng_trajectory_t tng_data,
8727 tng_residue_t *residue)
8730 tng_residue_t new_residues, temp_residue, last_residue;
8731 tng_molecule_t molecule = chain->molecule;
8732 tng_function_status stat = TNG_SUCCESS;
8734 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8735 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8737 if(chain->n_residues)
8739 curr_index = chain->residues - molecule->residues;
8746 new_residues = realloc(molecule->residues,
8747 sizeof(struct tng_residue) *
8748 (molecule->n_residues + 1));
8752 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8753 sizeof(struct tng_residue) * (molecule->n_residues + 1),
8754 __FILE__, __LINE__);
8755 free(molecule->residues);
8756 molecule->residues = 0;
8757 return(TNG_CRITICAL);
8760 molecule->residues = new_residues;
8762 if(curr_index != -1)
8764 chain->residues = new_residues + curr_index;
8765 if(molecule->n_residues)
8767 last_residue = &new_residues[molecule->n_residues - 1];
8769 temp_residue = chain->residues + (chain->n_residues - 1);
8770 /* Make space in list of residues to add the new residues together with the other
8771 * residues of this chain */
8772 if(temp_residue != last_residue)
8775 memmove(temp_residue + 1, temp_residue,
8776 last_residue - temp_residue);
8782 curr_index = molecule->n_residues;
8785 *residue = &molecule->residues[curr_index + chain->n_residues];
8787 if(!chain->n_residues)
8789 chain->residues = *residue;
8793 chain->residues = &molecule->residues[curr_index];
8796 (*residue)->name = 0;
8797 tng_residue_name_set(tng_data, *residue, name);
8799 (*residue)->chain = chain;
8800 (*residue)->n_atoms = 0;
8801 (*residue)->atoms_offset = 0;
8803 chain->n_residues++;
8804 molecule->n_residues++;
8806 (*residue)->id = id;
8811 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8812 const tng_residue_t residue,
8817 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8818 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
8820 strncpy(name, residue->name, max_len - 1);
8821 name[max_len - 1] = 0;
8823 if(strlen(residue->name) > (unsigned int)max_len - 1)
8825 return(TNG_FAILURE);
8827 return(TNG_SUCCESS);
8830 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
8831 tng_residue_t residue,
8832 const char *new_name)
8837 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8838 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
8840 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
8842 /* If the currently stored string length is not enough to store the new
8843 * string it is freed and reallocated. */
8844 if(residue->name && strlen(residue->name) < len)
8846 free(residue->name);
8851 residue->name = malloc(len);
8854 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
8855 __FILE__, __LINE__);
8856 return(TNG_CRITICAL);
8860 strncpy(residue->name, new_name, len);
8862 return(TNG_SUCCESS);
8865 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8866 (const tng_trajectory_t tng_data,
8867 const tng_residue_t residue,
8871 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
8872 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
8874 *n = residue->n_atoms;
8876 return(TNG_SUCCESS);
8879 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8880 (const tng_trajectory_t tng_data,
8881 const tng_residue_t residue,
8882 const int64_t index,
8886 tng_molecule_t molecule;
8889 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
8890 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
8892 if(index >= residue->n_atoms)
8895 return(TNG_FAILURE);
8897 chain = residue->chain;
8898 molecule = chain->molecule;
8900 if(index + residue->atoms_offset >= molecule->n_atoms)
8903 return(TNG_FAILURE);
8906 *atom = &molecule->atoms[residue->atoms_offset + index];
8907 return(TNG_SUCCESS);
8910 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8911 (tng_trajectory_t tng_data,
8912 tng_residue_t residue,
8913 const char *atom_name,
8914 const char *atom_type,
8919 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8920 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8921 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8923 /* Set ID to the ID of the last atom + 1 */
8924 if(residue->chain->molecule->n_atoms)
8926 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
8933 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
8937 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
8938 (tng_trajectory_t tng_data,
8939 tng_residue_t residue,
8940 const char *atom_name,
8941 const char *atom_type,
8945 tng_atom_t new_atoms;
8946 tng_molecule_t molecule = residue->chain->molecule;
8947 tng_function_status stat = TNG_SUCCESS;
8949 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8950 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8951 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8953 if(!residue->n_atoms)
8955 residue->atoms_offset = molecule->n_atoms;
8958 new_atoms = realloc(molecule->atoms,
8959 sizeof(struct tng_atom) *
8960 (molecule->n_atoms + 1));
8964 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
8965 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
8966 __FILE__, __LINE__);
8967 free(molecule->atoms);
8968 molecule->atoms = 0;
8969 return(TNG_CRITICAL);
8972 molecule->atoms = new_atoms;
8974 *atom = &new_atoms[molecule->n_atoms];
8976 tng_atom_init(*atom);
8977 tng_atom_name_set(tng_data, *atom, atom_name);
8978 tng_atom_type_set(tng_data, *atom, atom_type);
8980 (*atom)->residue = residue;
8983 molecule->n_atoms++;
8990 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8991 tng_molecule_t *molecule_p)
8993 *molecule_p = malloc(sizeof(struct tng_molecule));
8996 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
8997 sizeof(struct tng_molecule), __FILE__, __LINE__);
8998 return(TNG_CRITICAL);
9001 tng_molecule_init(tng_data, *molecule_p);
9003 return(TNG_SUCCESS);
9006 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
9007 tng_molecule_t *molecule_p)
9011 return(TNG_SUCCESS);
9014 tng_molecule_destroy(tng_data, *molecule_p);
9019 return(TNG_SUCCESS);
9022 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9023 tng_molecule_t molecule)
9026 molecule->quaternary_str = 1;
9028 molecule->n_chains = 0;
9029 molecule->chains = 0;
9030 molecule->n_residues = 0;
9031 molecule->residues = 0;
9032 molecule->n_atoms = 0;
9033 molecule->atoms = 0;
9034 molecule->n_bonds = 0;
9035 molecule->bonds = 0;
9037 return(TNG_SUCCESS);
9040 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
9041 tng_molecule_t molecule)
9048 free(molecule->name);
9052 if(molecule->chains)
9054 for(i = 0; i < molecule->n_chains; i++)
9056 if(molecule->chains[i].name)
9058 free(molecule->chains[i].name);
9059 molecule->chains[i].name = 0;
9062 free(molecule->chains);
9063 molecule->chains = 0;
9065 molecule->n_chains = 0;
9067 if(molecule->residues)
9069 for(i = 0; i < molecule->n_residues; i++)
9071 if(molecule->residues[i].name)
9073 free(molecule->residues[i].name);
9074 molecule->residues[i].name = 0;
9077 free(molecule->residues);
9078 molecule->residues = 0;
9080 molecule->n_residues = 0;
9084 for(i = 0; i < molecule->n_atoms; i++)
9086 tng_atom_destroy(&molecule->atoms[i]);
9088 free(molecule->atoms);
9089 molecule->atoms = 0;
9091 molecule->n_atoms = 0;
9095 free(molecule->bonds);
9096 molecule->bonds = 0;
9098 molecule->n_bonds = 0;
9100 return(TNG_SUCCESS);
9103 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9104 (const tng_trajectory_t tng_data,
9109 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9111 tng_bool found = TNG_FALSE;
9113 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9114 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9116 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9118 if(!molecule_cnt_list)
9120 return(TNG_FAILURE);
9123 for(i = 0; i < tng_data->n_molecules; i++)
9125 mol = &tng_data->molecules[i];
9126 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9128 cnt += mol->n_atoms * molecule_cnt_list[i];
9136 return(TNG_FAILURE);
9139 strncpy(name, mol->name, max_len - 1);
9140 name[max_len - 1] = 0;
9142 if(strlen(mol->name) > (unsigned int)max_len - 1)
9144 return(TNG_FAILURE);
9146 return(TNG_SUCCESS);
9149 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9150 (const tng_trajectory_t tng_data,
9154 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9156 tng_bool found = TNG_FALSE;
9158 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9159 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9161 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9163 if(!molecule_cnt_list)
9165 return(TNG_FAILURE);
9168 for(i = 0; i < tng_data->n_molecules; i++)
9170 mol = &tng_data->molecules[i];
9171 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9173 cnt += mol->n_atoms * molecule_cnt_list[i];
9181 return(TNG_FAILURE);
9186 return(TNG_SUCCESS);
9189 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9190 (const tng_trajectory_t tng_data,
9192 int64_t **from_atoms,
9195 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9196 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9200 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9201 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
9202 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
9203 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
9205 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9207 if(!molecule_cnt_list)
9209 return(TNG_FAILURE);
9213 /* First count the total number of bonds to allocate memory */
9214 for(i = 0; i < tng_data->n_molecules; i++)
9216 mol = &tng_data->molecules[i];
9217 mol_cnt = molecule_cnt_list[i];
9218 *n_bonds += mol_cnt * mol->n_bonds;
9222 return(TNG_SUCCESS);
9225 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9228 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9229 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9230 return(TNG_CRITICAL);
9232 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9235 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9236 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9239 return(TNG_CRITICAL);
9243 for(i = 0; i < tng_data->n_molecules; i++)
9245 mol = &tng_data->molecules[i];
9246 mol_cnt = molecule_cnt_list[i];
9247 for(j = 0; j < mol_cnt; j++)
9249 for(k = 0; k < mol->n_bonds; k++)
9251 bond = &mol->bonds[k];
9252 from_atom = atom_cnt + bond->from_atom_id;
9253 to_atom = atom_cnt + bond->to_atom_id;
9254 (*from_atoms)[cnt] = from_atom;
9255 (*to_atoms)[cnt++] = to_atom;
9257 atom_cnt += mol->n_atoms;
9261 return(TNG_SUCCESS);
9264 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9265 (const tng_trajectory_t tng_data,
9270 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9273 tng_bool found = TNG_FALSE;
9275 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9276 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9278 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9280 if(!molecule_cnt_list)
9282 return(TNG_FAILURE);
9285 for(i = 0; i < tng_data->n_molecules; i++)
9287 mol = &tng_data->molecules[i];
9288 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9290 cnt += mol->n_atoms * molecule_cnt_list[i];
9293 atom = &mol->atoms[nr % mol->n_atoms];
9299 return(TNG_FAILURE);
9301 if(!atom->residue || !atom->residue->chain)
9303 return(TNG_FAILURE);
9306 strncpy(name, atom->residue->chain->name, max_len - 1);
9307 name[max_len - 1] = 0;
9309 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
9311 return(TNG_FAILURE);
9313 return(TNG_SUCCESS);
9316 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9317 (const tng_trajectory_t tng_data,
9322 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9325 tng_bool found = TNG_FALSE;
9327 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9328 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9330 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9332 if(!molecule_cnt_list)
9334 return(TNG_FAILURE);
9337 for(i = 0; i < tng_data->n_molecules; i++)
9339 mol = &tng_data->molecules[i];
9340 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9342 cnt += mol->n_atoms * molecule_cnt_list[i];
9345 atom = &mol->atoms[nr % mol->n_atoms];
9351 return(TNG_FAILURE);
9355 return(TNG_FAILURE);
9358 strncpy(name, atom->residue->name, max_len - 1);
9359 name[max_len - 1] = 0;
9361 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
9363 return(TNG_FAILURE);
9365 return(TNG_SUCCESS);
9368 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9369 (const tng_trajectory_t tng_data,
9373 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9376 tng_bool found = TNG_FALSE;
9378 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9379 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9381 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9383 if(!molecule_cnt_list)
9385 return(TNG_FAILURE);
9388 for(i = 0; i < tng_data->n_molecules; i++)
9390 mol = &tng_data->molecules[i];
9391 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9393 cnt += mol->n_atoms * molecule_cnt_list[i];
9396 atom = &mol->atoms[nr % mol->n_atoms];
9402 return(TNG_FAILURE);
9406 return(TNG_FAILURE);
9409 *id = atom->residue->id;
9411 return(TNG_SUCCESS);
9414 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9415 (const tng_trajectory_t tng_data,
9419 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9422 tng_bool found = TNG_FALSE;
9424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9425 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9427 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9429 if(!molecule_cnt_list)
9431 return(TNG_FAILURE);
9434 for(i = 0; i < tng_data->n_molecules; i++)
9436 mol = &tng_data->molecules[i];
9437 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9439 cnt += mol->n_atoms * molecule_cnt_list[i];
9440 offset += mol->n_residues * molecule_cnt_list[i];
9443 atom = &mol->atoms[nr % mol->n_atoms];
9449 return(TNG_FAILURE);
9453 return(TNG_FAILURE);
9456 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
9458 *id = atom->residue->id + offset;
9460 return(TNG_SUCCESS);
9463 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9464 (const tng_trajectory_t tng_data,
9469 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9472 tng_bool found = TNG_FALSE;
9474 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9475 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
9477 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9479 if(!molecule_cnt_list)
9481 return(TNG_FAILURE);
9484 for(i = 0; i < tng_data->n_molecules; i++)
9486 mol = &tng_data->molecules[i];
9487 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9489 cnt += mol->n_atoms * molecule_cnt_list[i];
9492 atom = &mol->atoms[nr % mol->n_atoms];
9498 return(TNG_FAILURE);
9501 strncpy(name, atom->name, max_len - 1);
9502 name[max_len - 1] = 0;
9504 if(strlen(atom->name) > (unsigned int)max_len - 1)
9506 return(TNG_FAILURE);
9508 return(TNG_SUCCESS);
9511 tng_function_status tng_atom_type_of_particle_nr_get
9512 (const tng_trajectory_t tng_data,
9517 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9520 tng_bool found = TNG_FALSE;
9522 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9523 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
9525 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9527 if(!molecule_cnt_list)
9529 return(TNG_FAILURE);
9532 for(i = 0; i < tng_data->n_molecules; i++)
9534 mol = &tng_data->molecules[i];
9535 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9537 cnt += mol->n_atoms * molecule_cnt_list[i];
9540 atom = &mol->atoms[nr % mol->n_atoms];
9546 return(TNG_FAILURE);
9549 strncpy(type, atom->atom_type, max_len - 1);
9550 type[max_len - 1] = 0;
9552 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
9554 return(TNG_FAILURE);
9556 return(TNG_SUCCESS);
9559 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9560 (tng_trajectory_t tng_data,
9561 const int64_t num_first_particle,
9562 const int64_t n_particles,
9563 const int64_t *mapping_table)
9566 tng_particle_mapping_t mapping;
9567 tng_trajectory_frame_set_t frame_set;
9569 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9571 frame_set = &tng_data->current_trajectory_frame_set;
9573 /* Sanity check of the particle ranges. Split into multiple if
9574 * statements for improved readability */
9575 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9577 mapping = &frame_set->mappings[i];
9578 if(num_first_particle >= mapping->num_first_particle &&
9579 num_first_particle < mapping->num_first_particle +
9580 mapping->n_particles)
9582 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9583 return(TNG_FAILURE);
9585 if(num_first_particle + n_particles >=
9586 mapping->num_first_particle &&
9587 num_first_particle + n_particles <
9588 mapping->num_first_particle + mapping->n_particles)
9590 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9591 return(TNG_FAILURE);
9593 if(mapping->num_first_particle >= num_first_particle &&
9594 mapping->num_first_particle < num_first_particle +
9597 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9598 return(TNG_FAILURE);
9600 if(mapping->num_first_particle + mapping->n_particles >
9601 num_first_particle &&
9602 mapping->num_first_particle + mapping->n_particles <
9603 num_first_particle + n_particles)
9605 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
9606 return(TNG_FAILURE);
9610 frame_set->n_mapping_blocks++;
9612 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
9613 frame_set->n_mapping_blocks);
9617 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9618 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
9619 __FILE__, __LINE__);
9620 free(frame_set->mappings);
9621 frame_set->mappings = 0;
9622 return(TNG_CRITICAL);
9624 frame_set->mappings = mapping;
9626 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
9627 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
9629 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
9630 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
9632 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9633 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
9634 return(TNG_CRITICAL);
9637 for(i=0; i<n_particles; i++)
9639 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
9642 return(TNG_SUCCESS);
9645 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
9647 tng_trajectory_frame_set_t frame_set;
9648 tng_particle_mapping_t mapping;
9651 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9653 frame_set = &tng_data->current_trajectory_frame_set;
9655 if(frame_set->n_mapping_blocks && frame_set->mappings)
9657 for(i = 0; i < frame_set->n_mapping_blocks; i++)
9659 mapping = &frame_set->mappings[i];
9660 if(mapping->real_particle_numbers)
9662 free(mapping->real_particle_numbers);
9663 mapping->real_particle_numbers = 0;
9666 free(frame_set->mappings);
9667 frame_set->mappings = 0;
9668 frame_set->n_mapping_blocks = 0;
9671 return(TNG_SUCCESS);
9674 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
9677 tng_trajectory_frame_set_t frame_set;
9678 tng_trajectory_t tng_data;
9680 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9683 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9684 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9685 return(TNG_CRITICAL);
9688 tng_data = *tng_data_p;
9690 frame_set = &tng_data->current_trajectory_frame_set;
9692 tng_data->input_file_path = 0;
9693 tng_data->input_file = 0;
9694 tng_data->input_file_len = 0;
9695 tng_data->output_file_path = 0;
9696 tng_data->output_file = 0;
9698 tng_data->first_program_name = 0;
9699 tng_data->first_user_name = 0;
9700 tng_data->first_computer_name = 0;
9701 tng_data->first_pgp_signature = 0;
9702 tng_data->last_program_name = 0;
9703 tng_data->last_user_name = 0;
9704 tng_data->last_computer_name = 0;
9705 tng_data->last_pgp_signature = 0;
9706 tng_data->forcefield_name = 0;
9711 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9715 tng_data->time = seconds;
9718 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
9719 tng_data->first_trajectory_frame_set_input_file_pos = -1;
9720 tng_data->last_trajectory_frame_set_input_file_pos = -1;
9721 tng_data->current_trajectory_frame_set_input_file_pos = -1;
9722 tng_data->first_trajectory_frame_set_output_file_pos = -1;
9723 tng_data->last_trajectory_frame_set_output_file_pos = -1;
9724 tng_data->current_trajectory_frame_set_output_file_pos = -1;
9725 tng_data->frame_set_n_frames = 100;
9726 tng_data->n_trajectory_frame_sets = 0;
9727 tng_data->medium_stride_length = 100;
9728 tng_data->long_stride_length = 10000;
9730 tng_data->time_per_frame = -1;
9732 tng_data->n_particle_data_blocks = 0;
9733 tng_data->n_data_blocks = 0;
9735 tng_data->non_tr_particle_data = 0;
9736 tng_data->non_tr_data = 0;
9738 tng_data->compress_algo_pos = 0;
9739 tng_data->compress_algo_vel = 0;
9740 tng_data->compression_precision = 1000;
9741 tng_data->distance_unit_exponential = -9;
9743 frame_set->first_frame = -1;
9744 frame_set->n_mapping_blocks = 0;
9745 frame_set->mappings = 0;
9746 frame_set->molecule_cnt_list = 0;
9748 frame_set->n_particle_data_blocks = 0;
9749 frame_set->n_data_blocks = 0;
9751 frame_set->tr_particle_data = 0;
9752 frame_set->tr_data = 0;
9754 frame_set->n_written_frames = 0;
9755 frame_set->n_unwritten_frames = 0;
9757 frame_set->next_frame_set_file_pos = -1;
9758 frame_set->prev_frame_set_file_pos = -1;
9759 frame_set->medium_stride_next_frame_set_file_pos = -1;
9760 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9761 frame_set->long_stride_next_frame_set_file_pos = -1;
9762 frame_set->long_stride_prev_frame_set_file_pos = -1;
9764 frame_set->first_frame_time = -1;
9766 tng_data->n_molecules = 0;
9767 tng_data->molecules = 0;
9768 tng_data->molecule_cnt_list = 0;
9769 tng_data->n_particles = 0;
9772 /* Check the endianness of the computer */
9773 static int32_t endianness_32 = 0x01234567;
9775 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9777 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9781 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9783 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9788 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
9790 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
9794 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
9795 /* 0x0123456789ABCDEF */
9796 if ( *(const unsigned char*)&endianness_64 == 0x01 )
9798 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
9801 /* 0xEFCDAB8967452301 */
9802 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
9804 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
9807 /* 0x89ABCDEF01234567 */
9808 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
9810 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
9813 /* 0x45670123CDEF89AB */
9814 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
9816 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
9819 /* 0x23016745AB89EFCD */
9820 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
9822 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
9826 /* By default do not swap the byte order, i.e. keep the byte order of the
9827 * architecture. The input file endianness will be set when reading the
9828 * header. The output endianness can be changed - before the file is
9830 tng_data->input_endianness_swap_func_32 = 0;
9831 tng_data->input_endianness_swap_func_64 = 0;
9832 tng_data->output_endianness_swap_func_32 = 0;
9833 tng_data->output_endianness_swap_func_64 = 0;
9835 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9836 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9837 tng_data->current_trajectory_frame_set.n_frames = 0;
9839 return(TNG_SUCCESS);
9842 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
9845 int64_t n_particles, n_values_per_frame;
9846 tng_trajectory_t tng_data = *tng_data_p;
9847 tng_trajectory_frame_set_t frame_set;
9851 return(TNG_SUCCESS);
9854 frame_set = &tng_data->current_trajectory_frame_set;
9856 if(tng_data->input_file_path)
9858 free(tng_data->input_file_path);
9859 tng_data->input_file_path = 0;
9862 if(tng_data->input_file)
9864 if(tng_data->output_file == tng_data->input_file)
9866 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9867 tng_data->output_file = 0;
9869 fclose(tng_data->input_file);
9870 tng_data->input_file = 0;
9873 if(tng_data->output_file_path)
9875 free(tng_data->output_file_path);
9876 tng_data->output_file_path = 0;
9879 if(tng_data->output_file)
9881 /* FIXME: Do not always write the hash */
9882 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
9883 fclose(tng_data->output_file);
9884 tng_data->output_file = 0;
9887 if(tng_data->first_program_name)
9889 free(tng_data->first_program_name);
9890 tng_data->first_program_name = 0;
9893 if(tng_data->last_program_name)
9895 free(tng_data->last_program_name);
9896 tng_data->last_program_name = 0;
9899 if(tng_data->first_user_name)
9901 free(tng_data->first_user_name);
9902 tng_data->first_user_name = 0;
9905 if(tng_data->last_user_name)
9907 free(tng_data->last_user_name);
9908 tng_data->last_user_name = 0;
9911 if(tng_data->first_computer_name)
9913 free(tng_data->first_computer_name);
9914 tng_data->first_computer_name = 0;
9917 if(tng_data->last_computer_name)
9919 free(tng_data->last_computer_name);
9920 tng_data->last_computer_name = 0;
9923 if(tng_data->first_pgp_signature)
9925 free(tng_data->first_pgp_signature);
9926 tng_data->first_pgp_signature = 0;
9929 if(tng_data->last_pgp_signature)
9931 free(tng_data->last_pgp_signature);
9932 tng_data->last_pgp_signature = 0;
9935 if(tng_data->forcefield_name)
9937 free(tng_data->forcefield_name);
9938 tng_data->forcefield_name = 0;
9941 tng_frame_set_particle_mapping_free(tng_data);
9943 if(frame_set->molecule_cnt_list)
9945 free(frame_set->molecule_cnt_list);
9946 frame_set->molecule_cnt_list = 0;
9949 if(tng_data->var_num_atoms_flag)
9951 n_particles = frame_set->n_particles;
9955 n_particles = tng_data->n_particles;
9958 if(tng_data->non_tr_particle_data)
9960 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
9962 if(tng_data->non_tr_particle_data[i].values)
9964 free(tng_data->non_tr_particle_data[i].values);
9965 tng_data->non_tr_particle_data[i].values = 0;
9968 if(tng_data->non_tr_particle_data[i].strings)
9970 n_values_per_frame = tng_data->non_tr_particle_data[i].
9972 if(tng_data->non_tr_particle_data[i].strings[0])
9974 for(j = 0; j < n_particles; j++)
9976 if(tng_data->non_tr_particle_data[i].strings[0][j])
9978 for(k = 0; k < n_values_per_frame; k++)
9980 if(tng_data->non_tr_particle_data[i].
9983 free(tng_data->non_tr_particle_data[i].
9985 tng_data->non_tr_particle_data[i].
9986 strings[0][j][k] = 0;
9989 free(tng_data->non_tr_particle_data[i].
9991 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9994 free(tng_data->non_tr_particle_data[i].strings[0]);
9995 tng_data->non_tr_particle_data[i].strings[0] = 0;
9997 free(tng_data->non_tr_particle_data[i].strings);
9998 tng_data->non_tr_particle_data[i].strings = 0;
10001 if(tng_data->non_tr_particle_data[i].block_name)
10003 free(tng_data->non_tr_particle_data[i].block_name);
10004 tng_data->non_tr_particle_data[i].block_name = 0;
10007 free(tng_data->non_tr_particle_data);
10008 tng_data->non_tr_particle_data = 0;
10011 if(tng_data->non_tr_data)
10013 for(i = 0; i < tng_data->n_data_blocks; i++)
10015 if(tng_data->non_tr_data[i].values)
10017 free(tng_data->non_tr_data[i].values);
10018 tng_data->non_tr_data[i].values = 0;
10021 if(tng_data->non_tr_data[i].strings)
10023 n_values_per_frame = tng_data->non_tr_data[i].
10024 n_values_per_frame;
10025 if(tng_data->non_tr_data[i].strings[0])
10027 for(j = 0; j < n_values_per_frame; j++)
10029 if(tng_data->non_tr_data[i].strings[0][j])
10031 free(tng_data->non_tr_data[i].strings[0][j]);
10032 tng_data->non_tr_data[i].strings[0][j] = 0;
10035 free(tng_data->non_tr_data[i].strings[0]);
10036 tng_data->non_tr_data[i].strings[0] = 0;
10038 free(tng_data->non_tr_data[i].strings);
10039 tng_data->non_tr_data[i].strings = 0;
10042 if(tng_data->non_tr_data[i].block_name)
10044 free(tng_data->non_tr_data[i].block_name);
10045 tng_data->non_tr_data[i].block_name = 0;
10048 free(tng_data->non_tr_data);
10049 tng_data->non_tr_data = 0;
10052 tng_data->n_particle_data_blocks = 0;
10053 tng_data->n_data_blocks = 0;
10055 if(tng_data->compress_algo_pos)
10057 free(tng_data->compress_algo_pos);
10058 tng_data->compress_algo_pos = 0;
10060 if(tng_data->compress_algo_vel)
10062 free(tng_data->compress_algo_vel);
10063 tng_data->compress_algo_vel = 0;
10066 if(frame_set->tr_particle_data)
10068 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
10070 if(frame_set->tr_particle_data[i].values)
10072 free(frame_set->tr_particle_data[i].values);
10073 frame_set->tr_particle_data[i].values = 0;
10076 if(frame_set->tr_particle_data[i].strings)
10078 n_values_per_frame = frame_set->tr_particle_data[i].
10079 n_values_per_frame;
10080 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
10082 if(frame_set->tr_particle_data[i].strings[j])
10084 for(k = 0; k < n_particles; k++)
10086 if(frame_set->tr_particle_data[i].
10089 for(l = 0; l < n_values_per_frame; l++)
10091 if(frame_set->tr_particle_data[i].
10094 free(frame_set->tr_particle_data[i].
10096 frame_set->tr_particle_data[i].
10097 strings[j][k][l] = 0;
10100 free(frame_set->tr_particle_data[i].
10102 frame_set->tr_particle_data[i].
10106 free(frame_set->tr_particle_data[i].strings[j]);
10107 frame_set->tr_particle_data[i].strings[j] = 0;
10110 free(frame_set->tr_particle_data[i].strings);
10111 frame_set->tr_particle_data[i].strings = 0;
10114 if(frame_set->tr_particle_data[i].block_name)
10116 free(frame_set->tr_particle_data[i].block_name);
10117 frame_set->tr_particle_data[i].block_name = 0;
10120 free(frame_set->tr_particle_data);
10121 frame_set->tr_particle_data = 0;
10124 if(frame_set->tr_data)
10126 for(i = 0; i < frame_set->n_data_blocks; i++)
10128 if(frame_set->tr_data[i].values)
10130 free(frame_set->tr_data[i].values);
10131 frame_set->tr_data[i].values = 0;
10134 if(frame_set->tr_data[i].strings)
10136 n_values_per_frame = frame_set->tr_data[i].
10137 n_values_per_frame;
10138 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
10140 if(frame_set->tr_data[i].strings[j])
10142 for(k = 0; k < n_values_per_frame; k++)
10144 if(frame_set->tr_data[i].strings[j][k])
10146 free(frame_set->tr_data[i].strings[j][k]);
10147 frame_set->tr_data[i].strings[j][k] = 0;
10150 free(frame_set->tr_data[i].strings[j]);
10151 frame_set->tr_data[i].strings[j] = 0;
10154 free(frame_set->tr_data[i].strings);
10155 frame_set->tr_data[i].strings = 0;
10158 if(frame_set->tr_data[i].block_name)
10160 free(frame_set->tr_data[i].block_name);
10161 frame_set->tr_data[i].block_name = 0;
10164 free(frame_set->tr_data);
10165 frame_set->tr_data = 0;
10168 frame_set->n_particle_data_blocks = 0;
10169 frame_set->n_data_blocks = 0;
10171 if(tng_data->molecules)
10173 for(i = 0; i < tng_data->n_molecules; i++)
10175 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
10177 free(tng_data->molecules);
10178 tng_data->molecules = 0;
10179 tng_data->n_molecules = 0;
10181 if(tng_data->molecule_cnt_list)
10183 free(tng_data->molecule_cnt_list);
10184 tng_data->molecule_cnt_list = 0;
10190 return(TNG_SUCCESS);
10193 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
10194 tng_trajectory_t *dest_p)
10196 tng_trajectory_frame_set_t frame_set;
10197 tng_trajectory_t dest;
10199 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
10201 *dest_p = malloc(sizeof(struct tng_trajectory));
10204 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10205 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10206 return(TNG_CRITICAL);
10211 frame_set = &dest->current_trajectory_frame_set;
10213 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
10214 if(!dest->input_file_path)
10216 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10217 (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
10218 return(TNG_CRITICAL);
10220 strcpy(dest->input_file_path, src->input_file_path);
10221 dest->input_file = 0;
10222 dest->input_file_len = src->input_file_len;
10223 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
10224 if(!dest->output_file_path)
10226 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10227 (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
10228 return(TNG_CRITICAL);
10230 strcpy(dest->output_file_path, src->output_file_path);
10231 dest->output_file = 0;
10233 dest->first_program_name = 0;
10234 dest->first_user_name = 0;
10235 dest->first_computer_name = 0;
10236 dest->first_pgp_signature = 0;
10237 dest->last_program_name = 0;
10238 dest->last_user_name = 0;
10239 dest->last_computer_name = 0;
10240 dest->last_pgp_signature = 0;
10241 dest->forcefield_name = 0;
10243 dest->var_num_atoms_flag = src->var_num_atoms_flag;
10244 dest->first_trajectory_frame_set_input_file_pos =
10245 src->first_trajectory_frame_set_input_file_pos;
10246 dest->last_trajectory_frame_set_input_file_pos =
10247 src->last_trajectory_frame_set_input_file_pos;
10248 dest->current_trajectory_frame_set_input_file_pos =
10249 src->current_trajectory_frame_set_input_file_pos;
10250 dest->first_trajectory_frame_set_output_file_pos =
10251 src->first_trajectory_frame_set_output_file_pos;
10252 dest->last_trajectory_frame_set_output_file_pos =
10253 src->last_trajectory_frame_set_output_file_pos;
10254 dest->current_trajectory_frame_set_output_file_pos =
10255 src->current_trajectory_frame_set_output_file_pos;
10256 dest->frame_set_n_frames = src->frame_set_n_frames;
10257 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
10258 dest->medium_stride_length = src->medium_stride_length;
10259 dest->long_stride_length = src->long_stride_length;
10261 dest->time_per_frame = src->time_per_frame;
10263 /* Currently the non trajectory data blocks are not copied since it
10264 * can lead to problems when freeing memory in a parallel block. */
10265 dest->n_particle_data_blocks = 0;
10266 dest->n_data_blocks = 0;
10267 dest->non_tr_particle_data = 0;
10268 dest->non_tr_data = 0;
10270 dest->compress_algo_pos = 0;
10271 dest->compress_algo_vel = 0;
10272 dest->distance_unit_exponential = -9;
10273 dest->compression_precision = 1000;
10275 frame_set->n_mapping_blocks = 0;
10276 frame_set->mappings = 0;
10277 frame_set->molecule_cnt_list = 0;
10279 frame_set->n_particle_data_blocks = 0;
10280 frame_set->n_data_blocks = 0;
10282 frame_set->tr_particle_data = 0;
10283 frame_set->tr_data = 0;
10285 frame_set->next_frame_set_file_pos = -1;
10286 frame_set->prev_frame_set_file_pos = -1;
10287 frame_set->medium_stride_next_frame_set_file_pos = -1;
10288 frame_set->medium_stride_prev_frame_set_file_pos = -1;
10289 frame_set->long_stride_next_frame_set_file_pos = -1;
10290 frame_set->long_stride_prev_frame_set_file_pos = -1;
10291 frame_set->first_frame = -1;
10293 dest->n_molecules = 0;
10294 dest->molecules = 0;
10295 dest->molecule_cnt_list = 0;
10296 dest->n_particles = src->n_particles;
10298 dest->endianness_32 = src->endianness_32;
10299 dest->endianness_64 = src->endianness_64;
10300 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
10301 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
10302 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
10303 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
10305 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
10306 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
10307 dest->current_trajectory_frame_set.n_frames = 0;
10309 return(TNG_SUCCESS);
10312 tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
10313 char *file_name, const int max_len)
10315 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10316 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10318 strncpy(file_name, tng_data->input_file_path, max_len - 1);
10319 file_name[max_len - 1] = 0;
10321 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
10323 return(TNG_FAILURE);
10325 return(TNG_SUCCESS);
10328 tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
10329 const char *file_name)
10334 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10335 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10338 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
10341 return(TNG_SUCCESS);
10344 if(tng_data->input_file)
10346 fclose(tng_data->input_file);
10349 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10350 temp = realloc(tng_data->input_file_path, len);
10353 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10354 __FILE__, __LINE__);
10355 free(tng_data->input_file_path);
10356 tng_data->input_file_path = 0;
10357 return(TNG_CRITICAL);
10359 tng_data->input_file_path = temp;
10361 strncpy(tng_data->input_file_path, file_name, len);
10363 return(tng_input_file_init(tng_data));
10366 tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
10367 char *file_name, const int max_len)
10369 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10370 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10372 strncpy(file_name, tng_data->output_file_path, max_len - 1);
10373 file_name[max_len - 1] = 0;
10375 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
10377 return(TNG_FAILURE);
10379 return(TNG_SUCCESS);
10382 tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
10383 const char *file_name)
10388 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10389 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10391 if(tng_data->output_file_path &&
10392 strcmp(tng_data->output_file_path, file_name) == 0)
10394 return(TNG_SUCCESS);
10397 if(tng_data->output_file)
10399 fclose(tng_data->output_file);
10402 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10403 temp = realloc(tng_data->output_file_path, len);
10406 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10407 __FILE__, __LINE__);
10408 free(tng_data->output_file_path);
10409 tng_data->output_file_path = 0;
10410 return(TNG_CRITICAL);
10412 tng_data->output_file_path = temp;
10414 strncpy(tng_data->output_file_path, file_name, len);
10416 return(tng_output_file_init(tng_data));
10419 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10420 (tng_trajectory_t tng_data,
10421 const char *file_name)
10426 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10427 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
10429 if(tng_data->output_file_path &&
10430 strcmp(tng_data->output_file_path, file_name) == 0)
10432 return(TNG_SUCCESS);
10435 if(tng_data->output_file)
10437 fclose(tng_data->output_file);
10440 len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
10441 temp = realloc(tng_data->output_file_path, len);
10444 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
10445 __FILE__, __LINE__);
10446 free(tng_data->output_file_path);
10447 tng_data->output_file_path = 0;
10448 return(TNG_CRITICAL);
10450 tng_data->output_file_path = temp;
10452 strncpy(tng_data->output_file_path, file_name, len);
10454 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
10455 if(!tng_data->output_file)
10457 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
10458 tng_data->output_file_path, __FILE__, __LINE__);
10459 return(TNG_CRITICAL);
10461 tng_data->input_file = tng_data->output_file;
10463 return(TNG_SUCCESS);
10466 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10467 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
10469 tng_endianness_32 end_32;
10470 tng_endianness_64 end_64;
10472 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10473 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
10475 if(tng_data->output_endianness_swap_func_32)
10477 /* If other endianness variants are added they must be added here as well */
10478 if(tng_data->output_endianness_swap_func_32 ==
10479 &tng_swap_byte_order_big_endian_32)
10481 end_32 = TNG_BIG_ENDIAN_32;
10483 else if(tng_data->output_endianness_swap_func_32 ==
10484 &tng_swap_byte_order_little_endian_32)
10486 end_32 = TNG_LITTLE_ENDIAN_32;
10490 return(TNG_FAILURE);
10495 end_32 = (tng_endianness_32)tng_data->endianness_32;
10498 if(tng_data->output_endianness_swap_func_64)
10500 /* If other endianness variants are added they must be added here as well */
10501 if(tng_data->output_endianness_swap_func_64 ==
10502 &tng_swap_byte_order_big_endian_64)
10504 end_64 = TNG_BIG_ENDIAN_64;
10506 else if(tng_data->output_endianness_swap_func_64 ==
10507 &tng_swap_byte_order_little_endian_64)
10509 end_64 = TNG_LITTLE_ENDIAN_64;
10513 return(TNG_FAILURE);
10518 end_64 = (tng_endianness_64)tng_data->endianness_64;
10521 if((int)end_32 != (int)end_64)
10523 return(TNG_FAILURE);
10526 if(end_32 == TNG_LITTLE_ENDIAN_32)
10528 *endianness = TNG_LITTLE_ENDIAN;
10531 else if(end_32 == TNG_BIG_ENDIAN_32)
10533 *endianness = TNG_BIG_ENDIAN;
10537 return(TNG_FAILURE);
10540 return(TNG_SUCCESS);
10543 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10544 (tng_trajectory_t tng_data,
10545 const tng_file_endianness endianness)
10547 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10549 /* Tne endianness cannot be changed if the data has already been written
10550 * to the output file. */
10551 if(ftell(tng_data->output_file) > 0)
10553 return(TNG_FAILURE);
10556 if(endianness == TNG_BIG_ENDIAN)
10558 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
10560 tng_data->output_endianness_swap_func_32 = 0;
10564 tng_data->output_endianness_swap_func_32 =
10565 &tng_swap_byte_order_big_endian_32;
10567 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
10569 tng_data->output_endianness_swap_func_64 = 0;
10573 tng_data->output_endianness_swap_func_64 =
10574 &tng_swap_byte_order_big_endian_64;
10576 return(TNG_SUCCESS);
10578 else if(endianness == TNG_LITTLE_ENDIAN)
10580 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
10582 tng_data->output_endianness_swap_func_32 = 0;
10586 tng_data->output_endianness_swap_func_32 =
10587 &tng_swap_byte_order_little_endian_32;
10589 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
10591 tng_data->output_endianness_swap_func_64 = 0;
10595 tng_data->output_endianness_swap_func_64 =
10596 &tng_swap_byte_order_little_endian_64;
10598 return(TNG_SUCCESS);
10601 /* If the specified endianness is neither big nor little endian return a
10603 return(TNG_FAILURE);
10606 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10607 (const tng_trajectory_t tng_data,
10608 char *name, const int max_len)
10610 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10611 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10613 strncpy(name, tng_data->first_program_name, max_len - 1);
10614 name[max_len - 1] = 0;
10616 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
10618 return(TNG_FAILURE);
10620 return(TNG_SUCCESS);
10623 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
10624 const char *new_name)
10628 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10629 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10631 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10633 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
10635 free(tng_data->first_program_name);
10636 tng_data->first_program_name = 0;
10638 if(!tng_data->first_program_name)
10640 tng_data->first_program_name = malloc(len);
10641 if(!tng_data->first_program_name)
10643 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10644 __FILE__, __LINE__);
10645 return(TNG_CRITICAL);
10649 strncpy(tng_data->first_program_name, new_name, len);
10651 return(TNG_SUCCESS);
10654 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10655 (const tng_trajectory_t tng_data,
10656 char *name, const int max_len)
10658 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10659 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10661 strncpy(name, tng_data->last_program_name, max_len - 1);
10662 name[max_len - 1] = 0;
10664 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
10666 return(TNG_FAILURE);
10668 return(TNG_SUCCESS);
10671 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10672 (tng_trajectory_t tng_data,
10673 const char *new_name)
10677 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10678 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10680 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10682 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
10684 free(tng_data->last_program_name);
10685 tng_data->last_program_name = 0;
10687 if(!tng_data->last_program_name)
10689 tng_data->last_program_name = malloc(len);
10690 if(!tng_data->last_program_name)
10692 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10693 __FILE__, __LINE__);
10694 return(TNG_CRITICAL);
10698 strncpy(tng_data->last_program_name, new_name, len);
10700 return(TNG_SUCCESS);
10703 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10704 (const tng_trajectory_t tng_data,
10705 char *name, const int max_len)
10707 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10708 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10710 strncpy(name, tng_data->first_user_name, max_len - 1);
10711 name[max_len - 1] = 0;
10713 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
10715 return(TNG_FAILURE);
10717 return(TNG_SUCCESS);
10720 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10721 (tng_trajectory_t tng_data,
10722 const char *new_name)
10726 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10727 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10729 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10731 /* If the currently stored string length is not enough to store the new
10732 * string it is freed and reallocated. */
10733 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
10735 free(tng_data->first_user_name);
10736 tng_data->first_user_name = 0;
10738 if(!tng_data->first_user_name)
10740 tng_data->first_user_name = malloc(len);
10741 if(!tng_data->first_user_name)
10743 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10744 __FILE__, __LINE__);
10745 return(TNG_CRITICAL);
10749 strncpy(tng_data->first_user_name, new_name, len);
10751 return(TNG_SUCCESS);
10754 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10755 (const tng_trajectory_t tng_data,
10756 char *name, const int max_len)
10758 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10759 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10761 strncpy(name, tng_data->last_user_name, max_len - 1);
10762 name[max_len - 1] = 0;
10764 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
10766 return(TNG_FAILURE);
10768 return(TNG_SUCCESS);
10771 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10772 (tng_trajectory_t tng_data,
10773 const char *new_name)
10777 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10778 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10780 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10782 /* If the currently stored string length is not enough to store the new
10783 * string it is freed and reallocated. */
10784 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
10786 free(tng_data->last_user_name);
10787 tng_data->last_user_name = 0;
10789 if(!tng_data->last_user_name)
10791 tng_data->last_user_name = malloc(len);
10792 if(!tng_data->last_user_name)
10794 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10795 __FILE__, __LINE__);
10796 return(TNG_CRITICAL);
10800 strncpy(tng_data->last_user_name, new_name, len);
10802 return(TNG_SUCCESS);
10805 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10806 (const tng_trajectory_t tng_data,
10807 char *name, const int max_len)
10809 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10810 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10812 strncpy(name, tng_data->first_computer_name, max_len - 1);
10813 name[max_len - 1] = 0;
10815 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
10817 return(TNG_FAILURE);
10819 return(TNG_SUCCESS);
10822 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10823 (tng_trajectory_t tng_data,
10824 const char *new_name)
10828 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10829 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10831 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10833 /* If the currently stored string length is not enough to store the new
10834 * string it is freed and reallocated. */
10835 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
10837 free(tng_data->first_computer_name);
10838 tng_data->first_computer_name = 0;
10840 if(!tng_data->first_computer_name)
10842 tng_data->first_computer_name = malloc(len);
10843 if(!tng_data->first_computer_name)
10845 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10846 __FILE__, __LINE__);
10847 return(TNG_CRITICAL);
10851 strncpy(tng_data->first_computer_name, new_name, len);
10853 return(TNG_SUCCESS);
10856 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10857 (const tng_trajectory_t tng_data,
10858 char *name, const int max_len)
10860 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10861 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10863 strncpy(name, tng_data->last_computer_name, max_len - 1);
10864 name[max_len - 1] = 0;
10866 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
10868 return(TNG_FAILURE);
10870 return(TNG_SUCCESS);
10873 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10874 (tng_trajectory_t tng_data,
10875 const char *new_name)
10879 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10880 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10882 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
10884 /* If the currently stored string length is not enough to store the new
10885 * string it is freed and reallocated. */
10886 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
10889 free(tng_data->last_computer_name);
10890 tng_data->last_computer_name = 0;
10892 if(!tng_data->last_computer_name)
10894 tng_data->last_computer_name = malloc(len);
10895 if(!tng_data->last_computer_name)
10897 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10898 __FILE__, __LINE__);
10899 return(TNG_CRITICAL);
10903 strncpy(tng_data->last_computer_name, new_name, len);
10905 return(TNG_SUCCESS);
10908 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10909 (const tng_trajectory_t tng_data,
10910 char *signature, const int max_len)
10912 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10913 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10915 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
10916 signature[max_len - 1] = 0;
10918 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10920 return(TNG_FAILURE);
10922 return(TNG_SUCCESS);
10925 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10926 (tng_trajectory_t tng_data,
10927 const char *signature)
10931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10932 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10934 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10936 /* If the currently stored string length is not enough to store the new
10937 * string it is freed and reallocated. */
10938 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10941 free(tng_data->first_pgp_signature);
10942 tng_data->first_pgp_signature = 0;
10944 if(!tng_data->first_pgp_signature)
10946 tng_data->first_pgp_signature = malloc(len);
10947 if(!tng_data->first_pgp_signature)
10949 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10950 __FILE__, __LINE__);
10951 return(TNG_CRITICAL);
10955 strncpy(tng_data->first_pgp_signature, signature, len);
10957 return(TNG_SUCCESS);
10960 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10961 (const tng_trajectory_t tng_data,
10962 char *signature, const int max_len)
10964 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10965 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10967 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10968 signature[max_len - 1] = 0;
10970 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10972 return(TNG_FAILURE);
10974 return(TNG_SUCCESS);
10977 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10978 (tng_trajectory_t tng_data,
10979 const char *signature)
10983 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10984 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10986 len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
10988 /* If the currently stored string length is not enough to store the new
10989 * string it is freed and reallocated. */
10990 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10993 free(tng_data->last_pgp_signature);
10994 tng_data->last_pgp_signature = 0;
10996 if(!tng_data->last_pgp_signature)
10998 tng_data->last_pgp_signature = malloc(len);
10999 if(!tng_data->last_pgp_signature)
11001 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11002 __FILE__, __LINE__);
11003 return(TNG_CRITICAL);
11007 strncpy(tng_data->last_pgp_signature, signature, len);
11009 return(TNG_SUCCESS);
11012 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11013 (const tng_trajectory_t tng_data,
11014 char *name, const int max_len)
11016 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11017 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
11019 strncpy(name, tng_data->forcefield_name, max_len - 1);
11020 name[max_len - 1] = 0;
11022 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
11024 return(TNG_FAILURE);
11026 return(TNG_SUCCESS);
11029 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11030 (tng_trajectory_t tng_data,
11031 const char *new_name)
11035 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11036 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
11038 len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
11040 /* If the currently stored string length is not enough to store the new
11041 * string it is freed and reallocated. */
11042 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
11044 free(tng_data->forcefield_name);
11045 tng_data->forcefield_name = 0;
11047 if(!tng_data->forcefield_name)
11049 tng_data->forcefield_name = malloc(len);
11050 if(!tng_data->forcefield_name)
11052 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
11053 __FILE__, __LINE__);
11054 return(TNG_CRITICAL);
11058 strncpy(tng_data->forcefield_name, new_name, len);
11060 return(TNG_SUCCESS);
11063 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11064 (const tng_trajectory_t tng_data,
11067 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11068 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11070 *len = tng_data->medium_stride_length;
11072 return(TNG_SUCCESS);
11075 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11076 (tng_trajectory_t tng_data,
11079 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11081 if(len >= tng_data->long_stride_length)
11083 return(TNG_FAILURE);
11085 tng_data->medium_stride_length = len;
11087 return(TNG_SUCCESS);
11090 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11091 (const tng_trajectory_t tng_data,
11094 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11095 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11097 *len = tng_data->long_stride_length;
11099 return(TNG_SUCCESS);
11102 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11103 (tng_trajectory_t tng_data,
11106 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11108 if(len <= tng_data->medium_stride_length)
11110 return(TNG_FAILURE);
11112 tng_data->long_stride_length = len;
11114 return(TNG_SUCCESS);
11117 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11118 (const tng_trajectory_t tng_data,
11121 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11122 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
11124 *time = tng_data->time_per_frame;
11126 return(TNG_SUCCESS);
11129 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11130 (tng_trajectory_t tng_data,
11133 tng_trajectory_frame_set_t frame_set;
11135 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11136 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
11138 if(fabs(time - tng_data->time_per_frame) < 0.00001)
11140 return(TNG_SUCCESS);
11143 frame_set = &tng_data->current_trajectory_frame_set;
11145 /* If the current frame set is not finished write it to disk before
11146 changing time per frame. */
11147 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
11149 frame_set->n_frames = frame_set->n_unwritten_frames;
11150 tng_frame_set_write(tng_data, TNG_USE_HASH);
11152 tng_data->time_per_frame = time;
11154 return(TNG_SUCCESS);
11157 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11158 (const tng_trajectory_t tng_data,
11161 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11162 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
11164 *len = tng_data->input_file_len;
11166 return(TNG_SUCCESS);
11169 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11170 (const tng_trajectory_t tng_data,
11173 tng_gen_block_t block;
11174 tng_function_status stat;
11176 int64_t last_file_pos, first_frame, n_frames;
11178 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11179 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
11180 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11182 file_pos = ftell(tng_data->input_file);
11183 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11185 if(last_file_pos <= 0)
11187 return(TNG_FAILURE);
11190 tng_block_init(&block);
11191 fseek(tng_data->input_file,
11192 (long)last_file_pos,
11194 /* Read block headers first to see that a frame set block is found. */
11195 stat = tng_block_header_read(tng_data, block);
11196 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11198 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
11199 __FILE__, __LINE__);
11200 tng_block_destroy(&block);
11201 return(TNG_FAILURE);
11203 tng_block_destroy(&block);
11205 if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
11207 fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11208 __FILE__, __LINE__);
11209 return(TNG_CRITICAL);
11211 if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
11213 fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11214 __FILE__, __LINE__);
11215 return(TNG_CRITICAL);
11217 fseek(tng_data->input_file, file_pos, SEEK_SET);
11219 *n = first_frame + n_frames;
11221 return(TNG_SUCCESS);
11224 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11225 (const tng_trajectory_t tng_data,
11228 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11230 *precision = tng_data->compression_precision;
11232 return(TNG_SUCCESS);
11235 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11236 (tng_trajectory_t tng_data,
11237 const double precision)
11239 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11241 tng_data->compression_precision = precision;
11243 return(TNG_SUCCESS);
11246 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11247 (tng_trajectory_t tng_data,
11250 tng_molecule_t mol;
11254 tng_function_status stat;
11255 int64_t diff, n_mod, n_impl;
11257 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
11259 diff = n - tng_data->n_particles;
11261 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
11262 if(stat == TNG_SUCCESS)
11264 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
11266 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11267 __FILE__, __LINE__);
11268 return(TNG_FAILURE);
11270 diff -= n_impl * mol->n_atoms;
11275 if(stat == TNG_SUCCESS)
11277 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11280 return(TNG_SUCCESS);
11284 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
11285 fprintf(stderr, "particle count.\n");
11286 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11287 __FILE__, __LINE__);
11288 /* FIXME: Should we set the count of all other molecules to 0 and add
11289 * implicit molecules? */
11290 return(TNG_FAILURE);
11292 if(stat != TNG_SUCCESS)
11294 stat = tng_molecule_add(tng_data,
11295 "TNG_IMPLICIT_MOL",
11297 if(stat != TNG_SUCCESS)
11301 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11302 if(stat != TNG_SUCCESS)
11306 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11307 if(stat != TNG_SUCCESS)
11311 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11312 if(stat != TNG_SUCCESS)
11319 if(mol->n_atoms > 1)
11321 n_mod = diff % mol->n_atoms;
11324 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
11325 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
11326 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
11327 __FILE__, __LINE__);
11328 return(TNG_FAILURE);
11330 diff /= mol->n_atoms;
11333 stat = tng_molecule_cnt_set(tng_data, mol, diff);
11338 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11339 (const tng_trajectory_t tng_data,
11342 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11343 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11345 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
11347 *n = tng_data->n_particles;
11351 *n = tng_data->current_trajectory_frame_set.n_particles;
11354 return(TNG_SUCCESS);
11357 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11358 (const tng_trajectory_t tng_data,
11361 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11362 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
11364 *variable = tng_data->var_num_atoms_flag;
11366 return(TNG_SUCCESS);
11369 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11370 (const tng_trajectory_t tng_data,
11373 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11374 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11376 *n = tng_data->n_molecules;
11378 return(TNG_SUCCESS);
11381 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11382 (const tng_trajectory_t tng_data,
11385 int64_t *cnt_list = 0, cnt = 0, i;
11387 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11388 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11390 tng_molecule_cnt_list_get(tng_data, &cnt_list);
11394 return(TNG_FAILURE);
11397 for(i = 0; i < tng_data->n_molecules; i++)
11399 cnt += cnt_list[i];
11404 return(TNG_SUCCESS);
11407 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11408 (const tng_trajectory_t tng_data,
11409 int64_t **mol_cnt_list)
11411 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11413 if(tng_data->var_num_atoms_flag)
11415 *mol_cnt_list = tng_data->current_trajectory_frame_set.
11420 *mol_cnt_list = tng_data->molecule_cnt_list;
11422 if(*mol_cnt_list == 0)
11424 return(TNG_FAILURE);
11426 return(TNG_SUCCESS);
11429 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11430 (const tng_trajectory_t tng_data,
11433 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11434 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
11436 *exp = tng_data->distance_unit_exponential;
11438 return(TNG_SUCCESS);
11441 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11442 (const tng_trajectory_t tng_data,
11445 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11447 tng_data->distance_unit_exponential = exp;
11449 return(TNG_SUCCESS);
11452 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11453 (const tng_trajectory_t tng_data,
11456 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11457 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11459 *n = tng_data->frame_set_n_frames;
11461 return(TNG_SUCCESS);
11464 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11465 (const tng_trajectory_t tng_data,
11468 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11470 tng_data->frame_set_n_frames = n;
11472 return(TNG_SUCCESS);
11475 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11476 (const tng_trajectory_t tng_data,
11479 int64_t long_stride_length, medium_stride_length;
11480 long file_pos, orig_frame_set_file_pos;
11481 tng_trajectory_frame_set_t frame_set;
11482 struct tng_trajectory_frame_set orig_frame_set;
11483 tng_gen_block_t block;
11484 tng_function_status stat;
11487 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11488 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
11490 orig_frame_set = tng_data->current_trajectory_frame_set;
11492 frame_set = &tng_data->current_trajectory_frame_set;
11494 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11495 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
11497 tng_block_init(&block);
11498 fseek(tng_data->input_file,
11501 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11502 /* Read block headers first to see what block is found. */
11503 stat = tng_block_header_read(tng_data, block);
11504 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11506 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n", file_pos,
11507 __FILE__, __LINE__);
11508 tng_block_destroy(&block);
11509 return(TNG_CRITICAL);
11512 if(tng_block_read_next(tng_data, block,
11513 TNG_SKIP_HASH) != TNG_SUCCESS)
11515 tng_block_destroy(&block);
11516 return(TNG_CRITICAL);
11521 long_stride_length = tng_data->long_stride_length;
11522 medium_stride_length = tng_data->medium_stride_length;
11524 /* Take long steps forward until a long step forward would be too long or
11525 * the last frame set is found */
11526 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
11527 while(file_pos > 0)
11531 cnt += long_stride_length;
11532 fseek(tng_data->input_file, file_pos, SEEK_SET);
11533 /* Read block headers first to see what block is found. */
11534 stat = tng_block_header_read(tng_data, block);
11535 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11537 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11538 file_pos, __FILE__, __LINE__);
11539 tng_block_destroy(&block);
11540 return(TNG_CRITICAL);
11543 if(tng_block_read_next(tng_data, block,
11544 TNG_SKIP_HASH) != TNG_SUCCESS)
11546 tng_block_destroy(&block);
11547 return(TNG_CRITICAL);
11550 file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
11553 /* Take medium steps forward until a medium step forward would be too long
11554 * or the last frame set is found */
11555 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11556 while(file_pos > 0)
11560 cnt += medium_stride_length;
11561 fseek(tng_data->input_file,
11564 /* Read block headers first to see what block is found. */
11565 stat = tng_block_header_read(tng_data, block);
11566 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11568 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11569 file_pos, __FILE__, __LINE__);
11570 tng_block_destroy(&block);
11571 return(TNG_CRITICAL);
11574 if(tng_block_read_next(tng_data, block,
11575 TNG_SKIP_HASH) != TNG_SUCCESS)
11577 tng_block_destroy(&block);
11578 return(TNG_CRITICAL);
11581 file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
11584 /* Take one step forward until the last frame set is found */
11585 file_pos = (long)frame_set->next_frame_set_file_pos;
11586 while(file_pos > 0)
11591 fseek(tng_data->input_file,
11594 /* Read block headers first to see what block is found. */
11595 stat = tng_block_header_read(tng_data, block);
11596 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11598 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11599 file_pos, __FILE__, __LINE__);
11600 tng_block_destroy(&block);
11601 return(TNG_CRITICAL);
11604 if(tng_block_read_next(tng_data, block,
11605 TNG_SKIP_HASH) != TNG_SUCCESS)
11607 tng_block_destroy(&block);
11608 return(TNG_CRITICAL);
11611 file_pos = (long)frame_set->next_frame_set_file_pos;
11614 tng_block_destroy(&block);
11616 *n = tng_data->n_trajectory_frame_sets = cnt;
11618 *frame_set = orig_frame_set;
11620 fseek(tng_data->input_file,
11621 (long)tng_data->first_trajectory_frame_set_input_file_pos,
11624 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
11626 return(TNG_SUCCESS);
11629 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11630 (const tng_trajectory_t tng_data,
11631 tng_trajectory_frame_set_t *frame_set_p)
11633 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11635 *frame_set_p = &tng_data->current_trajectory_frame_set;
11637 return(TNG_SUCCESS);
11640 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11641 (tng_trajectory_t tng_data,
11644 int64_t long_stride_length, medium_stride_length;
11645 int64_t file_pos, curr_nr = 0, n_frame_sets;
11646 tng_trajectory_frame_set_t frame_set;
11647 tng_gen_block_t block;
11648 tng_function_status stat;
11650 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11651 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
11653 frame_set = &tng_data->current_trajectory_frame_set;
11655 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
11657 if(stat != TNG_SUCCESS)
11662 if(nr >= n_frame_sets)
11664 return(TNG_FAILURE);
11667 long_stride_length = tng_data->long_stride_length;
11668 medium_stride_length = tng_data->medium_stride_length;
11670 /* FIXME: The frame set number of the current frame set is not stored */
11672 if(nr < n_frame_sets - 1 - nr)
11674 /* Start from the beginning */
11675 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11679 /* Start from the end */
11680 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11681 curr_nr = n_frame_sets - 1;
11685 return(TNG_FAILURE);
11688 tng_block_init(&block);
11689 fseek(tng_data->input_file,
11692 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11693 /* Read block headers first to see what block is found. */
11694 stat = tng_block_header_read(tng_data, block);
11695 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11697 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
11698 __FILE__, __LINE__);
11699 tng_block_destroy(&block);
11700 return(TNG_CRITICAL);
11703 if(tng_block_read_next(tng_data, block,
11704 TNG_SKIP_HASH) != TNG_SUCCESS)
11706 tng_block_destroy(&block);
11707 return(TNG_CRITICAL);
11712 tng_block_destroy(&block);
11713 return(TNG_SUCCESS);
11716 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11718 /* Take long steps forward until a long step forward would be too long or
11719 * the right frame set is found */
11720 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
11722 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11725 curr_nr += long_stride_length;
11726 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
11727 /* Read block headers first to see what block is found. */
11728 stat = tng_block_header_read(tng_data, block);
11729 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11731 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11732 file_pos, __FILE__, __LINE__);
11733 tng_block_destroy(&block);
11734 return(TNG_CRITICAL);
11737 if(tng_block_read_next(tng_data, block,
11738 TNG_SKIP_HASH) != TNG_SUCCESS)
11740 tng_block_destroy(&block);
11741 return(TNG_CRITICAL);
11745 tng_block_destroy(&block);
11746 return(TNG_SUCCESS);
11751 /* Take medium steps forward until a medium step forward would be too long
11752 * or the right frame set is found */
11753 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
11755 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11758 curr_nr += medium_stride_length;
11759 fseek(tng_data->input_file,
11762 /* Read block headers first to see what block is found. */
11763 stat = tng_block_header_read(tng_data, block);
11764 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11766 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11767 file_pos, __FILE__, __LINE__);
11768 tng_block_destroy(&block);
11769 return(TNG_CRITICAL);
11772 if(tng_block_read_next(tng_data, block,
11773 TNG_SKIP_HASH) != TNG_SUCCESS)
11775 tng_block_destroy(&block);
11776 return(TNG_CRITICAL);
11780 tng_block_destroy(&block);
11781 return(TNG_SUCCESS);
11786 /* Take one step forward until the right frame set is found */
11787 while(file_pos > 0 && curr_nr < nr)
11789 file_pos = frame_set->next_frame_set_file_pos;
11794 fseek(tng_data->input_file,
11797 /* Read block headers first to see what block is found. */
11798 stat = tng_block_header_read(tng_data, block);
11799 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11801 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11802 file_pos, __FILE__, __LINE__);
11803 tng_block_destroy(&block);
11804 return(TNG_CRITICAL);
11807 if(tng_block_read_next(tng_data, block,
11808 TNG_SKIP_HASH) != TNG_SUCCESS)
11810 tng_block_destroy(&block);
11811 return(TNG_CRITICAL);
11815 tng_block_destroy(&block);
11816 return(TNG_SUCCESS);
11821 /* Take long steps backward until a long step backward would be too long
11822 * or the right frame set is found */
11823 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
11825 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11828 curr_nr -= long_stride_length;
11829 fseek(tng_data->input_file,
11832 /* Read block headers first to see what block is found. */
11833 stat = tng_block_header_read(tng_data, block);
11834 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11836 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11837 file_pos, __FILE__, __LINE__);
11838 tng_block_destroy(&block);
11839 return(TNG_CRITICAL);
11842 if(tng_block_read_next(tng_data, block,
11843 TNG_SKIP_HASH) != TNG_SUCCESS)
11845 tng_block_destroy(&block);
11846 return(TNG_CRITICAL);
11850 tng_block_destroy(&block);
11851 return(TNG_SUCCESS);
11856 /* Take medium steps backward until a medium step backward would be too long
11857 * or the right frame set is found */
11858 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
11860 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11863 curr_nr -= medium_stride_length;
11864 fseek(tng_data->input_file,
11867 /* Read block headers first to see what block is found. */
11868 stat = tng_block_header_read(tng_data, block);
11869 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11871 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11872 file_pos, __FILE__, __LINE__);
11873 tng_block_destroy(&block);
11874 return(TNG_CRITICAL);
11877 if(tng_block_read_next(tng_data, block,
11878 TNG_SKIP_HASH) != TNG_SUCCESS)
11880 tng_block_destroy(&block);
11881 return(TNG_CRITICAL);
11885 tng_block_destroy(&block);
11886 return(TNG_SUCCESS);
11891 /* Take one step backward until the right frame set is found */
11892 while(file_pos > 0 && curr_nr > nr)
11894 file_pos = frame_set->prev_frame_set_file_pos;
11898 fseek(tng_data->input_file,
11901 /* Read block headers first to see what block is found. */
11902 stat = tng_block_header_read(tng_data, block);
11903 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11905 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11906 file_pos, __FILE__, __LINE__);
11907 tng_block_destroy(&block);
11908 return(TNG_CRITICAL);
11911 if(tng_block_read_next(tng_data, block,
11912 TNG_SKIP_HASH) != TNG_SUCCESS)
11914 tng_block_destroy(&block);
11915 return(TNG_CRITICAL);
11919 tng_block_destroy(&block);
11920 return(TNG_SUCCESS);
11925 /* If for some reason the current frame set is not yet found,
11926 * take one step forward until the right frame set is found */
11927 while(file_pos > 0 && curr_nr < nr)
11929 file_pos = frame_set->next_frame_set_file_pos;
11933 fseek(tng_data->input_file,
11936 /* Read block headers first to see what block is found. */
11937 stat = tng_block_header_read(tng_data, block);
11938 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11940 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11941 file_pos, __FILE__, __LINE__);
11942 tng_block_destroy(&block);
11943 return(TNG_CRITICAL);
11946 if(tng_block_read_next(tng_data, block,
11947 TNG_SKIP_HASH) != TNG_SUCCESS)
11949 tng_block_destroy(&block);
11950 return(TNG_CRITICAL);
11954 tng_block_destroy(&block);
11955 return(TNG_SUCCESS);
11960 tng_block_destroy(&block);
11961 return(TNG_FAILURE);
11964 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11965 (tng_trajectory_t tng_data,
11966 const int64_t frame)
11968 int64_t first_frame, last_frame, n_frames_per_frame_set;
11969 int64_t long_stride_length, medium_stride_length;
11970 int64_t file_pos, temp_frame, n_frames;
11971 tng_trajectory_frame_set_t frame_set;
11972 tng_gen_block_t block;
11973 tng_function_status stat;
11975 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11976 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11978 frame_set = &tng_data->current_trajectory_frame_set;
11980 tng_block_init(&block);
11982 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11984 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11985 fseek(tng_data->input_file,
11988 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
11989 /* Read block headers first to see what block is found. */
11990 stat = tng_block_header_read(tng_data, block);
11991 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11993 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11994 file_pos, __FILE__, __LINE__);
11995 tng_block_destroy(&block);
11996 return(TNG_CRITICAL);
11999 if(tng_block_read_next(tng_data, block,
12000 TNG_SKIP_HASH) != TNG_SUCCESS)
12002 tng_block_destroy(&block);
12003 return(TNG_CRITICAL);
12007 first_frame = tng_max_i64(frame_set->first_frame, 0);
12008 last_frame = first_frame + frame_set->n_frames - 1;
12009 /* Is this the right frame set? */
12010 if(first_frame <= frame && frame <= last_frame)
12012 tng_block_destroy(&block);
12013 return(TNG_SUCCESS);
12016 n_frames_per_frame_set = tng_data->frame_set_n_frames;
12017 long_stride_length = tng_data->long_stride_length;
12018 medium_stride_length = tng_data->medium_stride_length;
12020 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
12023 if(temp_frame - first_frame > n_frames_per_frame_set)
12025 n_frames_per_frame_set = temp_frame - first_frame;
12029 tng_num_frames_get(tng_data, &n_frames);
12031 if(frame >= n_frames)
12033 tng_block_destroy(&block);
12034 return(TNG_FAILURE);
12037 if(first_frame - frame >= frame ||
12038 frame - last_frame >
12039 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
12041 /* Start from the beginning */
12042 if(first_frame - frame >= frame)
12044 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12048 tng_block_destroy(&block);
12049 return(TNG_FAILURE);
12052 /* Start from the end */
12053 else if(frame - first_frame > (n_frames - 1) - frame)
12055 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
12057 /* If the last frame set position is not set start from the current
12058 * frame set, since it will be closer than the first frame set. */
12060 /* Start from current */
12063 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12068 fseek(tng_data->input_file,
12071 tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
12072 /* Read block headers first to see what block is found. */
12073 stat = tng_block_header_read(tng_data, block);
12074 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12076 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12077 file_pos, __FILE__, __LINE__);
12078 tng_block_destroy(&block);
12079 return(TNG_CRITICAL);
12082 if(tng_block_read_next(tng_data, block,
12083 TNG_SKIP_HASH) != TNG_SUCCESS)
12085 tng_block_destroy(&block);
12086 return(TNG_CRITICAL);
12091 first_frame = tng_max_i64(frame_set->first_frame, 0);
12092 last_frame = first_frame + frame_set->n_frames - 1;
12094 if(frame >= first_frame && frame <= last_frame)
12096 tng_block_destroy(&block);
12097 return(TNG_SUCCESS);
12100 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12102 /* Take long steps forward until a long step forward would be too long or
12103 * the right frame set is found */
12104 while(file_pos > 0 && first_frame + long_stride_length *
12105 n_frames_per_frame_set <= frame)
12107 file_pos = frame_set->long_stride_next_frame_set_file_pos;
12110 fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
12111 /* Read block headers first to see what block is found. */
12112 stat = tng_block_header_read(tng_data, block);
12113 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12115 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12116 file_pos, __FILE__, __LINE__);
12117 tng_block_destroy(&block);
12118 return(TNG_CRITICAL);
12121 if(tng_block_read_next(tng_data, block,
12122 TNG_SKIP_HASH) != TNG_SUCCESS)
12124 tng_block_destroy(&block);
12125 return(TNG_CRITICAL);
12128 first_frame = tng_max_i64(frame_set->first_frame, 0);
12129 last_frame = first_frame + frame_set->n_frames - 1;
12130 if(frame >= first_frame && frame <= last_frame)
12132 tng_block_destroy(&block);
12133 return(TNG_SUCCESS);
12137 /* Take medium steps forward until a medium step forward would be too long
12138 * or the right frame set is found */
12139 while(file_pos > 0 && first_frame + medium_stride_length *
12140 n_frames_per_frame_set <= frame)
12142 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
12145 fseek(tng_data->input_file,
12148 /* Read block headers first to see what block is found. */
12149 stat = tng_block_header_read(tng_data, block);
12150 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12152 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12153 file_pos, __FILE__, __LINE__);
12154 tng_block_destroy(&block);
12155 return(TNG_CRITICAL);
12158 if(tng_block_read_next(tng_data, block,
12159 TNG_SKIP_HASH) != TNG_SUCCESS)
12161 tng_block_destroy(&block);
12162 return(TNG_CRITICAL);
12165 first_frame = tng_max_i64(frame_set->first_frame, 0);
12166 last_frame = first_frame + frame_set->n_frames - 1;
12167 if(frame >= first_frame && frame <= last_frame)
12169 tng_block_destroy(&block);
12170 return(TNG_SUCCESS);
12174 /* Take one step forward until the right frame set is found */
12175 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12177 file_pos = frame_set->next_frame_set_file_pos;
12180 fseek(tng_data->input_file,
12183 /* Read block headers first to see what block is found. */
12184 stat = tng_block_header_read(tng_data, block);
12185 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12187 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12188 file_pos, __FILE__, __LINE__);
12189 tng_block_destroy(&block);
12190 return(TNG_CRITICAL);
12193 if(tng_block_read_next(tng_data, block,
12194 TNG_SKIP_HASH) != TNG_SUCCESS)
12196 tng_block_destroy(&block);
12197 return(TNG_CRITICAL);
12200 first_frame = tng_max_i64(frame_set->first_frame, 0);
12201 last_frame = first_frame + frame_set->n_frames - 1;
12202 if(frame >= first_frame && frame <= last_frame)
12204 tng_block_destroy(&block);
12205 return(TNG_SUCCESS);
12209 /* Take long steps backward until a long step backward would be too long
12210 * or the right frame set is found */
12211 while(file_pos > 0 && first_frame - long_stride_length *
12212 n_frames_per_frame_set >= frame)
12214 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
12217 fseek(tng_data->input_file,
12220 /* Read block headers first to see what block is found. */
12221 stat = tng_block_header_read(tng_data, block);
12222 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12224 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12225 file_pos, __FILE__, __LINE__);
12226 tng_block_destroy(&block);
12227 return(TNG_CRITICAL);
12230 if(tng_block_read_next(tng_data, block,
12231 TNG_SKIP_HASH) != TNG_SUCCESS)
12233 tng_block_destroy(&block);
12234 return(TNG_CRITICAL);
12237 first_frame = tng_max_i64(frame_set->first_frame, 0);
12238 last_frame = first_frame + frame_set->n_frames - 1;
12239 if(frame >= first_frame && frame <= last_frame)
12241 tng_block_destroy(&block);
12242 return(TNG_SUCCESS);
12246 /* Take medium steps backward until a medium step backward would be too long
12247 * or the right frame set is found */
12248 while(file_pos > 0 && first_frame - medium_stride_length *
12249 n_frames_per_frame_set >= frame)
12251 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
12254 fseek(tng_data->input_file,
12257 /* Read block headers first to see what block is found. */
12258 stat = tng_block_header_read(tng_data, block);
12259 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12261 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12262 file_pos, __FILE__, __LINE__);
12263 tng_block_destroy(&block);
12264 return(TNG_CRITICAL);
12267 if(tng_block_read_next(tng_data, block,
12268 TNG_SKIP_HASH) != TNG_SUCCESS)
12270 tng_block_destroy(&block);
12271 return(TNG_CRITICAL);
12274 first_frame = tng_max_i64(frame_set->first_frame, 0);
12275 last_frame = first_frame + frame_set->n_frames - 1;
12276 if(frame >= first_frame && frame <= last_frame)
12278 tng_block_destroy(&block);
12279 return(TNG_SUCCESS);
12283 /* Take one step backward until the right frame set is found */
12284 while(file_pos > 0 && first_frame > frame && last_frame > frame)
12286 file_pos = frame_set->prev_frame_set_file_pos;
12289 fseek(tng_data->input_file,
12292 /* Read block headers first to see what block is found. */
12293 stat = tng_block_header_read(tng_data, block);
12294 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12296 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12297 file_pos, __FILE__, __LINE__);
12298 tng_block_destroy(&block);
12299 return(TNG_CRITICAL);
12302 if(tng_block_read_next(tng_data, block,
12303 TNG_SKIP_HASH) != TNG_SUCCESS)
12305 tng_block_destroy(&block);
12306 return(TNG_CRITICAL);
12309 first_frame = tng_max_i64(frame_set->first_frame, 0);
12310 last_frame = first_frame + frame_set->n_frames - 1;
12311 if(frame >= first_frame && frame <= last_frame)
12313 tng_block_destroy(&block);
12314 return(TNG_SUCCESS);
12318 /* If for some reason the current frame set is not yet found,
12319 * take one step forward until the right frame set is found */
12320 while(file_pos > 0 && first_frame < frame && last_frame < frame)
12322 file_pos = frame_set->next_frame_set_file_pos;
12325 fseek(tng_data->input_file,
12328 /* Read block headers first to see what block is found. */
12329 stat = tng_block_header_read(tng_data, block);
12330 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12332 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12333 file_pos, __FILE__, __LINE__);
12334 tng_block_destroy(&block);
12335 return(TNG_CRITICAL);
12338 if(tng_block_read_next(tng_data, block,
12339 TNG_SKIP_HASH) != TNG_SUCCESS)
12341 tng_block_destroy(&block);
12342 return(TNG_CRITICAL);
12345 first_frame = tng_max_i64(frame_set->first_frame, 0);
12346 last_frame = first_frame + frame_set->n_frames - 1;
12347 if(frame >= first_frame && frame <= last_frame)
12349 tng_block_destroy(&block);
12350 return(TNG_SUCCESS);
12354 tng_block_destroy(&block);
12355 return(TNG_FAILURE);
12358 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12359 (const tng_trajectory_t tng_data,
12360 const tng_trajectory_frame_set_t frame_set,
12365 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12366 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12368 *pos = frame_set->next_frame_set_file_pos;
12370 return(TNG_SUCCESS);
12373 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12374 (const tng_trajectory_t tng_data,
12375 const tng_trajectory_frame_set_t frame_set,
12380 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
12381 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
12383 *pos = frame_set->prev_frame_set_file_pos;
12385 return(TNG_SUCCESS);
12388 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12389 (const tng_trajectory_t tng_data,
12390 const tng_trajectory_frame_set_t frame_set,
12391 int64_t *first_frame,
12392 int64_t *last_frame)
12396 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
12397 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
12398 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
12400 *first_frame = frame_set->first_frame;
12401 *last_frame = *first_frame + frame_set->n_frames - 1;
12403 return(TNG_SUCCESS);
12406 /** Translate from the particle numbering used in a frame set to the real
12407 * particle numbering - used in the molecule description.
12408 * @param frame_set is the frame_set containing the mappings to use.
12409 * @param local is the index number of the atom in this frame set
12410 * @param real is set to the index of the atom in the molecular system.
12411 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12414 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12415 (const tng_trajectory_frame_set_t frame_set,
12416 const int64_t local,
12419 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12420 tng_particle_mapping_t mapping;
12424 return(TNG_SUCCESS);
12426 for(i = 0; i < n_blocks; i++)
12428 mapping = &frame_set->mappings[i];
12429 first = mapping->num_first_particle;
12430 if(local < first ||
12431 local >= first + mapping->n_particles)
12435 *real = mapping->real_particle_numbers[local-first];
12436 return(TNG_SUCCESS);
12439 return(TNG_FAILURE);
12442 /** Translate from the real particle numbering to the particle numbering
12443 * used in a frame set.
12444 * @param frame_set is the frame_set containing the mappings to use.
12445 * @param real is the index number of the atom in the molecular system.
12446 * @param local is set to the index of the atom in this frame set.
12447 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12450 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12451 (const tng_trajectory_frame_set_t frame_set,
12452 const int64_t real,
12455 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12456 tng_particle_mapping_t mapping;
12460 return(TNG_SUCCESS);
12462 for(i = 0; i < n_blocks; i++)
12464 mapping = &frame_set->mappings[i];
12465 for(j = mapping->n_particles; j--;)
12467 if(mapping->real_particle_numbers[j] == real)
12470 return(TNG_SUCCESS);
12474 return(TNG_FAILURE);
12478 static tng_function_status tng_file_headers_len_get
12479 (tng_trajectory_t tng_data,
12483 tng_gen_block_t block;
12485 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12487 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12489 return(TNG_CRITICAL);
12494 orig_pos = ftell(tng_data->input_file);
12496 if(!tng_data->input_file_len)
12498 fseek(tng_data->input_file, 0, SEEK_END);
12499 tng_data->input_file_len = ftell(tng_data->input_file);
12501 fseek(tng_data->input_file, 0, SEEK_SET);
12503 tng_block_init(&block);
12504 /* Read through the headers of non-trajectory blocks (they come before the
12505 * trajectory blocks in the file) */
12506 while (*len < tng_data->input_file_len &&
12507 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12509 block->id != TNG_TRAJECTORY_FRAME_SET)
12511 *len += block->header_contents_size + block->block_contents_size;
12512 fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12515 fseek(tng_data->input_file, orig_pos, SEEK_SET);
12517 tng_block_destroy(&block);
12519 return(TNG_SUCCESS);
12522 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12523 (tng_trajectory_t tng_data,
12524 const char hash_mode)
12526 int64_t prev_pos = 0;
12527 tng_gen_block_t block;
12529 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12531 tng_data->n_trajectory_frame_sets = 0;
12533 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12535 return(TNG_CRITICAL);
12538 if(!tng_data->input_file_len)
12540 fseek(tng_data->input_file, 0, SEEK_END);
12541 tng_data->input_file_len = ftell(tng_data->input_file);
12543 fseek(tng_data->input_file, 0, SEEK_SET);
12545 tng_block_init(&block);
12546 /* Non trajectory blocks (they come before the trajectory
12547 * blocks in the file) */
12548 while (prev_pos < tng_data->input_file_len &&
12549 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
12551 block->id != TNG_TRAJECTORY_FRAME_SET)
12553 tng_block_read_next(tng_data, block, hash_mode);
12554 prev_pos = ftell(tng_data->input_file);
12557 /* Go back if a trajectory block was encountered */
12558 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12560 fseek(tng_data->input_file, prev_pos, SEEK_SET);
12563 tng_block_destroy(&block);
12565 return(TNG_SUCCESS);
12568 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12569 (tng_trajectory_t tng_data,
12570 const char hash_mode)
12573 int64_t len, orig_len, tot_len = 0, data_start_pos;
12574 tng_function_status stat;
12575 tng_gen_block_t block;
12577 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12579 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
12581 return(TNG_CRITICAL);
12584 if(tng_data->n_trajectory_frame_sets > 0)
12586 stat = tng_file_headers_len_get(tng_data, &orig_len);
12587 if(stat != TNG_SUCCESS)
12592 tng_block_init(&block);
12593 block->name = malloc(TNG_MAX_STR_LEN);
12596 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12597 TNG_MAX_STR_LEN, __FILE__, __LINE__);
12598 tng_block_destroy(&block);
12599 return(TNG_CRITICAL);
12601 strcpy(block->name, "GENERAL INFO");
12602 tng_block_header_len_calculate(tng_data, block, &len);
12604 tng_general_info_block_len_calculate(tng_data, &len);
12606 strcpy(block->name, "MOLECULES");
12607 tng_block_header_len_calculate(tng_data, block, &len);
12609 tng_molecules_block_len_calculate(tng_data, &len);
12612 for(i = 0; i < tng_data->n_data_blocks; i++)
12614 strcpy(block->name, tng_data->non_tr_data[i].block_name);
12615 tng_block_header_len_calculate(tng_data, block, &len);
12617 tng_data_block_len_calculate(tng_data,
12618 (tng_particle_data_t)&tng_data->non_tr_data[i],
12619 TNG_FALSE, 1, 1, 1, 0,
12620 1, 0, &data_start_pos,
12624 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12626 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
12627 tng_block_header_len_calculate(tng_data, block, &len);
12629 tng_data_block_len_calculate(tng_data,
12630 &tng_data->non_tr_particle_data[i],
12631 TNG_TRUE, 1, 1, 1, 0,
12632 tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
12637 tng_block_destroy(&block);
12639 if(tot_len > orig_len)
12641 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
12644 tng_data->current_trajectory_frame_set_output_file_pos = -1;
12647 /* TODO: If there is already frame set data written to this file (e.g. when
12648 * appending to an already existing file we might need to move frame sets to
12649 * the end of the file. */
12651 if(tng_general_info_block_write(tng_data, hash_mode)
12654 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
12655 tng_data->input_file_path, __FILE__, __LINE__);
12656 return(TNG_CRITICAL);
12659 if(tng_molecules_block_write(tng_data, hash_mode)
12662 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12663 tng_data->input_file_path, __FILE__, __LINE__);
12664 return(TNG_CRITICAL);
12667 /* FIXME: Currently writing non-trajectory data blocks here.
12668 * Should perhaps be moved. */
12669 tng_block_init(&block);
12670 for(i = 0; i < tng_data->n_data_blocks; i++)
12672 block->id = tng_data->non_tr_data[i].block_id;
12673 tng_data_block_write(tng_data, block,
12677 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12679 block->id = tng_data->non_tr_particle_data[i].block_id;
12680 tng_particle_data_block_write(tng_data, block,
12684 tng_block_destroy(&block);
12686 return(TNG_SUCCESS);
12689 tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
12690 tng_gen_block_t block,
12691 const char hash_mode)
12693 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12694 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
12698 case TNG_TRAJECTORY_FRAME_SET:
12699 return(tng_frame_set_block_read(tng_data, block, hash_mode));
12700 case TNG_PARTICLE_MAPPING:
12701 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
12702 case TNG_GENERAL_INFO:
12703 return(tng_general_info_block_read(tng_data, block, hash_mode));
12704 case TNG_MOLECULES:
12705 return(tng_molecules_block_read(tng_data, block, hash_mode));
12707 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12709 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12713 /* Skip to the next block */
12714 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12715 return(TNG_FAILURE);
12720 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12721 (tng_trajectory_t tng_data,
12722 const char hash_mode)
12725 tng_gen_block_t block;
12726 tng_function_status stat;
12728 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12730 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12732 return(TNG_CRITICAL);
12735 file_pos = ftell(tng_data->input_file);
12737 tng_block_init(&block);
12739 if(!tng_data->input_file_len)
12741 fseek(tng_data->input_file, 0, SEEK_END);
12742 tng_data->input_file_len = ftell(tng_data->input_file);
12743 fseek(tng_data->input_file, file_pos, SEEK_SET);
12746 /* Read block headers first to see what block is found. */
12747 stat = tng_block_header_read(tng_data, block);
12748 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
12751 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12752 file_pos, __FILE__, __LINE__);
12753 tng_block_destroy(&block);
12754 return(TNG_CRITICAL);
12757 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12759 if(tng_block_read_next(tng_data, block,
12760 hash_mode) == TNG_SUCCESS)
12762 tng_data->n_trajectory_frame_sets++;
12763 file_pos = ftell(tng_data->input_file);
12764 /* Read all blocks until next frame set block */
12765 stat = tng_block_header_read(tng_data, block);
12766 while(file_pos < tng_data->input_file_len &&
12767 stat != TNG_CRITICAL &&
12768 block->id != TNG_TRAJECTORY_FRAME_SET &&
12771 stat = tng_block_read_next(tng_data, block,
12773 if(stat != TNG_CRITICAL)
12775 file_pos = ftell(tng_data->input_file);
12776 if(file_pos < tng_data->input_file_len)
12778 stat = tng_block_header_read(tng_data, block);
12782 if(stat == TNG_CRITICAL)
12784 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12785 file_pos, __FILE__, __LINE__);
12786 tng_block_destroy(&block);
12790 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12792 fseek(tng_data->input_file, file_pos, SEEK_SET);
12796 tng_block_destroy(&block);
12798 return(TNG_SUCCESS);
12802 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12803 (tng_trajectory_t tng_data,
12804 const char hash_mode,
12805 const int64_t block_id)
12808 tng_gen_block_t block;
12809 tng_function_status stat;
12810 int found_flag = 1;
12812 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12814 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12816 return(TNG_CRITICAL);
12819 file_pos = (long)tng_data->current_trajectory_frame_set_input_file_pos;
12823 /* No current frame set. This means that the first frame set must be
12826 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12831 fseek(tng_data->input_file,
12837 return(TNG_FAILURE);
12840 tng_block_init(&block);
12842 if(!tng_data->input_file_len)
12844 fseek(tng_data->input_file, 0, SEEK_END);
12845 tng_data->input_file_len = ftell(tng_data->input_file);
12846 fseek(tng_data->input_file, file_pos, SEEK_SET);
12849 /* Read block headers first to see what block is found. */
12850 stat = tng_block_header_read(tng_data, block);
12851 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12853 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12854 file_pos, __FILE__, __LINE__);
12855 tng_block_destroy(&block);
12856 return(TNG_CRITICAL);
12858 /* If the current frame set had already been read skip its block contents */
12861 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12863 /* Otherwiese read the frame set block */
12866 stat = tng_block_read_next(tng_data, block,
12868 if(stat != TNG_SUCCESS)
12870 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
12871 tng_block_destroy(&block);
12875 file_pos = ftell(tng_data->input_file);
12879 /* Read only blocks of the requested ID
12880 * until next frame set block */
12881 stat = tng_block_header_read(tng_data, block);
12882 while(file_pos < tng_data->input_file_len &&
12883 stat != TNG_CRITICAL &&
12884 block->id != TNG_TRAJECTORY_FRAME_SET &&
12887 if(block->id == block_id)
12889 stat = tng_block_read_next(tng_data, block,
12891 if(stat != TNG_CRITICAL)
12893 file_pos = ftell(tng_data->input_file);
12895 if(file_pos < tng_data->input_file_len)
12897 stat = tng_block_header_read(tng_data, block);
12903 file_pos += (long)(block->block_contents_size + block->header_contents_size);
12904 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12905 if(file_pos < tng_data->input_file_len)
12907 stat = tng_block_header_read(tng_data, block);
12911 if(stat == TNG_CRITICAL)
12913 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12914 file_pos, __FILE__, __LINE__);
12915 tng_block_destroy(&block);
12919 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12921 fseek(tng_data->input_file, file_pos, SEEK_SET);
12924 tng_block_destroy(&block);
12928 return(TNG_SUCCESS);
12932 return(TNG_FAILURE);
12936 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12937 (tng_trajectory_t tng_data,
12938 const char hash_mode)
12942 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12944 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12946 return(TNG_CRITICAL);
12949 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12951 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12953 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12958 fseek(tng_data->input_file,
12964 return(TNG_FAILURE);
12967 return(tng_frame_set_read(tng_data, hash_mode));
12970 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12971 (tng_trajectory_t tng_data,
12972 const char hash_mode,
12973 const int64_t block_id)
12976 tng_gen_block_t block;
12977 tng_function_status stat;
12979 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12981 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12983 return(TNG_CRITICAL);
12986 file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12988 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12990 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12995 fseek(tng_data->input_file,
13001 return(TNG_FAILURE);
13004 tng_block_init(&block);
13006 if(!tng_data->input_file_len)
13008 fseek(tng_data->input_file, 0, SEEK_END);
13009 tng_data->input_file_len = ftell(tng_data->input_file);
13010 fseek(tng_data->input_file, file_pos, SEEK_SET);
13013 /* Read block headers first to see what block is found. */
13014 stat = tng_block_header_read(tng_data, block);
13015 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13017 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13018 file_pos, __FILE__, __LINE__);
13019 tng_block_destroy(&block);
13020 return(TNG_CRITICAL);
13023 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
13025 if(tng_block_read_next(tng_data, block,
13026 hash_mode) == TNG_SUCCESS)
13028 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
13031 tng_block_destroy(&block);
13036 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13037 const char hash_mode)
13040 tng_gen_block_t block;
13041 tng_trajectory_frame_set_t frame_set;
13042 tng_function_status stat;
13044 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13046 frame_set = &tng_data->current_trajectory_frame_set;
13048 if(frame_set->n_written_frames == frame_set->n_frames)
13050 return(TNG_SUCCESS);
13053 tng_data->current_trajectory_frame_set_output_file_pos =
13054 ftell(tng_data->output_file);
13055 tng_data->last_trajectory_frame_set_output_file_pos =
13056 tng_data->current_trajectory_frame_set_output_file_pos;
13058 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
13060 return(TNG_FAILURE);
13063 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
13065 tng_data->first_trajectory_frame_set_output_file_pos =
13066 tng_data->current_trajectory_frame_set_output_file_pos;
13069 tng_block_init(&block);
13071 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
13073 tng_block_destroy(&block);
13074 return(TNG_FAILURE);
13077 /* Write non-particle data blocks */
13078 for(i = 0; i<frame_set->n_data_blocks; i++)
13080 block->id = frame_set->tr_data[i].block_id;
13081 tng_data_block_write(tng_data, block, i, hash_mode);
13083 /* Write the mapping blocks and particle data blocks*/
13084 if(frame_set->n_mapping_blocks)
13086 for(i = 0; i < frame_set->n_mapping_blocks; i++)
13088 block->id = TNG_PARTICLE_MAPPING;
13089 if(frame_set->mappings[i].n_particles > 0)
13091 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
13092 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
13094 block->id = frame_set->tr_particle_data[j].block_id;
13095 tng_particle_data_block_write(tng_data, block,
13096 j, &frame_set->mappings[i],
13104 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
13106 block->id = frame_set->tr_particle_data[i].block_id;
13107 tng_particle_data_block_write(tng_data, block,
13113 /* Update pointers in the general info block */
13114 stat = tng_header_pointers_update(tng_data, hash_mode);
13116 if(stat == TNG_SUCCESS)
13118 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
13121 tng_block_destroy(&block);
13123 frame_set->n_unwritten_frames = 0;
13125 fflush(tng_data->output_file);
13130 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13131 (tng_trajectory_t tng_data,
13132 const char hash_mode)
13134 tng_trajectory_frame_set_t frame_set;
13136 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13138 frame_set = &tng_data->current_trajectory_frame_set;
13140 if(frame_set->n_unwritten_frames == 0)
13142 return(TNG_SUCCESS);
13144 frame_set->n_frames = frame_set->n_unwritten_frames;
13146 return(tng_frame_set_write(tng_data, hash_mode));
13149 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13150 (tng_trajectory_t tng_data,
13151 const int64_t first_frame,
13152 const int64_t n_frames)
13154 tng_gen_block_t block;
13155 tng_trajectory_frame_set_t frame_set;
13156 FILE *temp = tng_data->input_file;
13159 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13160 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13161 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13163 frame_set = &tng_data->current_trajectory_frame_set;
13165 curr_pos = ftell(tng_data->output_file);
13169 tng_file_headers_write(tng_data, TNG_USE_HASH);
13172 /* Set pointer to previous frame set to the one that was loaded
13174 * FIXME: This is a bit risky. If they are not added in order
13175 * it will be wrong. */
13176 if(tng_data->n_trajectory_frame_sets)
13178 frame_set->prev_frame_set_file_pos =
13179 tng_data->current_trajectory_frame_set_output_file_pos;
13182 tng_data->current_trajectory_frame_set_output_file_pos =
13183 ftell(tng_data->output_file);
13185 tng_data->n_trajectory_frame_sets++;
13187 /* Set the medium range pointers */
13188 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
13190 frame_set->medium_stride_prev_frame_set_file_pos =
13191 tng_data->first_trajectory_frame_set_output_file_pos;
13193 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13195 /* FIXME: Currently only working if the previous frame set has its
13196 * medium stride pointer already set. This might need some fixing. */
13197 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
13198 frame_set->medium_stride_prev_frame_set_file_pos != 0)
13200 tng_block_init(&block);
13201 tng_data->input_file = tng_data->output_file;
13203 curr_pos = ftell(tng_data->output_file);
13204 fseek(tng_data->output_file,
13205 (long)frame_set->medium_stride_prev_frame_set_file_pos,
13208 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13210 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13211 __FILE__, __LINE__);
13212 tng_data->input_file = temp;
13213 tng_block_destroy(&block);
13214 return(TNG_CRITICAL);
13217 /* Read the next frame set from the previous frame set and one
13218 * medium stride step back */
13219 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
13220 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13221 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
13222 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
13223 1, tng_data->output_file) == 0)
13225 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13226 tng_data->input_file = temp;
13227 tng_block_destroy(&block);
13228 return(TNG_CRITICAL);
13231 if(tng_data->input_endianness_swap_func_64)
13233 if(tng_data->input_endianness_swap_func_64(tng_data,
13234 &frame_set->medium_stride_prev_frame_set_file_pos)
13237 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13238 __FILE__, __LINE__);
13242 tng_block_destroy(&block);
13244 /* Set the long range pointers */
13245 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
13247 frame_set->long_stride_prev_frame_set_file_pos =
13248 tng_data->first_trajectory_frame_set_output_file_pos;
13250 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
13252 /* FIXME: Currently only working if the previous frame set has its
13253 * long stride pointer already set. This might need some fixing. */
13254 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
13255 frame_set->long_stride_prev_frame_set_file_pos != 0)
13257 tng_block_init(&block);
13258 tng_data->input_file = tng_data->output_file;
13260 fseek(tng_data->output_file,
13261 (long)frame_set->long_stride_prev_frame_set_file_pos,
13264 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
13266 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
13267 __FILE__, __LINE__);
13268 tng_data->input_file = temp;
13269 tng_block_destroy(&block);
13270 return(TNG_CRITICAL);
13273 /* Read the next frame set from the previous frame set and one
13274 * long stride step back */
13275 fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
13276 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
13278 tng_block_destroy(&block);
13280 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
13281 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
13282 1, tng_data->output_file) == 0)
13284 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
13285 tng_data->input_file = temp;
13286 return(TNG_CRITICAL);
13289 if(tng_data->input_endianness_swap_func_64)
13291 if(tng_data->input_endianness_swap_func_64(tng_data,
13292 &frame_set->long_stride_prev_frame_set_file_pos)
13295 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13296 __FILE__, __LINE__);
13303 tng_data->input_file = temp;
13304 fseek(tng_data->output_file, (long)curr_pos, SEEK_SET);
13308 frame_set->first_frame = first_frame;
13309 frame_set->n_frames = n_frames;
13310 frame_set->n_written_frames = 0;
13311 frame_set->n_unwritten_frames = 0;
13312 frame_set->first_frame_time = -1;
13314 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
13315 tng_data->first_trajectory_frame_set_output_file_pos == 0)
13317 tng_data->first_trajectory_frame_set_output_file_pos =
13318 tng_data->current_trajectory_frame_set_output_file_pos;
13320 /* FIXME: Should check the frame number instead of the file_pos,
13321 * in case frame sets are not in order */
13322 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
13323 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
13324 tng_data->last_trajectory_frame_set_output_file_pos <
13325 tng_data->current_trajectory_frame_set_output_file_pos)
13327 tng_data->last_trajectory_frame_set_output_file_pos =
13328 tng_data->current_trajectory_frame_set_output_file_pos;
13331 return(TNG_SUCCESS);
13334 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13335 (tng_trajectory_t tng_data,
13336 const int64_t first_frame,
13337 const int64_t n_frames,
13338 const double first_frame_time)
13340 tng_function_status stat;
13342 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13343 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
13344 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
13345 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13348 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
13349 if(stat != TNG_SUCCESS)
13353 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13358 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13359 (tng_trajectory_t tng_data,
13360 const double first_frame_time)
13362 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13363 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
13365 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
13367 return(TNG_SUCCESS);
13370 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13371 (const tng_trajectory_t tng_data,
13374 long file_pos, next_frame_set_file_pos;
13375 tng_gen_block_t block;
13376 tng_function_status stat;
13378 tng_trajectory_frame_set_t frame_set;
13380 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13381 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
13382 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
13384 file_pos = ftell(tng_data->input_file);
13386 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13388 next_frame_set_file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
13392 frame_set = &tng_data->current_trajectory_frame_set;
13393 next_frame_set_file_pos = (long)frame_set->next_frame_set_file_pos;
13396 if(next_frame_set_file_pos <= 0)
13398 return(TNG_FAILURE);
13401 fseek(tng_data->input_file, (long)next_frame_set_file_pos, SEEK_SET);
13402 /* Read block headers first to see that a frame set block is found. */
13403 tng_block_init(&block);
13404 stat = tng_block_header_read(tng_data, block);
13405 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
13407 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13408 file_pos, __FILE__, __LINE__);
13409 return(TNG_CRITICAL);
13411 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13413 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13415 tng_block_destroy(&block);
13417 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
13419 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13420 __FILE__, __LINE__);
13421 return(TNG_CRITICAL);
13423 fseek(tng_data->input_file, file_pos, SEEK_SET);
13425 return(TNG_SUCCESS);
13428 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13429 (tng_trajectory_t tng_data,
13431 const char *block_name,
13432 const char datatype,
13433 const char block_type_flag,
13435 const int64_t n_values_per_frame,
13436 int64_t stride_length,
13437 const int64_t codec_id,
13440 int i, j, size, len;
13441 tng_trajectory_frame_set_t frame_set;
13442 tng_non_particle_data_t data;
13443 char **first_dim_values;
13444 char *new_data_c=new_data;
13445 int64_t n_frames_div;
13447 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13448 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
13449 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13451 frame_set = &tng_data->current_trajectory_frame_set;
13453 if(stride_length <= 0)
13458 /* If the block does not exist, create it */
13459 if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
13461 if(tng_data_block_create(tng_data, block_type_flag) !=
13464 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
13465 __FILE__, __LINE__);
13466 return(TNG_CRITICAL);
13468 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13470 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
13474 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
13476 data->block_id = id;
13478 data->block_name = malloc(strlen(block_name) + 1);
13479 if(!data->block_name)
13481 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13482 (int)strlen(block_name)+1, __FILE__, __LINE__);
13483 return(TNG_CRITICAL);
13485 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13488 /* FIXME: Memory leak from strings. */
13490 data->last_retrieved_frame = -1;
13493 data->datatype = datatype;
13494 data->stride_length = tng_max_i64(stride_length, 1);
13495 data->n_values_per_frame = n_values_per_frame;
13496 data->n_frames = n_frames;
13497 data->codec_id = codec_id;
13498 data->compression_multiplier = 1.0;
13499 /* FIXME: This can cause problems. */
13500 data->first_frame_with_data = frame_set->first_frame;
13504 case TNG_FLOAT_DATA:
13505 size = sizeof(float);
13508 size = sizeof(int64_t);
13510 case TNG_DOUBLE_DATA:
13512 size = sizeof(double);
13518 /* Allocate memory */
13519 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13520 n_values_per_frame) !=
13523 fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
13524 __FILE__, __LINE__);
13525 return(TNG_CRITICAL);
13528 if(n_frames > frame_set->n_unwritten_frames)
13530 frame_set->n_unwritten_frames = n_frames;
13533 n_frames_div = (n_frames % stride_length) ?
13534 n_frames / stride_length + 1:
13535 n_frames / stride_length;
13537 if(datatype == TNG_CHAR_DATA)
13539 for(i = 0; i < n_frames_div; i++)
13541 first_dim_values = data->strings[i];
13542 for(j = 0; j < n_values_per_frame; j++)
13544 len = tng_min_i((int)strlen(new_data_c) + 1,
13546 if(first_dim_values[j])
13548 free(first_dim_values[j]);
13550 first_dim_values[j] = malloc(len);
13551 if(!first_dim_values[j])
13553 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13554 len, __FILE__, __LINE__);
13555 return(TNG_CRITICAL);
13557 strncpy(first_dim_values[j],
13565 memcpy(data->values, new_data, size * n_frames_div *
13566 n_values_per_frame);
13570 return(TNG_SUCCESS);
13573 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13574 (tng_trajectory_t tng_data,
13576 const char *block_name,
13577 const char datatype,
13578 const char block_type_flag,
13580 const int64_t n_values_per_frame,
13581 int64_t stride_length,
13582 const int64_t num_first_particle,
13583 const int64_t n_particles,
13584 const int64_t codec_id,
13589 int64_t tot_n_particles, n_frames_div;
13590 char ***first_dim_values, **second_dim_values;
13591 tng_trajectory_frame_set_t frame_set;
13592 tng_particle_data_t data;
13593 char *new_data_c=new_data;
13595 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13596 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
13597 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
13598 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
13599 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
13602 frame_set = &tng_data->current_trajectory_frame_set;
13604 if(stride_length <= 0)
13609 /* If the block does not exist, create it */
13610 if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
13612 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
13615 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
13616 __FILE__, __LINE__);
13617 return(TNG_CRITICAL);
13619 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
13621 data = &frame_set->tr_particle_data[frame_set->
13622 n_particle_data_blocks - 1];
13626 data = &tng_data->non_tr_particle_data[tng_data->
13627 n_particle_data_blocks - 1];
13629 data->block_id = id;
13631 data->block_name = malloc(strlen(block_name) + 1);
13632 if(!data->block_name)
13634 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13635 (int)strlen(block_name)+1, __FILE__, __LINE__);
13636 return(TNG_CRITICAL);
13638 strncpy(data->block_name, block_name, strlen(block_name) + 1);
13640 data->datatype = datatype;
13643 /* FIXME: Memory leak from strings. */
13645 data->last_retrieved_frame = -1;
13648 data->stride_length = tng_max_i64(stride_length, 1);
13649 data->n_values_per_frame = n_values_per_frame;
13650 data->n_frames = n_frames;
13651 data->codec_id = codec_id;
13652 data->compression_multiplier = 1.0;
13653 /* FIXME: This can cause problems. */
13654 data->first_frame_with_data = frame_set->first_frame;
13656 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
13658 tot_n_particles = frame_set->n_particles;
13662 tot_n_particles = tng_data->n_particles;
13665 /* If data values are supplied add that data to the data block. */
13668 /* Allocate memory */
13669 if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
13670 stride_length, tot_n_particles,
13671 n_values_per_frame) !=
13674 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13675 __FILE__, __LINE__);
13676 return(TNG_CRITICAL);
13679 if(n_frames > frame_set->n_unwritten_frames)
13681 frame_set->n_unwritten_frames = n_frames;
13684 n_frames_div = (n_frames % stride_length) ?
13685 n_frames / stride_length + 1:
13686 n_frames / stride_length;
13688 if(datatype == TNG_CHAR_DATA)
13690 for(i = 0; i < n_frames_div; i++)
13692 first_dim_values = data->strings[i];
13693 for(j = num_first_particle; j < num_first_particle + n_particles;
13696 second_dim_values = first_dim_values[j];
13697 for(k = 0; k < n_values_per_frame; k++)
13699 len = tng_min_i((int)strlen(new_data_c) + 1,
13701 if(second_dim_values[k])
13703 free(second_dim_values[k]);
13705 second_dim_values[k] = malloc(len);
13706 if(!second_dim_values[k])
13708 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13709 len, __FILE__, __LINE__);
13710 return(TNG_CRITICAL);
13712 strncpy(second_dim_values[k],
13724 size = sizeof(int64_t);
13726 case TNG_FLOAT_DATA:
13727 size = sizeof(float);
13729 case TNG_DOUBLE_DATA:
13731 size = sizeof(double);
13734 memcpy(data->values, new_data, size * n_frames_div *
13735 n_particles * n_values_per_frame);
13739 return(TNG_SUCCESS);
13742 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13743 (tng_trajectory_t tng_data,
13749 tng_trajectory_frame_set_t frame_set;
13750 tng_function_status stat;
13751 tng_particle_data_t p_data;
13752 tng_non_particle_data_t np_data;
13753 int block_type = -1;
13755 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13756 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
13758 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13760 p_data = &tng_data->non_tr_particle_data[i];
13761 if(p_data->block_id == block_id)
13763 strncpy(name, p_data->block_name, max_len);
13764 name[max_len - 1] = '\0';
13765 return(TNG_SUCCESS);
13768 for(i = 0; i < tng_data->n_data_blocks; i++)
13770 np_data = &tng_data->non_tr_data[i];
13771 if(np_data->block_id == block_id)
13773 strncpy(name, np_data->block_name, max_len);
13774 name[max_len - 1] = '\0';
13775 return(TNG_SUCCESS);
13779 frame_set = &tng_data->current_trajectory_frame_set;
13781 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13782 if(stat == TNG_SUCCESS)
13784 block_type = TNG_PARTICLE_BLOCK_DATA;
13788 stat = tng_data_find(tng_data, block_id, &np_data);
13789 if(stat == TNG_SUCCESS)
13791 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13795 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13796 if(stat != TNG_SUCCESS)
13800 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13801 if(stat == TNG_SUCCESS)
13803 block_type = TNG_PARTICLE_BLOCK_DATA;
13807 stat = tng_data_find(tng_data, block_id, &np_data);
13808 if(stat == TNG_SUCCESS)
13810 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13815 if(block_type == TNG_PARTICLE_BLOCK_DATA)
13817 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13819 p_data = &frame_set->tr_particle_data[i];
13820 if(p_data->block_id == block_id)
13822 strncpy(name, p_data->block_name, max_len);
13823 name[max_len - 1] = '\0';
13824 return(TNG_SUCCESS);
13828 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
13830 for(i = 0; i < frame_set->n_data_blocks; i++)
13832 np_data = &frame_set->tr_data[i];
13833 if(np_data->block_id == block_id)
13835 strncpy(name, np_data->block_name, max_len);
13836 name[max_len - 1] = '\0';
13837 return(TNG_SUCCESS);
13842 return(TNG_FAILURE);
13845 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13846 (const tng_trajectory_t tng_data,
13848 int *block_dependency)
13851 tng_function_status stat;
13852 tng_particle_data_t p_data;
13853 tng_non_particle_data_t np_data;
13855 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13856 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
13858 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13860 p_data = &tng_data->non_tr_particle_data[i];
13861 if(p_data->block_id == block_id)
13863 *block_dependency = TNG_PARTICLE_DEPENDENT;
13864 return(TNG_SUCCESS);
13867 for(i = 0; i < tng_data->n_data_blocks; i++)
13869 np_data = &tng_data->non_tr_data[i];
13870 if(np_data->block_id == block_id)
13872 *block_dependency = 0;
13873 return(TNG_SUCCESS);
13877 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13878 if(stat == TNG_SUCCESS)
13880 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13881 return(TNG_SUCCESS);
13885 stat = tng_data_find(tng_data, block_id, &np_data);
13886 if(stat == TNG_SUCCESS)
13888 *block_dependency = TNG_FRAME_DEPENDENT;
13889 return(TNG_SUCCESS);
13893 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13894 if(stat != TNG_SUCCESS)
13898 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13899 if(stat == TNG_SUCCESS)
13901 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
13902 return(TNG_SUCCESS);
13906 stat = tng_data_find(tng_data, block_id, &np_data);
13907 if(stat == TNG_SUCCESS)
13909 *block_dependency = TNG_FRAME_DEPENDENT;
13910 return(TNG_SUCCESS);
13916 return(TNG_FAILURE);
13919 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13920 (const tng_trajectory_t tng_data,
13922 int64_t *n_values_per_frame)
13925 tng_function_status stat;
13926 tng_particle_data_t p_data;
13927 tng_non_particle_data_t np_data;
13929 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13930 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13932 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13934 p_data = &tng_data->non_tr_particle_data[i];
13935 if(p_data->block_id == block_id)
13937 *n_values_per_frame = p_data->n_values_per_frame;
13938 return(TNG_SUCCESS);
13941 for(i = 0; i < tng_data->n_data_blocks; i++)
13943 np_data = &tng_data->non_tr_data[i];
13944 if(np_data->block_id == block_id)
13946 *n_values_per_frame = np_data->n_values_per_frame;
13947 return(TNG_SUCCESS);
13951 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13952 if(stat == TNG_SUCCESS)
13954 *n_values_per_frame = p_data->n_values_per_frame;
13955 return(TNG_SUCCESS);
13959 stat = tng_data_find(tng_data, block_id, &np_data);
13960 if(stat == TNG_SUCCESS)
13962 *n_values_per_frame = np_data->n_values_per_frame;
13963 return(TNG_SUCCESS);
13967 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13968 if(stat != TNG_SUCCESS)
13972 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13973 if(stat == TNG_SUCCESS)
13975 *n_values_per_frame = p_data->n_values_per_frame;
13976 return(TNG_SUCCESS);
13980 stat = tng_data_find(tng_data, block_id, &np_data);
13981 if(stat == TNG_SUCCESS)
13983 *n_values_per_frame = np_data->n_values_per_frame;
13984 return(TNG_SUCCESS);
13990 return(TNG_FAILURE);
13993 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13994 (tng_trajectory_t tng_data,
13995 const int64_t frame_nr,
13996 const int64_t block_id,
13997 const void *values,
13998 const char hash_mode)
14000 int64_t header_pos, file_pos;
14001 int64_t output_file_len, n_values_per_frame, size, contents_size;
14002 int64_t header_size, temp_first, temp_last;
14003 int64_t i, last_frame;
14005 tng_gen_block_t block;
14006 tng_trajectory_frame_set_t frame_set;
14007 FILE *temp = tng_data->input_file;
14008 struct tng_non_particle_data data;
14009 tng_function_status stat;
14010 char dependency, sparse_data, datatype;
14013 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14014 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14015 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14017 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14019 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14020 __FILE__, __LINE__);
14021 return(TNG_CRITICAL);
14024 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14025 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14026 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14027 tng_data->first_trajectory_frame_set_input_file_pos =
14028 tng_data->first_trajectory_frame_set_output_file_pos;
14029 tng_data->last_trajectory_frame_set_input_file_pos =
14030 tng_data->last_trajectory_frame_set_output_file_pos;
14031 tng_data->current_trajectory_frame_set_input_file_pos =
14032 tng_data->current_trajectory_frame_set_output_file_pos;
14034 tng_data->input_file = tng_data->output_file;
14036 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14038 frame_set = &tng_data->current_trajectory_frame_set;
14040 if(stat != TNG_SUCCESS)
14042 last_frame = frame_set->first_frame +
14043 frame_set->n_frames - 1;
14044 /* If the wanted frame would be in the frame set after the last
14045 * frame set create a new frame set. */
14046 if(stat == TNG_FAILURE &&
14047 last_frame < frame_nr)
14048 /* (last_frame < frame_nr &&
14049 tng_data->current_trajectory_frame_set.first_frame +
14050 tng_data->frame_set_n_frames >= frame_nr))*/
14052 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14054 last_frame = frame_nr - 1;
14056 tng_frame_set_new(tng_data,
14058 tng_data->frame_set_n_frames);
14059 file_pos = ftell(tng_data->output_file);
14060 fseek(tng_data->output_file, 0, SEEK_END);
14061 output_file_len = ftell(tng_data->output_file);
14062 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14064 /* Read mapping blocks from the last frame set */
14065 tng_block_init(&block);
14067 stat = tng_block_header_read(tng_data, block);
14068 while(file_pos < output_file_len &&
14069 stat != TNG_CRITICAL &&
14070 block->id != TNG_TRAJECTORY_FRAME_SET &&
14073 if(block->id == TNG_PARTICLE_MAPPING)
14075 tng_trajectory_mapping_block_read(tng_data, block,
14080 fseek(tng_data->output_file, (long)block->block_contents_size,
14083 file_pos = ftell(tng_data->output_file);
14084 if(file_pos < output_file_len)
14086 stat = tng_block_header_read(tng_data, block);
14090 tng_block_destroy(&block);
14091 /* Write the frame set to disk */
14092 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14094 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14095 return(TNG_CRITICAL);
14100 tng_data->input_file = temp;
14101 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14102 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14103 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14108 tng_block_init(&block);
14110 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14112 fseek(tng_data->output_file, 0, SEEK_END);
14113 output_file_len = ftell(tng_data->output_file);
14114 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14116 /* Read past the frame set block first */
14117 stat = tng_block_header_read(tng_data, block);
14118 if(stat == TNG_CRITICAL)
14120 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14121 file_pos, __FILE__, __LINE__);
14122 tng_block_destroy(&block);
14123 tng_data->input_file = temp;
14125 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14126 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14127 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14130 fseek(tng_data->output_file, (long)block->block_contents_size,
14133 /* Read all block headers until next frame set block or
14134 * until the wanted block id is found */
14135 stat = tng_block_header_read(tng_data, block);
14136 while(file_pos < output_file_len &&
14137 stat != TNG_CRITICAL &&
14138 block->id != block_id &&
14139 block->id != TNG_TRAJECTORY_FRAME_SET &&
14142 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
14143 file_pos = ftell(tng_data->output_file);
14144 if(file_pos < output_file_len)
14146 stat = tng_block_header_read(tng_data, block);
14149 if(stat == TNG_CRITICAL)
14151 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14152 file_pos, __FILE__, __LINE__);
14153 tng_block_destroy(&block);
14154 tng_data->input_file = temp;
14155 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14156 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14157 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14161 contents_size = block->block_contents_size;
14162 header_size = block->header_contents_size;
14164 header_pos = ftell(tng_data->output_file) - header_size;
14165 frame_set = &tng_data->current_trajectory_frame_set;
14167 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14169 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14170 tng_block_destroy(&block);
14171 return(TNG_CRITICAL);
14173 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14175 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14176 tng_block_destroy(&block);
14177 return(TNG_CRITICAL);
14179 data.datatype = datatype;
14181 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14182 (dependency & TNG_PARTICLE_DEPENDENT))
14184 tng_block_destroy(&block);
14185 tng_data->input_file = temp;
14187 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14188 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14189 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14190 return(TNG_FAILURE);
14193 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14195 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14196 tng_block_destroy(&block);
14197 return(TNG_CRITICAL);
14200 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14201 tng_data->input_file) == 0)
14203 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14204 tng_block_destroy(&block);
14205 return(TNG_CRITICAL);
14207 if(tng_data->output_endianness_swap_func_64)
14209 if(tng_data->output_endianness_swap_func_64(tng_data,
14210 &data.n_values_per_frame)
14213 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14214 __FILE__, __LINE__);
14218 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14219 tng_data->input_file) == 0)
14221 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14222 tng_block_destroy(&block);
14223 return(TNG_CRITICAL);
14225 if(tng_data->output_endianness_swap_func_64)
14227 if(tng_data->output_endianness_swap_func_64(tng_data,
14231 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14232 __FILE__, __LINE__);
14236 if(data.codec_id != TNG_UNCOMPRESSED)
14238 if(fread(&data.compression_multiplier,
14239 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14242 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14243 tng_block_destroy(&block);
14244 return(TNG_CRITICAL);
14246 if(tng_data->output_endianness_swap_func_64)
14248 if(tng_data->output_endianness_swap_func_64(tng_data,
14249 (int64_t *)&data.compression_multiplier)
14252 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14253 __FILE__, __LINE__);
14259 data.compression_multiplier = 1;
14264 if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
14265 1, tng_data->input_file) == 0)
14267 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14268 tng_block_destroy(&block);
14269 return(TNG_CRITICAL);
14271 if(tng_data->output_endianness_swap_func_64)
14273 if(tng_data->output_endianness_swap_func_64(tng_data,
14274 &data.first_frame_with_data)
14277 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14278 __FILE__, __LINE__);
14282 if(fread(&data.stride_length, sizeof(data.stride_length),
14283 1, tng_data->input_file) == 0)
14285 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14286 tng_block_destroy(&block);
14287 return(TNG_CRITICAL);
14289 if(tng_data->output_endianness_swap_func_64)
14291 if(tng_data->output_endianness_swap_func_64(tng_data,
14292 &data.stride_length)
14295 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14296 __FILE__, __LINE__);
14302 data.first_frame_with_data = 0;
14303 data.stride_length = 1;
14305 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14307 tng_data->input_file = temp;
14309 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14310 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14311 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14313 switch(data.datatype)
14315 case(TNG_INT_DATA):
14316 size = sizeof(int64_t);
14318 case(TNG_FLOAT_DATA):
14319 size = sizeof(float);
14321 case(TNG_DOUBLE_DATA):
14322 size = sizeof(double);
14325 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14327 tng_block_destroy(&block);
14328 return(TNG_FAILURE);
14331 n_values_per_frame = data.n_values_per_frame;
14333 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14334 data.first_frame_with_data)) /
14335 data.stride_length;
14336 file_pos *= size * n_values_per_frame;
14338 if(file_pos > contents_size)
14340 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14342 tng_block_destroy(&block);
14343 return(TNG_FAILURE);
14346 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14348 /* If the endianness is not big endian the data needs to be swapped */
14349 if((data.datatype == TNG_INT_DATA ||
14350 data.datatype == TNG_DOUBLE_DATA) &&
14351 tng_data->output_endianness_swap_func_64)
14353 copy = malloc(n_values_per_frame * size);
14354 memcpy(copy, values, n_values_per_frame * size);
14355 for(i = 0; i < n_values_per_frame; i++)
14357 if(tng_data->output_endianness_swap_func_64(tng_data,
14361 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14362 __FILE__, __LINE__);
14365 fwrite(copy, n_values_per_frame, size,
14366 tng_data->output_file);
14369 else if(data.datatype == TNG_FLOAT_DATA &&
14370 tng_data->output_endianness_swap_func_32)
14372 copy = malloc(n_values_per_frame * size);
14373 memcpy(copy, values, n_values_per_frame * size);
14374 for(i = 0; i < n_values_per_frame; i++)
14376 if(tng_data->output_endianness_swap_func_32(tng_data,
14380 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14381 __FILE__, __LINE__);
14384 fwrite(copy, n_values_per_frame, size,
14385 tng_data->output_file);
14391 fwrite(values, n_values_per_frame, size, tng_data->output_file);
14394 fflush(tng_data->output_file);
14396 /* Update the number of written frames in the frame set. */
14397 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14399 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14402 /* If the last frame has been written update the hash */
14403 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14404 data.first_frame_with_data) >=
14405 frame_set->n_frames)
14407 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14411 tng_block_destroy(&block);
14413 return(TNG_SUCCESS);
14416 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14417 (tng_trajectory_t tng_data,
14418 const int64_t frame_nr,
14419 const int64_t block_id,
14420 const int64_t val_first_particle,
14421 const int64_t val_n_particles,
14422 const void *values,
14423 const char hash_mode)
14425 int64_t header_pos, file_pos, tot_n_particles;
14426 int64_t output_file_len, n_values_per_frame, size, contents_size;
14427 int64_t header_size, temp_first, temp_last;
14428 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
14429 int64_t i, last_frame;
14431 tng_gen_block_t block;
14432 tng_trajectory_frame_set_t frame_set;
14433 FILE *temp = tng_data->input_file;
14434 struct tng_particle_data data;
14435 tng_function_status stat;
14436 tng_particle_mapping_t mapping;
14437 char dependency, sparse_data, datatype;
14440 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14441 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
14442 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
14443 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
14444 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
14446 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
14448 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
14449 __FILE__, __LINE__);
14450 return(TNG_CRITICAL);
14453 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
14454 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
14455 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
14456 tng_data->first_trajectory_frame_set_input_file_pos =
14457 tng_data->first_trajectory_frame_set_output_file_pos;
14458 tng_data->last_trajectory_frame_set_input_file_pos =
14459 tng_data->last_trajectory_frame_set_output_file_pos;
14460 tng_data->current_trajectory_frame_set_input_file_pos =
14461 tng_data->current_trajectory_frame_set_output_file_pos;
14463 tng_data->input_file = tng_data->output_file;
14465 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
14467 frame_set = &tng_data->current_trajectory_frame_set;
14469 if(stat != TNG_SUCCESS)
14471 last_frame = frame_set->first_frame +
14472 frame_set->n_frames - 1;
14473 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14475 /* If the wanted frame would be in the frame set after the last
14476 * frame set create a new frame set. */
14477 if(stat == TNG_FAILURE &&
14478 (last_frame < frame_nr &&
14479 last_frame + tng_data->frame_set_n_frames >= frame_nr))
14481 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
14483 last_frame = frame_nr - 1;
14485 tng_frame_set_new(tng_data,
14487 tng_data->frame_set_n_frames);
14489 file_pos = ftell(tng_data->output_file);
14490 fseek(tng_data->output_file, 0, SEEK_END);
14491 output_file_len = ftell(tng_data->output_file);
14492 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14494 /* Read mapping blocks from the last frame set */
14495 tng_block_init(&block);
14497 stat = tng_block_header_read(tng_data, block);
14498 while(file_pos < output_file_len &&
14499 stat != TNG_CRITICAL &&
14500 block->id != TNG_TRAJECTORY_FRAME_SET &&
14503 if(block->id == TNG_PARTICLE_MAPPING)
14505 tng_trajectory_mapping_block_read(tng_data, block,
14510 fseek(tng_data->output_file, (long)block->block_contents_size,
14513 file_pos = ftell(tng_data->output_file);
14514 if(file_pos < output_file_len)
14516 stat = tng_block_header_read(tng_data, block);
14520 tng_block_destroy(&block);
14521 /* Write the frame set to disk */
14522 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
14524 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
14530 tng_data->input_file = temp;
14531 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14532 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14533 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14539 tng_block_init(&block);
14541 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
14543 fseek(tng_data->output_file, 0, SEEK_END);
14544 output_file_len = ftell(tng_data->output_file);
14545 fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
14547 /* Read past the frame set block first */
14548 stat = tng_block_header_read(tng_data, block);
14549 if(stat == TNG_CRITICAL)
14551 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14552 file_pos, __FILE__, __LINE__);
14553 tng_block_destroy(&block);
14554 tng_data->input_file = temp;
14556 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14557 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14558 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14561 fseek(tng_data->output_file, (long)block->block_contents_size,
14564 if(tng_data->var_num_atoms_flag)
14566 tot_n_particles = frame_set->n_particles;
14570 tot_n_particles = tng_data->n_particles;
14573 if(val_n_particles < tot_n_particles)
14575 mapping_block_end_pos = -1;
14576 /* Read all mapping blocks to find the right place to put the data */
14577 stat = tng_block_header_read(tng_data, block);
14578 while(file_pos < output_file_len &&
14579 stat != TNG_CRITICAL &&
14580 block->id != TNG_TRAJECTORY_FRAME_SET &&
14583 if(block->id == TNG_PARTICLE_MAPPING)
14585 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14589 fseek(tng_data->output_file, (long)block->block_contents_size,
14592 file_pos = ftell(tng_data->output_file);
14593 if(block->id == TNG_PARTICLE_MAPPING)
14595 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
14596 if(val_first_particle >= mapping->num_first_particle &&
14597 val_first_particle < mapping->num_first_particle +
14598 mapping->n_particles &&
14599 val_first_particle + val_n_particles <=
14600 mapping->num_first_particle + mapping->n_particles)
14602 mapping_block_end_pos = file_pos;
14605 if(file_pos < output_file_len)
14607 stat = tng_block_header_read(tng_data, block);
14610 if(stat == TNG_CRITICAL)
14612 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14613 file_pos, __FILE__, __LINE__);
14614 tng_block_destroy(&block);
14615 tng_data->input_file = temp;
14617 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14618 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14619 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14622 if(mapping_block_end_pos < 0)
14624 tng_block_destroy(&block);
14625 tng_data->input_file = temp;
14627 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14628 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14629 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14630 return(TNG_FAILURE);
14632 fseek(tng_data->output_file, (long)mapping_block_end_pos, SEEK_SET);
14635 /* Read all block headers until next frame set block or
14636 * until the wanted block id is found */
14637 stat = tng_block_header_read(tng_data, block);
14638 while(file_pos < output_file_len &&
14639 stat != TNG_CRITICAL &&
14640 block->id != block_id &&
14641 block->id != TNG_PARTICLE_MAPPING &&
14642 block->id != TNG_TRAJECTORY_FRAME_SET &&
14645 fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
14646 file_pos = ftell(tng_data->output_file);
14647 if(file_pos < output_file_len)
14649 stat = tng_block_header_read(tng_data, block);
14652 if(stat == TNG_CRITICAL)
14654 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14655 file_pos, __FILE__, __LINE__);
14656 tng_block_destroy(&block);
14657 tng_data->input_file = temp;
14659 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14660 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14661 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14665 contents_size = block->block_contents_size;
14666 header_size = block->header_contents_size;
14668 header_pos = ftell(tng_data->output_file) - header_size;
14669 frame_set = &tng_data->current_trajectory_frame_set;
14671 if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
14673 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14674 tng_block_destroy(&block);
14675 return(TNG_CRITICAL);
14678 data.datatype = datatype;
14680 if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
14682 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14683 tng_block_destroy(&block);
14684 return(TNG_CRITICAL);
14687 if(!(dependency & TNG_FRAME_DEPENDENT) ||
14688 !(dependency & TNG_PARTICLE_DEPENDENT))
14690 tng_block_destroy(&block);
14691 tng_data->input_file = temp;
14693 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14694 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14695 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14696 return(TNG_FAILURE);
14699 if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
14701 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14702 tng_block_destroy(&block);
14703 return(TNG_CRITICAL);
14706 if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
14707 tng_data->input_file) == 0)
14709 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14710 tng_block_destroy(&block);
14711 return(TNG_CRITICAL);
14713 if(tng_data->output_endianness_swap_func_64)
14715 if(tng_data->output_endianness_swap_func_64(tng_data,
14716 &data.n_values_per_frame)
14719 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14720 __FILE__, __LINE__);
14724 if(fread(&data.codec_id, sizeof(data.codec_id), 1,
14725 tng_data->input_file) == 0)
14727 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14728 tng_block_destroy(&block);
14729 return(TNG_CRITICAL);
14731 if(tng_data->output_endianness_swap_func_64)
14733 if(tng_data->output_endianness_swap_func_64(tng_data,
14737 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14738 __FILE__, __LINE__);
14742 if(data.codec_id != TNG_UNCOMPRESSED)
14744 if(fread(&data.compression_multiplier,
14745 sizeof(data.compression_multiplier), 1, tng_data->input_file)
14748 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14749 tng_block_destroy(&block);
14750 return(TNG_CRITICAL);
14753 if(tng_data->output_endianness_swap_func_64)
14755 if(tng_data->output_endianness_swap_func_64(tng_data,
14756 (int64_t *)&data.compression_multiplier)
14759 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14760 __FILE__, __LINE__);
14766 data.compression_multiplier = 1;
14771 if(fread(&data.first_frame_with_data,
14772 sizeof(data.first_frame_with_data),
14773 1, tng_data->input_file) == 0)
14775 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14776 tng_block_destroy(&block);
14777 return(TNG_CRITICAL);
14779 if(tng_data->output_endianness_swap_func_64)
14781 if(tng_data->output_endianness_swap_func_64(tng_data,
14782 &data.first_frame_with_data)
14785 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14786 __FILE__, __LINE__);
14790 if(fread(&data.stride_length, sizeof(data.stride_length),
14791 1, tng_data->input_file) == 0)
14793 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14794 tng_block_destroy(&block);
14795 return(TNG_CRITICAL);
14797 if(tng_data->output_endianness_swap_func_64)
14799 if(tng_data->output_endianness_swap_func_64(tng_data,
14800 &data.stride_length)
14803 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14804 __FILE__, __LINE__);
14810 data.first_frame_with_data = 0;
14811 data.stride_length = 1;
14813 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
14815 if(fread(&num_first_particle, sizeof(num_first_particle), 1,
14816 tng_data->input_file) == 0)
14818 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14819 tng_block_destroy(&block);
14820 return(TNG_CRITICAL);
14822 if(tng_data->output_endianness_swap_func_64)
14824 if(tng_data->output_endianness_swap_func_64(tng_data,
14825 &num_first_particle)
14828 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14829 __FILE__, __LINE__);
14833 if(fread(&block_n_particles, sizeof(block_n_particles), 1,
14834 tng_data->input_file) == 0)
14836 fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
14837 tng_block_destroy(&block);
14838 return(TNG_CRITICAL);
14840 if(tng_data->output_endianness_swap_func_64)
14842 if(tng_data->output_endianness_swap_func_64(tng_data,
14843 &block_n_particles)
14846 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14847 __FILE__, __LINE__);
14852 tng_data->input_file = temp;
14854 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
14855 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
14856 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
14859 switch(data.datatype)
14861 case(TNG_INT_DATA):
14862 size = sizeof(int64_t);
14864 case(TNG_FLOAT_DATA):
14865 size = sizeof(float);
14867 case(TNG_DOUBLE_DATA):
14868 size = sizeof(double);
14871 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14873 tng_block_destroy(&block);
14874 return(TNG_FAILURE);
14877 n_values_per_frame = data.n_values_per_frame;
14879 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
14880 data.first_frame_with_data)) /
14881 data.stride_length;
14882 file_pos *= block_n_particles * size * n_values_per_frame;
14884 if(file_pos > contents_size)
14886 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
14888 tng_block_destroy(&block);
14889 return(TNG_FAILURE);
14892 fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
14894 /* If the endianness is not big endian the data needs to be swapped */
14895 if((data.datatype == TNG_INT_DATA ||
14896 data.datatype == TNG_DOUBLE_DATA) &&
14897 tng_data->output_endianness_swap_func_64)
14899 copy = malloc(val_n_particles * n_values_per_frame * size);
14900 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14901 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14903 if(tng_data->output_endianness_swap_func_64(tng_data,
14904 (int64_t *) copy+i)
14907 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14908 __FILE__, __LINE__);
14911 fwrite(copy, val_n_particles * n_values_per_frame, size,
14912 tng_data->output_file);
14915 else if(data.datatype == TNG_FLOAT_DATA &&
14916 tng_data->output_endianness_swap_func_32)
14918 copy = malloc(val_n_particles * n_values_per_frame * size);
14919 memcpy(copy, values, val_n_particles * n_values_per_frame * size);
14920 for(i = 0; i < val_n_particles * n_values_per_frame; i++)
14922 if(tng_data->output_endianness_swap_func_32(tng_data,
14923 (int32_t *) copy+i)
14926 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14927 __FILE__, __LINE__);
14930 fwrite(copy, val_n_particles * n_values_per_frame, size,
14931 tng_data->output_file);
14937 fwrite(values, val_n_particles * n_values_per_frame, size,
14938 tng_data->output_file);
14940 fflush(tng_data->output_file);
14942 /* Update the number of written frames in the frame set. */
14943 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
14945 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
14948 /* If the last frame has been written update the hash */
14949 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
14950 data.first_frame_with_data) >=
14951 frame_set->n_frames)
14953 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
14957 tng_block_destroy(&block);
14958 return(TNG_SUCCESS);
14961 static tng_function_status tng_data_values_alloc
14962 (const tng_trajectory_t tng_data,
14963 union data_values ***values,
14964 const int64_t n_frames,
14965 const int64_t n_values_per_frame,
14969 tng_function_status stat;
14971 if(n_frames <= 0 || n_values_per_frame <= 0)
14973 return(TNG_FAILURE);
14978 stat = tng_data_values_free(tng_data, *values, n_frames,
14979 n_values_per_frame,
14981 if(stat != TNG_SUCCESS)
14983 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
14984 __FILE__, __LINE__);
14988 *values = malloc(sizeof(union data_values *) * n_frames);
14991 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14992 sizeof(union data_values **) * n_frames,
14993 __FILE__, __LINE__);
14994 return(TNG_CRITICAL);
14998 for(i = 0; i < n_frames; i++)
15000 (*values)[i] = malloc(sizeof(union data_values) *
15001 n_values_per_frame);
15004 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15005 sizeof(union data_values) * n_values_per_frame,
15006 __FILE__, __LINE__);
15009 return(TNG_CRITICAL);
15012 return(TNG_SUCCESS);
15015 /* FIXME: This needs ***values */
15016 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15017 (const tng_trajectory_t tng_data,
15018 union data_values **values,
15019 const int64_t n_frames,
15020 const int64_t n_values_per_frame,
15028 for(i = 0; i < n_frames; i++)
15032 if(type == TNG_CHAR_DATA)
15034 for(j = 0; j < n_values_per_frame; j++)
15038 free(values[i][j].c);
15039 values[i][j].c = 0;
15051 return(TNG_SUCCESS);
15054 static tng_function_status tng_particle_data_values_alloc
15055 (const tng_trajectory_t tng_data,
15056 union data_values ****values,
15057 const int64_t n_frames,
15058 const int64_t n_particles,
15059 const int64_t n_values_per_frame,
15063 tng_function_status stat;
15065 if(n_particles == 0 || n_values_per_frame == 0)
15067 return(TNG_FAILURE);
15072 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15073 n_particles, n_values_per_frame,
15075 if(stat != TNG_SUCCESS)
15077 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15078 __FILE__, __LINE__);
15082 *values = malloc(sizeof(union data_values **) * n_frames);
15085 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15086 sizeof(union data_values **) * n_frames,
15087 __FILE__, __LINE__);
15088 return(TNG_CRITICAL);
15092 for(i = 0; i < n_frames; i++)
15094 (*values)[i] = malloc(sizeof(union data_values *) *
15098 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15099 sizeof(union data_values *) * n_particles,
15100 __FILE__, __LINE__);
15103 return(TNG_CRITICAL);
15105 for(j = 0; j < n_particles; j++)
15107 (*values)[i][j] = malloc(sizeof(union data_values) *
15108 n_values_per_frame);
15109 if(!(*values)[i][j])
15111 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15112 sizeof(union data_values *) * n_particles,
15113 __FILE__, __LINE__);
15114 tng_particle_data_values_free(tng_data, *values, n_frames,
15115 n_particles, n_values_per_frame,
15118 return(TNG_CRITICAL);
15122 return(TNG_SUCCESS);
15125 /* FIXME: This needs ****values */
15126 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15127 (const tng_trajectory_t tng_data,
15128 union data_values ***values,
15129 const int64_t n_frames,
15130 const int64_t n_particles,
15131 const int64_t n_values_per_frame,
15139 for(i = 0; i < n_frames; i++)
15143 for(j = 0; j < n_particles; j++)
15145 if(type == TNG_CHAR_DATA)
15147 for(k = 0; k < n_values_per_frame; k++)
15149 if(values[i][j][k].c)
15151 free(values[i][j][k].c);
15152 values[i][j][k].c = 0;
15156 free(values[i][j]);
15167 return(TNG_SUCCESS);
15171 tng_function_status DECLSPECDLLEXPORT tng_data_get
15172 (tng_trajectory_t tng_data,
15173 const int64_t block_id,
15174 union data_values ***values,
15176 int64_t *n_values_per_frame,
15179 int64_t i, j, file_pos, block_index;
15182 tng_non_particle_data_t data;
15183 tng_trajectory_frame_set_t frame_set;
15184 tng_gen_block_t block;
15185 tng_function_status stat;
15187 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15188 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15189 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15190 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15192 frame_set = &tng_data->current_trajectory_frame_set;
15197 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15199 tng_block_init(&block);
15200 file_pos = ftell(tng_data->input_file);
15201 /* Read all blocks until next frame set block */
15202 stat = tng_block_header_read(tng_data, block);
15203 while(file_pos < tng_data->input_file_len &&
15204 stat != TNG_CRITICAL &&
15205 block->id != TNG_TRAJECTORY_FRAME_SET &&
15208 /* Use hash by default */
15209 stat = tng_block_read_next(tng_data, block,
15211 if(stat != TNG_CRITICAL)
15213 file_pos = ftell(tng_data->input_file);
15214 if(file_pos < tng_data->input_file_len)
15216 stat = tng_block_header_read(tng_data, block);
15220 tng_block_destroy(&block);
15221 if(stat == TNG_CRITICAL)
15223 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15224 file_pos, __FILE__, __LINE__);
15228 for(i = 0; i < frame_set->n_data_blocks; i++)
15230 data = &frame_set->tr_data[i];
15231 if(data->block_id == block_id)
15237 if(block_index < 0)
15239 return(TNG_FAILURE);
15243 *n_frames = tng_max_i64(1, data->n_frames);
15244 *n_values_per_frame = data->n_values_per_frame;
15245 *type = data->datatype;
15249 if(tng_data_values_alloc(tng_data, values, *n_frames,
15250 *n_values_per_frame,
15254 return(TNG_CRITICAL);
15260 case TNG_CHAR_DATA:
15261 for(i = 0; i < *n_frames; i++)
15263 for(j = 0; j < *n_values_per_frame; j++)
15265 len = strlen(data->strings[i][j]) + 1;
15266 (*values)[i][j].c = malloc(len);
15267 strncpy((*values)[i][j].c, data->strings[i][j], len);
15272 size = sizeof(int);
15273 for(i = 0; i < *n_frames; i++)
15275 for(j = 0; j < *n_values_per_frame; j++)
15277 (*values)[i][j].i = *(int *)((char *)data->values + size *
15278 (i*(*n_values_per_frame) + j));
15282 case TNG_FLOAT_DATA:
15283 size = sizeof(float);
15284 for(i = 0; i < *n_frames; i++)
15286 for(j = 0; j < *n_values_per_frame; j++)
15288 (*values)[i][j].f = *(float *)((char *)data->values + size *
15289 (i*(*n_values_per_frame) + j));
15293 case TNG_DOUBLE_DATA:
15295 size = sizeof(double);
15296 for(i = 0; i < *n_frames; i++)
15298 for(j = 0; j < *n_values_per_frame; j++)
15300 (*values)[i][j].d = *(double *)((char *)data->values + size *
15301 (i*(*n_values_per_frame) + j));
15306 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15308 return(TNG_SUCCESS);
15311 tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
15312 const int64_t block_id,
15315 int64_t *stride_length,
15316 int64_t *n_values_per_frame,
15319 int64_t file_pos, data_size, n_frames_div, block_index;
15321 tng_non_particle_data_t data;
15322 tng_trajectory_frame_set_t frame_set;
15323 tng_gen_block_t block;
15325 tng_function_status stat;
15327 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15328 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15329 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15330 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15331 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15333 frame_set = &tng_data->current_trajectory_frame_set;
15338 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15340 tng_block_init(&block);
15341 file_pos = ftell(tng_data->input_file);
15342 /* Read all blocks until next frame set block */
15343 stat = tng_block_header_read(tng_data, block);
15344 while(file_pos < tng_data->input_file_len &&
15345 stat != TNG_CRITICAL &&
15346 block->id != TNG_TRAJECTORY_FRAME_SET &&
15349 /* Use hash by default */
15350 stat = tng_block_read_next(tng_data, block,
15352 if(stat != TNG_CRITICAL)
15354 file_pos = ftell(tng_data->input_file);
15355 if(file_pos < tng_data->input_file_len)
15357 stat = tng_block_header_read(tng_data, block);
15361 tng_block_destroy(&block);
15362 if(stat == TNG_CRITICAL)
15364 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15365 file_pos, __FILE__, __LINE__);
15369 for(i = 0; i < frame_set->n_data_blocks; i++)
15371 data = &frame_set->tr_data[i];
15372 if(data->block_id == block_id)
15378 if(block_index < 0)
15380 return(TNG_FAILURE);
15384 *type = data->datatype;
15388 case TNG_CHAR_DATA:
15389 return(TNG_FAILURE);
15391 size = sizeof(int64_t);
15393 case TNG_FLOAT_DATA:
15394 size = sizeof(float);
15396 case TNG_DOUBLE_DATA:
15398 size = sizeof(double);
15401 *n_frames = data->n_frames;
15402 *n_values_per_frame = data->n_values_per_frame;
15403 *stride_length = data->stride_length;
15404 n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
15405 *n_frames / *stride_length;
15407 data_size = n_frames_div * size *
15408 *n_values_per_frame;
15410 temp = realloc(*values, data_size);
15413 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15414 data_size, __FILE__, __LINE__);
15417 return(TNG_CRITICAL);
15422 memcpy(*values, data->values, data_size);
15424 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
15426 return(TNG_SUCCESS);
15429 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15430 (tng_trajectory_t tng_data,
15431 const int64_t block_id,
15432 const int64_t start_frame_nr,
15433 const int64_t end_frame_nr,
15434 const char hash_mode,
15435 union data_values ***values,
15436 int64_t *n_values_per_frame,
15439 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15440 int64_t block_index;
15443 tng_non_particle_data_t data;
15444 tng_trajectory_frame_set_t frame_set;
15445 tng_gen_block_t block;
15446 tng_function_status stat;
15448 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15449 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15450 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15451 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15455 frame_set = &tng_data->current_trajectory_frame_set;
15456 first_frame = frame_set->first_frame;
15458 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15459 if(stat != TNG_SUCCESS)
15465 /* Do not re-read the frame set. */
15466 if(first_frame != frame_set->first_frame ||
15467 frame_set->n_data_blocks <= 0)
15469 tng_block_init(&block);
15470 file_pos = ftell(tng_data->input_file);
15471 /* Read all blocks until next frame set block */
15472 stat = tng_block_header_read(tng_data, block);
15473 while(file_pos < tng_data->input_file_len &&
15474 stat != TNG_CRITICAL &&
15475 block->id != TNG_TRAJECTORY_FRAME_SET &&
15478 stat = tng_block_read_next(tng_data, block,
15480 if(stat != TNG_CRITICAL)
15482 file_pos = ftell(tng_data->input_file);
15483 if(file_pos < tng_data->input_file_len)
15485 stat = tng_block_header_read(tng_data, block);
15489 tng_block_destroy(&block);
15490 if(stat == TNG_CRITICAL)
15492 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15493 file_pos, __FILE__, __LINE__);
15499 /* See if there is a data block of this ID.
15500 * Start checking the last read frame set */
15501 for(i = 0; i < frame_set->n_data_blocks; i++)
15503 data = &frame_set->tr_data[i];
15504 if(data->block_id == block_id)
15511 if(block_index < 0)
15513 fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
15514 block_id, __FILE__, __LINE__);
15515 return(TNG_FAILURE);
15518 n_frames = end_frame_nr - start_frame_nr + 1;
15519 *n_values_per_frame = data->n_values_per_frame;
15520 *type = data->datatype;
15524 if(tng_data_values_alloc(tng_data, values, n_frames,
15525 *n_values_per_frame,
15526 *type) != TNG_SUCCESS)
15528 return(TNG_CRITICAL);
15532 current_frame_pos = start_frame_nr - frame_set->first_frame;
15533 /* It's not very elegant to reuse so much of the code in the different case
15534 * statements, but it's unnecessarily slow to have the switch-case block
15535 * inside the for loops. */
15538 case TNG_CHAR_DATA:
15539 for(i=0; i<n_frames; i++)
15541 if(current_frame_pos == frame_set->n_frames)
15543 stat = tng_frame_set_read_next(tng_data, hash_mode);
15544 if(stat != TNG_SUCCESS)
15548 current_frame_pos = 0;
15550 for(j = 0; j < *n_values_per_frame; j++)
15552 len = strlen(data->strings[current_frame_pos][j]) + 1;
15553 (*values)[i][j].c = malloc(len);
15554 strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
15556 current_frame_pos++;
15560 size = sizeof(int);
15561 for(i=0; i<n_frames; i++)
15563 if(current_frame_pos == frame_set->n_frames)
15565 stat = tng_frame_set_read_next(tng_data, hash_mode);
15566 if(stat != TNG_SUCCESS)
15570 current_frame_pos = 0;
15572 for(j = 0; j < *n_values_per_frame; j++)
15574 (*values)[i][j].i = *(int *)((char *)data->values + size *
15575 (current_frame_pos *
15576 (*n_values_per_frame) + j));
15578 current_frame_pos++;
15581 case TNG_FLOAT_DATA:
15582 size = sizeof(float);
15583 for(i=0; i<n_frames; i++)
15585 if(current_frame_pos == frame_set->n_frames)
15587 stat = tng_frame_set_read_next(tng_data, hash_mode);
15588 if(stat != TNG_SUCCESS)
15592 current_frame_pos = 0;
15594 for(j = 0; j < *n_values_per_frame; j++)
15596 (*values)[i][j].f = *(float *)((char *)data->values + size *
15597 (current_frame_pos *
15598 (*n_values_per_frame) + j));
15600 current_frame_pos++;
15603 case TNG_DOUBLE_DATA:
15605 size = sizeof(double);
15606 for(i=0; i<n_frames; i++)
15608 if(current_frame_pos == frame_set->n_frames)
15610 stat = tng_frame_set_read_next(tng_data, hash_mode);
15611 if(stat != TNG_SUCCESS)
15615 current_frame_pos = 0;
15617 for(j = 0; j < *n_values_per_frame; j++)
15619 (*values)[i][j].d = *(double *)((char *)data->values + size *
15620 (current_frame_pos *
15621 (*n_values_per_frame) + j));
15623 current_frame_pos++;
15627 data->last_retrieved_frame = end_frame_nr;
15629 return(TNG_SUCCESS);
15632 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15633 (tng_trajectory_t tng_data,
15634 const int64_t block_id,
15635 const int64_t start_frame_nr,
15636 const int64_t end_frame_nr,
15637 const char hash_mode,
15639 int64_t *stride_length,
15640 int64_t *n_values_per_frame,
15643 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
15644 int64_t file_pos, current_frame_pos, data_size, frame_size;
15645 int64_t last_frame_pos;
15647 tng_trajectory_frame_set_t frame_set;
15648 tng_non_particle_data_t np_data;
15649 tng_gen_block_t block;
15650 void *current_values = 0, *temp;
15651 tng_function_status stat;
15653 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15654 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15655 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15656 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15657 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15659 frame_set = &tng_data->current_trajectory_frame_set;
15660 first_frame = frame_set->first_frame;
15662 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
15663 if(stat != TNG_SUCCESS)
15668 /* Do not re-read the frame set and only need the requested block. */
15669 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15670 stat = tng_data_find(tng_data, block_id, &np_data);
15671 if(first_frame != frame_set->first_frame ||
15672 stat != TNG_SUCCESS)
15674 tng_block_init(&block);
15675 if(stat != TNG_SUCCESS)
15677 fseek(tng_data->input_file,
15678 (long)tng_data->current_trajectory_frame_set_input_file_pos,
15680 stat = tng_block_header_read(tng_data, block);
15681 if(stat != TNG_SUCCESS)
15683 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
15684 __FILE__, __LINE__);
15688 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15690 file_pos = ftell(tng_data->input_file);
15691 /* Read until next frame set block */
15692 stat = tng_block_header_read(tng_data, block);
15693 while(file_pos < tng_data->input_file_len &&
15694 stat != TNG_CRITICAL &&
15695 block->id != TNG_TRAJECTORY_FRAME_SET &&
15698 if(block->id == block_id)
15700 stat = tng_block_read_next(tng_data, block,
15702 if(stat != TNG_CRITICAL)
15704 file_pos = ftell(tng_data->input_file);
15705 if(file_pos < tng_data->input_file_len)
15707 stat = tng_block_header_read(tng_data, block);
15713 file_pos += block->block_contents_size + block->header_contents_size;
15714 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
15715 if(file_pos < tng_data->input_file_len)
15717 stat = tng_block_header_read(tng_data, block);
15721 tng_block_destroy(&block);
15722 if(stat == TNG_CRITICAL)
15724 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15725 file_pos, __FILE__, __LINE__);
15730 stat = tng_data_find(tng_data, block_id, &np_data);
15731 if(stat != TNG_SUCCESS)
15736 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15737 &n_frames, stride_length,
15738 n_values_per_frame, type);
15740 if(stat != TNG_SUCCESS)
15744 free(current_values);
15749 if(n_frames == 1 && n_frames < frame_set->n_frames)
15755 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15760 case TNG_CHAR_DATA:
15761 return(TNG_FAILURE);
15763 size = sizeof(int64_t);
15765 case TNG_FLOAT_DATA:
15766 size = sizeof(float);
15768 case TNG_DOUBLE_DATA:
15770 size = sizeof(double);
15773 n_frames_div = (tot_n_frames % *stride_length) ?
15774 tot_n_frames / *stride_length + 1:
15775 tot_n_frames / *stride_length;
15776 data_size = n_frames_div * size * (*n_values_per_frame);
15778 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15779 size, n_frames_div, data_size);
15781 temp = realloc(*values, data_size);
15784 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15785 data_size, __FILE__, __LINE__);
15788 return(TNG_CRITICAL);
15793 if( n_frames == 1 && n_frames < frame_set->n_frames)
15795 memcpy(*values, current_values, size * (*n_values_per_frame));
15799 current_frame_pos = start_frame_nr - frame_set->first_frame;
15801 frame_size = size * (*n_values_per_frame);
15803 last_frame_pos = tng_min_i64(n_frames,
15804 end_frame_nr - start_frame_nr);
15806 n_frames_div = current_frame_pos / *stride_length;
15807 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15808 last_frame_pos / *stride_length + 1:
15809 last_frame_pos / *stride_length;
15810 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15812 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
15813 n_frames_div_2 * frame_size);
15815 current_frame_pos += n_frames - current_frame_pos;
15817 while(current_frame_pos <= end_frame_nr - start_frame_nr)
15819 stat = tng_frame_set_read_next(tng_data, hash_mode);
15820 if(stat != TNG_SUCCESS)
15824 free(current_values);
15831 stat = tng_data_vector_get(tng_data, block_id, ¤t_values,
15832 &n_frames, stride_length,
15833 n_values_per_frame, type);
15835 if(stat != TNG_SUCCESS)
15839 free(current_values);
15846 last_frame_pos = tng_min_i64(n_frames,
15847 end_frame_nr - current_frame_pos);
15849 n_frames_div = current_frame_pos / *stride_length;
15850 n_frames_div_2 = (last_frame_pos % *stride_length) ?
15851 last_frame_pos / *stride_length + 1:
15852 last_frame_pos / *stride_length;
15853 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
15855 memcpy(((char *)*values) + n_frames_div * frame_size,
15857 n_frames_div_2 * frame_size);
15859 current_frame_pos += n_frames;
15865 free(current_values);
15868 np_data->last_retrieved_frame = end_frame_nr;
15870 return(TNG_SUCCESS);
15873 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15874 (tng_trajectory_t tng_data,
15875 const int64_t block_id,
15876 union data_values ****values,
15878 int64_t *n_particles,
15879 int64_t *n_values_per_frame,
15882 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15885 tng_particle_data_t data;
15886 tng_trajectory_frame_set_t frame_set;
15887 tng_gen_block_t block;
15888 char block_type_flag;
15889 tng_function_status stat;
15891 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15892 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15893 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15894 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15895 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15897 frame_set = &tng_data->current_trajectory_frame_set;
15902 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
15904 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15906 block_type_flag = TNG_TRAJECTORY_BLOCK;
15910 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15913 tng_block_init(&block);
15914 file_pos = ftell(tng_data->input_file);
15915 /* Read all blocks until next frame set block */
15916 stat = tng_block_header_read(tng_data, block);
15917 while(file_pos < tng_data->input_file_len &&
15918 stat != TNG_CRITICAL &&
15919 block->id != TNG_TRAJECTORY_FRAME_SET &&
15922 /* Use hash by default */
15923 stat = tng_block_read_next(tng_data, block,
15925 if(stat != TNG_CRITICAL)
15927 file_pos = ftell(tng_data->input_file);
15928 if(file_pos < tng_data->input_file_len)
15930 stat = tng_block_header_read(tng_data, block);
15934 tng_block_destroy(&block);
15935 if(stat == TNG_CRITICAL)
15937 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
15938 file_pos, __FILE__, __LINE__);
15942 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
15944 data = &frame_set->tr_particle_data[i];
15945 if(data->block_id == block_id)
15948 block_type_flag = TNG_TRAJECTORY_BLOCK;
15952 if(block_index < 0)
15954 return(TNG_FAILURE);
15959 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
15961 block_type_flag = TNG_TRAJECTORY_BLOCK;
15965 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
15969 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
15970 tng_data->var_num_atoms_flag)
15972 *n_particles = frame_set->n_particles;
15976 *n_particles = tng_data->n_particles;
15979 *n_frames = tng_max_i64(1, data->n_frames);
15980 *n_values_per_frame = data->n_values_per_frame;
15981 *type = data->datatype;
15985 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
15986 *n_particles, *n_values_per_frame,
15990 return(TNG_CRITICAL);
15994 /* It's not very elegant to reuse so much of the code in the different case
15995 * statements, but it's unnecessarily slow to have the switch-case block
15996 * inside the for loops. */
15999 case TNG_CHAR_DATA:
16000 for(i = 0; i < *n_frames; i++)
16002 for(j = 0; j < *n_particles; j++)
16004 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16005 for(k = 0; k < *n_values_per_frame; k++)
16007 len = strlen(data->strings[i][j][k]) + 1;
16008 (*values)[i][mapping][k].c = malloc(len);
16009 strncpy((*values)[i][mapping][k].c,
16010 data->strings[i][j][k], len);
16016 size = sizeof(int);
16017 i_step = (*n_particles) * (*n_values_per_frame);
16018 for(i = 0; i < *n_frames; i++)
16020 for(j = 0; j < *n_particles; j++)
16022 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16023 for(k = 0; k < *n_values_per_frame; k++)
16025 (*values)[i][mapping][k].i = *(int *)
16026 ((char *)data->values + size *
16028 (*n_values_per_frame) + k));
16033 case TNG_FLOAT_DATA:
16034 size = sizeof(float);
16035 i_step = (*n_particles) * (*n_values_per_frame);
16036 for(i = 0; i < *n_frames; i++)
16038 for(j = 0; j < *n_particles; j++)
16040 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16041 for(k = 0; k < *n_values_per_frame; k++)
16043 (*values)[i][mapping][k].f = *(float *)
16044 ((char *)data->values + size *
16046 (*n_values_per_frame) + k));
16051 case TNG_DOUBLE_DATA:
16053 size = sizeof(double);
16054 i_step = (*n_particles) * (*n_values_per_frame);
16055 for(i = 0; i < *n_frames; i++)
16057 for(j = 0; j < *n_particles; j++)
16059 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16060 for(k = 0; k < *n_values_per_frame; k++)
16062 (*values)[i][mapping][k].d = *(double *)
16063 ((char *)data->values + size *
16065 (*n_values_per_frame) + k));
16071 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16073 return(TNG_SUCCESS);
16076 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16077 (tng_trajectory_t tng_data,
16078 const int64_t block_id,
16081 int64_t *stride_length,
16082 int64_t *n_particles,
16083 int64_t *n_values_per_frame,
16086 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16087 int64_t block_index;
16089 tng_particle_data_t data;
16090 tng_trajectory_frame_set_t frame_set;
16091 tng_gen_block_t block;
16093 char block_type_flag;
16094 tng_function_status stat;
16096 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16097 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16098 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16099 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16100 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16102 frame_set = &tng_data->current_trajectory_frame_set;
16107 if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16109 tng_block_init(&block);
16110 file_pos = ftell(tng_data->input_file);
16111 /* Read all blocks until next frame set block */
16112 stat = tng_block_header_read(tng_data, block);
16113 while(file_pos < tng_data->input_file_len &&
16114 stat != TNG_CRITICAL &&
16115 block->id != TNG_TRAJECTORY_FRAME_SET &&
16118 /* Use hash by default */
16119 stat = tng_block_read_next(tng_data, block,
16121 if(stat != TNG_CRITICAL)
16123 file_pos = ftell(tng_data->input_file);
16124 if(file_pos < tng_data->input_file_len)
16126 stat = tng_block_header_read(tng_data, block);
16130 tng_block_destroy(&block);
16131 if(stat == TNG_CRITICAL)
16133 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16134 file_pos, __FILE__, __LINE__);
16138 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
16140 data = &frame_set->tr_particle_data[i];
16141 if(data->block_id == block_id)
16147 if(block_index < 0)
16149 return(TNG_FAILURE);
16153 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16155 block_type_flag = TNG_TRAJECTORY_BLOCK;
16159 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16162 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16163 tng_data->var_num_atoms_flag)
16165 *n_particles = frame_set->n_particles;
16169 *n_particles = tng_data->n_particles;
16172 *type = data->datatype;
16176 case TNG_CHAR_DATA:
16177 return(TNG_FAILURE);
16179 size = sizeof(int64_t);
16181 case TNG_FLOAT_DATA:
16182 size = sizeof(float);
16184 case TNG_DOUBLE_DATA:
16186 size = sizeof(double);
16189 *n_frames = tng_max_i64(1, data->n_frames);
16190 *n_values_per_frame = data->n_values_per_frame;
16191 *stride_length = data->stride_length;
16193 n_frames_div = (*n_frames % *stride_length) ?
16194 *n_frames / *stride_length + 1:
16195 *n_frames / *stride_length;
16197 data_size = n_frames_div * size * (*n_particles) *
16198 (*n_values_per_frame);
16200 temp = realloc(*values, data_size);
16203 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16204 data_size, __FILE__, __LINE__);
16207 return(TNG_CRITICAL);
16212 if(frame_set->n_mapping_blocks <= 0)
16214 memcpy(*values, data->values, data_size);
16218 i_step = (*n_particles) * (*n_values_per_frame);
16219 for(i = 0; i < *n_frames; i++)
16221 for(j = 0; j < *n_particles; j++)
16223 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16224 memcpy(((char *)*values) + size * (i * i_step + mapping *
16225 (*n_values_per_frame)),
16226 (char *)data->values + size *
16227 (i * i_step + j * (*n_values_per_frame)),
16228 size * (*n_values_per_frame));
16233 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
16235 return(TNG_SUCCESS);
16238 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16239 (tng_trajectory_t tng_data,
16240 const int64_t block_id,
16241 const int64_t start_frame_nr,
16242 const int64_t end_frame_nr,
16243 const char hash_mode,
16244 union data_values ****values,
16245 int64_t *n_particles,
16246 int64_t *n_values_per_frame,
16249 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16250 int64_t first_frame, block_index;
16253 tng_particle_data_t data;
16254 tng_trajectory_frame_set_t frame_set;
16255 tng_gen_block_t block;
16256 char block_type_flag;
16257 tng_function_status stat;
16259 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16260 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16261 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16262 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16263 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16267 frame_set = &tng_data->current_trajectory_frame_set;
16268 first_frame = frame_set->first_frame;
16270 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16271 if(stat != TNG_SUCCESS)
16276 /* Do not re-read the frame set. */
16277 if(first_frame != frame_set->first_frame ||
16278 frame_set->n_particle_data_blocks <= 0)
16280 tng_block_init(&block);
16281 file_pos = ftell(tng_data->input_file);
16282 /* Read all blocks until next frame set block */
16283 stat = tng_block_header_read(tng_data, block);
16284 while(file_pos < tng_data->input_file_len &&
16285 stat != TNG_CRITICAL &&
16286 block->id != TNG_TRAJECTORY_FRAME_SET &&
16289 stat = tng_block_read_next(tng_data, block,
16291 if(stat != TNG_CRITICAL)
16293 file_pos = ftell(tng_data->input_file);
16294 if(file_pos < tng_data->input_file_len)
16296 stat = tng_block_header_read(tng_data, block);
16300 tng_block_destroy(&block);
16301 if(stat == TNG_CRITICAL)
16303 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16304 file_pos, __FILE__, __LINE__);
16309 /* See if there is already a data block of this ID.
16310 * Start checking the last read frame set */
16311 for(i = frame_set->n_particle_data_blocks; i-- ;)
16313 data = &frame_set->tr_particle_data[i];
16314 if(data->block_id == block_id)
16317 block_type_flag = TNG_TRAJECTORY_BLOCK;
16322 if(block_index < 0)
16324 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
16325 block_id, __FILE__, __LINE__);
16326 return(TNG_FAILURE);
16329 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
16330 tng_data->var_num_atoms_flag)
16332 *n_particles = frame_set->n_particles;
16336 *n_particles = tng_data->n_particles;
16339 n_frames = end_frame_nr - start_frame_nr + 1;
16340 *n_values_per_frame = data->n_values_per_frame;
16341 *type = data->datatype;
16345 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16346 *n_particles, *n_values_per_frame,
16350 return(TNG_CRITICAL);
16354 current_frame_pos = start_frame_nr - frame_set->first_frame;
16355 /* It's not very elegant to reuse so much of the code in the different case
16356 * statements, but it's unnecessarily slow to have the switch-case block
16357 * inside the for loops. */
16360 case TNG_CHAR_DATA:
16361 for(i=0; i<n_frames; i++)
16363 if(current_frame_pos == frame_set->n_frames)
16365 stat = tng_frame_set_read_next(tng_data, hash_mode);
16366 if(stat != TNG_SUCCESS)
16370 current_frame_pos = 0;
16372 for(j = 0; j < *n_particles; j++)
16374 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16375 for(k = 0; k < *n_values_per_frame; k++)
16377 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
16378 (*values)[i][mapping][k].c = malloc(len);
16379 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
16382 current_frame_pos++;
16386 size = sizeof(int);
16387 i_step = (*n_particles) * (*n_values_per_frame);
16388 for(i=0; i<n_frames; i++)
16390 if(current_frame_pos == frame_set->n_frames)
16392 stat = tng_frame_set_read_next(tng_data, hash_mode);
16393 if(stat != TNG_SUCCESS)
16397 current_frame_pos = 0;
16399 for(j = 0; j < *n_particles; j++)
16401 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16402 for(k = 0; k < *n_values_per_frame; k++)
16404 (*values)[i][mapping][k].i = *(int *)
16405 ((char *)data->values + size *
16406 (current_frame_pos *
16408 (*n_values_per_frame) + k));
16411 current_frame_pos++;
16414 case TNG_FLOAT_DATA:
16415 size = sizeof(float);
16416 i_step = (*n_particles) * (*n_values_per_frame);
16417 for(i=0; i<n_frames; i++)
16419 if(current_frame_pos == frame_set->n_frames)
16421 stat = tng_frame_set_read_next(tng_data, hash_mode);
16422 if(stat != TNG_SUCCESS)
16426 current_frame_pos = 0;
16428 for(j=0; j<*n_particles; j++)
16430 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16431 for(k=0; k<*n_values_per_frame; k++)
16433 (*values)[i][mapping][k].f = *(float *)
16434 ((char *)data->values + size *
16435 (current_frame_pos *
16437 (*n_values_per_frame) + k));
16440 current_frame_pos++;
16443 case TNG_DOUBLE_DATA:
16445 size = sizeof(double);
16446 i_step = (*n_particles) * (*n_values_per_frame);
16447 for(i=0; i<n_frames; i++)
16449 if(current_frame_pos == frame_set->n_frames)
16451 stat = tng_frame_set_read_next(tng_data, hash_mode);
16452 if(stat != TNG_SUCCESS)
16456 current_frame_pos = 0;
16458 for(j=0; j<*n_particles; j++)
16460 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
16461 for(k=0; k<*n_values_per_frame; k++)
16463 (*values)[i][mapping][k].d = *(double *)
16464 ((char *)data->values + size *
16465 (current_frame_pos *
16467 (*n_values_per_frame) + k));
16470 current_frame_pos++;
16474 data->last_retrieved_frame = end_frame_nr;
16476 return(TNG_SUCCESS);
16479 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16480 (tng_trajectory_t tng_data,
16481 const int64_t block_id,
16482 const int64_t start_frame_nr,
16483 const int64_t end_frame_nr,
16484 const char hash_mode,
16486 int64_t *n_particles,
16487 int64_t *stride_length,
16488 int64_t *n_values_per_frame,
16491 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
16492 int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
16494 tng_trajectory_frame_set_t frame_set;
16495 tng_particle_data_t p_data;
16496 tng_gen_block_t block;
16497 void *current_values = 0, *temp;
16498 tng_function_status stat;
16500 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16501 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16502 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
16503 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
16504 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
16505 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
16507 frame_set = &tng_data->current_trajectory_frame_set;
16508 first_frame = frame_set->first_frame;
16510 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
16511 if(stat != TNG_SUCCESS)
16516 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16517 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16518 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16519 if(first_frame != frame_set->first_frame ||
16520 stat != TNG_SUCCESS)
16522 tng_block_init(&block);
16523 if(stat != TNG_SUCCESS)
16525 fseek(tng_data->input_file,
16526 (long)tng_data->current_trajectory_frame_set_input_file_pos,
16528 stat = tng_block_header_read(tng_data, block);
16529 if(stat != TNG_SUCCESS)
16531 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
16532 __FILE__, __LINE__);
16536 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
16538 file_pos = ftell(tng_data->input_file);
16539 /* Read until next frame set block */
16540 stat = tng_block_header_read(tng_data, block);
16541 while(file_pos < tng_data->input_file_len &&
16542 stat != TNG_CRITICAL &&
16543 block->id != TNG_TRAJECTORY_FRAME_SET &&
16546 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16548 stat = tng_block_read_next(tng_data, block,
16550 if(stat != TNG_CRITICAL)
16552 file_pos = ftell(tng_data->input_file);
16553 if(file_pos < tng_data->input_file_len)
16555 stat = tng_block_header_read(tng_data, block);
16561 file_pos += block->block_contents_size + block->header_contents_size;
16562 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
16563 if(file_pos < tng_data->input_file_len)
16565 stat = tng_block_header_read(tng_data, block);
16569 tng_block_destroy(&block);
16570 if(stat == TNG_CRITICAL)
16572 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
16573 file_pos, __FILE__, __LINE__);
16577 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16578 if(stat != TNG_SUCCESS)
16583 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16584 &n_frames, stride_length, n_particles,
16585 n_values_per_frame, type);
16587 if(stat != TNG_SUCCESS || *n_particles == 0)
16591 free(current_values);
16596 if(n_frames == 1 && n_frames < frame_set->n_frames)
16602 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16607 case TNG_CHAR_DATA:
16608 return(TNG_FAILURE);
16610 size = sizeof(int64_t);
16612 case TNG_FLOAT_DATA:
16613 size = sizeof(float);
16615 case TNG_DOUBLE_DATA:
16617 size = sizeof(double);
16620 n_frames_div = (tot_n_frames % *stride_length) ?
16621 tot_n_frames / *stride_length + 1:
16622 tot_n_frames / *stride_length;
16624 data_size = n_frames_div * size * (*n_particles) *
16625 (*n_values_per_frame);
16627 temp = realloc(*values, data_size);
16630 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16631 data_size, __FILE__, __LINE__);
16634 return(TNG_CRITICAL);
16639 if( n_frames == 1 && n_frames < frame_set->n_frames)
16641 memcpy(*values, current_values, size * (*n_particles) *
16642 (*n_values_per_frame));
16646 current_frame_pos = start_frame_nr - frame_set->first_frame;
16648 frame_size = size * (*n_particles) * (*n_values_per_frame);
16650 last_frame_pos = tng_min_i64(n_frames,
16651 end_frame_nr - start_frame_nr);
16653 n_frames_div = current_frame_pos / *stride_length;
16654 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16655 last_frame_pos / *stride_length + 1:
16656 last_frame_pos / *stride_length;
16657 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
16659 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
16660 n_frames_div_2 * frame_size);
16662 current_frame_pos += n_frames - current_frame_pos;
16664 while(current_frame_pos <= end_frame_nr - start_frame_nr)
16666 stat = tng_frame_set_read_next(tng_data, hash_mode);
16667 if(stat != TNG_SUCCESS)
16671 free(current_values);
16678 stat = tng_particle_data_vector_get(tng_data, block_id, ¤t_values,
16679 &n_frames, stride_length, n_particles,
16680 n_values_per_frame, type);
16682 if(stat != TNG_SUCCESS)
16686 free(current_values);
16693 last_frame_pos = tng_min_i64(n_frames,
16694 end_frame_nr - current_frame_pos);
16696 n_frames_div = current_frame_pos / *stride_length;
16697 n_frames_div_2 = (last_frame_pos % *stride_length) ?
16698 last_frame_pos / *stride_length + 1:
16699 last_frame_pos / *stride_length;
16700 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
16702 memcpy(((char *)*values) + n_frames_div * frame_size,
16704 n_frames_div_2 * frame_size);
16706 current_frame_pos += n_frames;
16712 free(current_values);
16715 p_data->last_retrieved_frame = end_frame_nr;
16717 return(TNG_SUCCESS);
16720 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16721 (const tng_trajectory_t tng_data,
16722 const int64_t block_id,
16724 int64_t *stride_length)
16726 tng_function_status stat;
16727 tng_non_particle_data_t np_data;
16728 tng_particle_data_t p_data;
16729 long orig_file_pos, file_pos;
16730 int is_particle_data;
16732 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
16739 stat = tng_frame_set_of_frame_find(tng_data, frame);
16740 if(stat != TNG_SUCCESS)
16745 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
16746 stat = tng_data_find(tng_data, block_id, &np_data);
16747 if(stat != TNG_SUCCESS)
16749 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16750 if(stat != TNG_SUCCESS)
16752 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16753 /* If no specific frame was required read until this data block is found */
16756 file_pos = ftell(tng_data->input_file);
16757 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
16759 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
16760 file_pos = ftell(tng_data->input_file);
16763 if(stat != TNG_SUCCESS)
16765 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16769 stat = tng_data_find(tng_data, block_id, &np_data);
16770 if(stat != TNG_SUCCESS)
16772 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16773 if(stat != TNG_SUCCESS)
16775 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16781 is_particle_data = 1;
16786 is_particle_data = 0;
16791 is_particle_data = 1;
16796 is_particle_data = 0;
16798 if(is_particle_data)
16800 *stride_length = p_data->stride_length;
16804 *stride_length = np_data->stride_length;
16806 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
16808 return(TNG_SUCCESS);
16811 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16812 (const tng_trajectory_t tng_data,
16815 struct tm *time_data;
16818 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16819 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16821 secs = tng_data->time;
16823 time_data = localtime(&secs); /* Returns a statically allocated variable. */
16824 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
16825 "%4d-%02d-%02d %02d:%02d:%02d",
16826 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
16827 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
16829 return(TNG_SUCCESS);
16833 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16834 (const char *filename,
16836 tng_trajectory_t *tng_data_p)
16838 tng_function_status stat;
16840 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
16842 if(mode != 'r' && mode != 'w' && mode != 'a')
16844 return(TNG_FAILURE);
16847 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
16849 tng_trajectory_destroy(tng_data_p);
16850 return(TNG_CRITICAL);
16853 if(mode == 'r' || mode == 'a')
16855 tng_input_file_set(*tng_data_p, filename);
16857 /* Read the file headers */
16858 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
16860 tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
16865 tng_output_file_set(*tng_data_p, filename);
16867 else if(mode == 'a')
16869 if((*tng_data_p)->output_file)
16871 fclose((*tng_data_p)->output_file);
16873 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
16874 fseek((*tng_data_p)->input_file,
16875 (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
16878 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
16879 if(stat != TNG_SUCCESS)
16881 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16882 __FILE__, __LINE__);
16884 (*tng_data_p)->output_file = 0;
16886 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
16887 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
16888 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
16889 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
16890 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
16891 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
16892 if((*tng_data_p)->input_file)
16894 fclose((*tng_data_p)->input_file);
16895 (*tng_data_p)->input_file = 0;
16897 if((*tng_data_p)->input_file_path)
16899 free((*tng_data_p)->input_file_path);
16900 (*tng_data_p)->input_file_path = 0;
16902 tng_output_append_file_set(*tng_data_p, filename);
16904 fseek((*tng_data_p)->output_file, 0, SEEK_END);
16907 return(TNG_SUCCESS);
16910 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
16911 (tng_trajectory_t *tng_data_p)
16913 tng_trajectory_frame_set_t frame_set;
16915 if(tng_data_p == 0)
16917 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
16918 __FILE__, __LINE__);
16919 return(TNG_FAILURE);
16922 if(*tng_data_p == 0)
16924 return(TNG_SUCCESS);
16927 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
16929 if(frame_set->n_unwritten_frames > 0)
16931 frame_set->n_frames = frame_set->n_unwritten_frames;
16932 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
16935 return(tng_trajectory_destroy(tng_data_p));
16938 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
16939 (tng_trajectory_t tng_data,
16940 const int64_t frame_nr,
16943 int64_t first_frame;
16944 tng_trajectory_frame_set_t frame_set;
16945 tng_function_status stat;
16947 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16948 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
16950 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
16951 if(stat != TNG_SUCCESS)
16953 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
16954 frame_nr, __FILE__, __LINE__);
16958 frame_set = &tng_data->current_trajectory_frame_set;
16959 first_frame = frame_set->first_frame;
16961 if(tng_data->time_per_frame <= 0)
16963 return(TNG_FAILURE);
16966 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
16968 return(TNG_SUCCESS);
16972 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
16973 (tng_trajectory_t tng_data,
16975 int64_t **molecule_cnt_list,
16976 tng_molecule_t *mols)
16978 tng_trajectory_frame_set_t frame_set;
16980 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16981 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
16983 *n_mols = tng_data->n_molecules;
16985 frame_set = &tng_data->current_trajectory_frame_set;
16986 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
16988 *molecule_cnt_list = frame_set->molecule_cnt_list;
16992 *molecule_cnt_list = tng_data->molecule_cnt_list;
16995 *mols = tng_data->molecules;
16997 return(TNG_SUCCESS);
17001 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17002 (tng_trajectory_t tng_data,
17005 tng_molecule_t *mol)
17007 tng_function_status stat;
17009 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17010 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17012 stat = tng_molecule_add(tng_data, name, mol);
17013 if(stat != TNG_SUCCESS)
17017 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17022 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17023 (tng_trajectory_t tng_data,
17024 const tng_molecule_t mol,
17025 int64_t *n_particles,
17030 char ***chain_names,
17031 int64_t **chain_ids)
17039 *n_particles = mol->n_atoms;
17041 *names = malloc(sizeof(char *) * *n_particles);
17042 *types = malloc(sizeof(char *) * *n_particles);
17043 *res_names = malloc(sizeof(char *) * *n_particles);
17044 *chain_names = malloc(sizeof(char *) * *n_particles);
17045 *res_ids = malloc(sizeof(int64_t) * *n_particles);
17046 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
17048 for(i = 0; i < *n_particles; i++)
17050 atom = &mol->atoms[i];
17051 res = atom->residue;
17052 chain = res->chain;
17053 (*names)[i] = malloc(strlen(atom->name));
17054 strcpy(*names[i], atom->name);
17055 (*types)[i] = malloc(strlen(atom->atom_type));
17056 strcpy(*types[i], atom->atom_type);
17057 (*res_names)[i] = malloc(strlen(res->name));
17058 strcpy(*res_names[i], res->name);
17059 (*chain_names)[i] = malloc(strlen(chain->name));
17060 strcpy(*chain_names[i], chain->name);
17061 (*res_ids)[i] = res->id;
17062 (*chain_ids)[i] = chain->id;
17065 return(TNG_SUCCESS);
17068 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17069 (tng_trajectory_t tng_data,
17070 tng_molecule_t mol,
17071 const int64_t n_particles,
17072 const char **names,
17073 const char **types,
17074 const char **res_names,
17075 const int64_t *res_ids,
17076 const char **chain_names,
17077 const int64_t *chain_ids)
17081 tng_residue_t residue;
17083 tng_function_status stat;
17085 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17086 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
17087 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
17088 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
17089 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
17090 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
17091 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
17093 for(i = 0; i < n_particles; i++)
17095 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
17096 &chain) == TNG_FAILURE)
17098 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
17100 if(stat != TNG_SUCCESS)
17105 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
17106 &residue) == TNG_FAILURE)
17108 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
17110 if(stat != TNG_SUCCESS)
17115 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17116 if(stat != TNG_SUCCESS)
17121 return(TNG_SUCCESS);
17124 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17125 (tng_trajectory_t tng_data,
17126 float **positions, int64_t *stride_length)
17128 int64_t n_frames, n_particles, n_values_per_frame;
17130 tng_function_status stat;
17132 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17133 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17134 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17136 stat = tng_num_frames_get(tng_data, &n_frames);
17137 if(stat != TNG_SUCCESS)
17142 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17143 0, n_frames - 1, TNG_USE_HASH,
17144 (void **)positions,
17147 &n_values_per_frame,
17153 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17154 (tng_trajectory_t tng_data,
17155 float **velocities, int64_t *stride_length)
17157 int64_t n_frames, n_particles, n_values_per_frame;
17159 tng_function_status stat;
17161 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17162 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17163 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17165 stat = tng_num_frames_get(tng_data, &n_frames);
17166 if(stat != TNG_SUCCESS)
17171 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17172 0, n_frames - 1, TNG_USE_HASH,
17173 (void **)velocities,
17176 &n_values_per_frame,
17182 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17183 (tng_trajectory_t tng_data,
17184 float **forces, int64_t *stride_length)
17186 int64_t n_frames, n_particles, n_values_per_frame;
17188 tng_function_status stat;
17190 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17191 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17192 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17194 stat = tng_num_frames_get(tng_data, &n_frames);
17195 if(stat != TNG_SUCCESS)
17200 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17201 0, n_frames - 1, TNG_USE_HASH,
17205 &n_values_per_frame,
17211 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17212 (tng_trajectory_t tng_data,
17214 int64_t *stride_length)
17216 int64_t n_frames, n_values_per_frame;
17218 tng_function_status stat;
17220 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17221 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17222 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17224 stat = tng_num_frames_get(tng_data, &n_frames);
17225 if(stat != TNG_SUCCESS)
17230 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17231 0, n_frames - 1, TNG_USE_HASH,
17232 (void **)box_shape,
17234 &n_values_per_frame,
17240 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17241 (tng_trajectory_t tng_data,
17242 const int64_t block_id,
17245 int64_t *retrieved_frame_number,
17246 double *retrieved_time)
17248 tng_trajectory_frame_set_t frame_set;
17249 tng_particle_data_t data = 0;
17250 tng_function_status stat;
17252 int64_t i, data_size, n_particles;
17256 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17257 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17258 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17259 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17260 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17262 frame_set = &tng_data->current_trajectory_frame_set;
17264 stat = tng_particle_data_find(tng_data, block_id, &data);
17265 if(stat != TNG_SUCCESS)
17267 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17268 file_pos = ftell(tng_data->input_file);
17269 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17271 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17272 file_pos = ftell(tng_data->input_file);
17274 if(stat != TNG_SUCCESS)
17278 stat = tng_particle_data_find(tng_data, block_id, &data);
17279 if(stat != TNG_SUCCESS)
17284 if(data->last_retrieved_frame < 0)
17286 fseek(tng_data->input_file,
17287 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17289 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17290 if(stat != TNG_SUCCESS)
17294 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17295 if(stat != TNG_SUCCESS)
17300 i = data->first_frame_with_data;
17304 if(data->n_frames == 1)
17306 i = data->last_retrieved_frame + 1;
17310 i = data->last_retrieved_frame + data->stride_length;
17312 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17314 stat = tng_frame_set_of_frame_find(tng_data, i);
17315 if(stat != TNG_SUCCESS)
17317 /* If the frame set search found the frame set after the starting
17318 * frame set there is a gap in the frame sets. So, even if the frame
17319 * was not found the next frame with data is still in the found
17321 if(stat == TNG_CRITICAL)
17325 i = frame_set->first_frame;
17328 if(data->last_retrieved_frame < frame_set->first_frame)
17330 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17331 if(stat != TNG_SUCCESS)
17337 data->last_retrieved_frame = i;
17338 *retrieved_frame_number = i;
17339 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17341 *retrieved_time = frame_set->first_frame_time +
17342 (i - frame_set->first_frame) *
17343 tng_data->time_per_frame;
17347 *retrieved_time = 0;
17350 if(data->stride_length > 1)
17352 i = (i - data->first_frame_with_data) / data->stride_length;
17356 i = (i - frame_set->first_frame);
17359 tng_num_particles_get(tng_data, &n_particles);
17361 *data_type = data->datatype;
17365 case TNG_CHAR_DATA:
17366 return(TNG_FAILURE);
17368 size = sizeof(int64_t);
17370 case TNG_FLOAT_DATA:
17371 size = sizeof(float);
17373 case TNG_DOUBLE_DATA:
17375 size = sizeof(double);
17378 data_size = size * n_particles * data->n_values_per_frame;
17380 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17381 // i, data_size, size, n_particles, data->n_values_per_frame);
17383 temp = realloc(*values, data_size);
17386 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17387 data_size, __FILE__, __LINE__);
17390 return(TNG_CRITICAL);
17395 memcpy(*values, (char *)data->values + i * data_size, data_size);
17397 return(TNG_SUCCESS);
17400 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17401 (tng_trajectory_t tng_data,
17402 const int64_t block_id,
17405 int64_t *retrieved_frame_number,
17406 double *retrieved_time)
17408 tng_trajectory_frame_set_t frame_set;
17409 tng_non_particle_data_t data = 0;
17410 tng_function_status stat;
17412 int64_t i, data_size;
17416 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17417 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
17418 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17419 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17420 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17422 frame_set = &tng_data->current_trajectory_frame_set;
17424 stat = tng_data_find(tng_data, block_id, &data);
17425 if(stat != TNG_SUCCESS)
17427 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17428 file_pos = ftell(tng_data->input_file);
17429 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
17431 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17432 file_pos = ftell(tng_data->input_file);
17434 if(stat != TNG_SUCCESS)
17438 stat = tng_data_find(tng_data, block_id, &data);
17439 if(stat != TNG_SUCCESS)
17444 if(data->last_retrieved_frame < 0)
17446 fseek(tng_data->input_file,
17447 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17449 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17450 if(stat != TNG_SUCCESS)
17454 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17455 if(stat != TNG_SUCCESS)
17460 i = data->first_frame_with_data;
17464 if(data->n_frames == 1)
17466 i = data->last_retrieved_frame + 1;
17470 i = data->last_retrieved_frame + data->stride_length;
17472 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17474 stat = tng_frame_set_of_frame_find(tng_data, i);
17475 if(stat != TNG_SUCCESS)
17477 /* If the frame set search found the frame set after the starting
17478 * frame set there is a gap in the frame sets. So, even if the frame
17479 * was not found the next frame with data is still in the found
17481 if(stat == TNG_CRITICAL)
17485 i = frame_set->first_frame;
17488 if(data->last_retrieved_frame < frame_set->first_frame)
17490 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17491 if(stat != TNG_SUCCESS)
17497 data->last_retrieved_frame = i;
17498 *retrieved_frame_number = i;
17499 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
17501 *retrieved_time = frame_set->first_frame_time +
17502 (i - frame_set->first_frame) *
17503 tng_data->time_per_frame;
17507 *retrieved_time = 0;
17510 if(data->stride_length > 1)
17512 i = (i - data->first_frame_with_data) / data->stride_length;
17516 i = (i - frame_set->first_frame);
17519 *data_type = data->datatype;
17523 case TNG_CHAR_DATA:
17524 return(TNG_FAILURE);
17526 size = sizeof(int64_t);
17528 case TNG_FLOAT_DATA:
17529 size = sizeof(float);
17531 case TNG_DOUBLE_DATA:
17533 size = sizeof(double);
17536 data_size = size * data->n_values_per_frame;
17538 temp = realloc(*values, data_size);
17541 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17542 data_size, __FILE__, __LINE__);
17545 return(TNG_CRITICAL);
17550 memcpy(*values, (char *)data->values + i * data_size, data_size);
17552 return(TNG_SUCCESS);
17555 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17556 (tng_trajectory_t tng_data,
17557 const int64_t first_frame,
17558 const int64_t last_frame,
17560 int64_t *stride_length)
17562 int64_t n_particles, n_values_per_frame;
17564 tng_function_status stat;
17566 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17567 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17568 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17569 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17571 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17572 first_frame, last_frame,
17574 (void **)positions,
17577 &n_values_per_frame,
17583 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17584 (tng_trajectory_t tng_data,
17585 const int64_t first_frame,
17586 const int64_t last_frame,
17587 float **velocities,
17588 int64_t *stride_length)
17590 int64_t n_particles, n_values_per_frame;
17592 tng_function_status stat;
17594 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17595 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17596 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17597 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17599 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17600 first_frame, last_frame,
17602 (void **)velocities,
17605 &n_values_per_frame,
17611 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17612 (tng_trajectory_t tng_data,
17613 const int64_t first_frame,
17614 const int64_t last_frame,
17616 int64_t *stride_length)
17618 int64_t n_particles, n_values_per_frame;
17620 tng_function_status stat;
17622 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17623 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17624 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17625 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17627 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17628 first_frame, last_frame,
17633 &n_values_per_frame,
17639 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17640 (tng_trajectory_t tng_data,
17641 const int64_t first_frame,
17642 const int64_t last_frame,
17644 int64_t *stride_length)
17646 int64_t n_values_per_frame;
17648 tng_function_status stat;
17650 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17651 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17652 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
17653 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
17655 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
17656 first_frame, last_frame,
17658 (void **)box_shape,
17660 &n_values_per_frame,
17666 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17667 (tng_trajectory_t tng_data,
17669 const int64_t n_values_per_frame,
17670 const int64_t block_id,
17671 const char *block_name,
17672 const char particle_dependency,
17673 const char compression)
17675 tng_trajectory_frame_set_t frame_set;
17676 tng_particle_data_t p_data;
17677 tng_non_particle_data_t np_data;
17678 int64_t n_particles, n_frames;
17679 tng_function_status stat;
17681 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17682 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17686 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17687 i, __FILE__, __LINE__);
17688 return(TNG_FAILURE);
17691 frame_set = &tng_data->current_trajectory_frame_set;
17693 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17695 n_frames = tng_data->frame_set_n_frames;
17697 stat = tng_frame_set_new(tng_data, 0, n_frames);
17698 if(stat != TNG_SUCCESS)
17700 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17707 n_frames = frame_set->n_frames;
17710 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17712 tng_num_particles_get(tng_data, &n_particles);
17713 if(n_particles <= 0)
17715 return(TNG_FAILURE);
17718 if(tng_particle_data_find(tng_data, block_id, &p_data)
17721 stat = tng_particle_data_block_add(tng_data, block_id,
17724 TNG_TRAJECTORY_BLOCK,
17725 n_frames, n_values_per_frame, i,
17728 if(stat != TNG_SUCCESS)
17730 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17731 __FILE__, __LINE__);
17734 p_data = &frame_set->tr_particle_data[frame_set->
17735 n_particle_data_blocks - 1];
17736 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17738 n_values_per_frame);
17739 if(stat != TNG_SUCCESS)
17741 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17742 __FILE__, __LINE__);
17748 if(p_data->stride_length != i)
17750 p_data->stride_length = i;
17751 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17753 n_values_per_frame);
17754 if(stat != TNG_SUCCESS)
17756 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17757 __FILE__, __LINE__);
17765 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17767 stat = tng_data_block_add(tng_data, block_id, block_name,
17768 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
17769 n_frames, n_values_per_frame,
17770 i, compression, 0);
17771 if(stat != TNG_SUCCESS)
17773 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17774 __FILE__, __LINE__);
17777 np_data = &frame_set->tr_data[frame_set->
17778 n_data_blocks - 1];
17779 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17780 i, n_values_per_frame);
17781 if(stat != TNG_SUCCESS)
17783 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17784 __FILE__, __LINE__);
17790 if(np_data->stride_length != i)
17792 np_data->stride_length = i;
17793 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17794 i, n_values_per_frame);
17795 if(stat != TNG_SUCCESS)
17797 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17798 __FILE__, __LINE__);
17805 return(TNG_SUCCESS);
17808 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17809 (tng_trajectory_t tng_data,
17811 const int64_t n_values_per_frame,
17812 const int64_t block_id,
17813 const char *block_name,
17814 const char particle_dependency,
17815 const char compression)
17817 tng_trajectory_frame_set_t frame_set;
17818 tng_particle_data_t p_data;
17819 tng_non_particle_data_t np_data;
17820 int64_t n_particles, n_frames;
17821 tng_function_status stat;
17823 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17824 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
17828 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
17829 i, __FILE__, __LINE__);
17830 return(TNG_FAILURE);
17833 frame_set = &tng_data->current_trajectory_frame_set;
17835 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
17837 n_frames = tng_data->frame_set_n_frames;
17839 stat = tng_frame_set_new(tng_data, 0, n_frames);
17840 if(stat != TNG_SUCCESS)
17842 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
17849 n_frames = frame_set->n_frames;
17852 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
17854 tng_num_particles_get(tng_data, &n_particles);
17856 if(n_particles <= 0)
17858 return(TNG_FAILURE);
17861 if(tng_particle_data_find(tng_data, block_id, &p_data)
17864 stat = tng_particle_data_block_add(tng_data, block_id,
17867 TNG_TRAJECTORY_BLOCK,
17868 n_frames, n_values_per_frame, i,
17871 if(stat != TNG_SUCCESS)
17873 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17874 __FILE__, __LINE__);
17877 p_data = &frame_set->tr_particle_data[frame_set->
17878 n_particle_data_blocks - 1];
17879 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
17881 n_values_per_frame);
17882 if(stat != TNG_SUCCESS)
17884 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17885 __FILE__, __LINE__);
17891 p_data->stride_length = i;
17896 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
17898 stat = tng_data_block_add(tng_data, block_id, block_name,
17899 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
17900 n_frames, n_values_per_frame,
17901 i, compression, 0);
17902 if(stat != TNG_SUCCESS)
17904 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17905 __FILE__, __LINE__);
17908 np_data = &frame_set->tr_data[frame_set->
17909 n_data_blocks - 1];
17910 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
17911 i, n_values_per_frame);
17912 if(stat != TNG_SUCCESS)
17914 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
17915 __FILE__, __LINE__);
17921 np_data->stride_length = i;
17925 return(TNG_SUCCESS);
17928 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
17929 (tng_trajectory_t tng_data,
17931 const int64_t n_values_per_frame,
17932 const int64_t block_id,
17933 const char *block_name,
17934 const char particle_dependency,
17935 const char compression)
17937 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
17938 "See documentation. %s: %d", __FILE__, __LINE__);
17939 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
17940 block_id, block_name,
17941 particle_dependency,
17944 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
17945 (tng_trajectory_t tng_data,
17948 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17949 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17951 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17952 TNG_TRAJ_POSITIONS,
17954 TNG_PARTICLE_BLOCK_DATA,
17955 TNG_TNG_COMPRESSION));
17958 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
17959 (tng_trajectory_t tng_data,
17962 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17963 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17965 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
17966 TNG_TRAJ_POSITIONS,
17968 TNG_PARTICLE_BLOCK_DATA,
17969 TNG_TNG_COMPRESSION));
17972 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
17973 (tng_trajectory_t tng_data,
17976 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
17977 "See documentation. %s: %d", __FILE__, __LINE__);
17978 return(tng_util_pos_write_interval_set(tng_data, i));
17981 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
17982 (tng_trajectory_t tng_data,
17985 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17986 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
17988 return(tng_util_generic_write_interval_set(tng_data, i, 3,
17989 TNG_TRAJ_VELOCITIES,
17991 TNG_PARTICLE_BLOCK_DATA,
17992 TNG_TNG_COMPRESSION));
17995 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
17996 (tng_trajectory_t tng_data,
17999 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18000 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18002 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18003 TNG_TRAJ_VELOCITIES,
18005 TNG_PARTICLE_BLOCK_DATA,
18006 TNG_TNG_COMPRESSION));
18009 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18010 (tng_trajectory_t tng_data,
18013 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18014 "See documentation. %s: %d", __FILE__, __LINE__);
18015 return(tng_util_vel_write_interval_set(tng_data, i));
18018 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18019 (tng_trajectory_t tng_data,
18022 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18023 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18025 return(tng_util_generic_write_interval_set(tng_data, i, 3,
18028 TNG_PARTICLE_BLOCK_DATA,
18029 TNG_GZIP_COMPRESSION));
18032 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18033 (tng_trajectory_t tng_data,
18036 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18037 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18039 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
18042 TNG_PARTICLE_BLOCK_DATA,
18043 TNG_GZIP_COMPRESSION));
18046 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18047 (tng_trajectory_t tng_data,
18050 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18051 "See documentation. %s: %d", __FILE__, __LINE__);
18052 return(tng_util_force_write_interval_set(tng_data, i));
18055 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18056 (tng_trajectory_t tng_data,
18059 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18060 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18062 return(tng_util_generic_write_interval_set(tng_data, i, 9,
18063 TNG_TRAJ_BOX_SHAPE,
18065 TNG_NON_PARTICLE_BLOCK_DATA,
18066 TNG_GZIP_COMPRESSION));
18069 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18070 (tng_trajectory_t tng_data,
18073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18074 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
18076 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
18077 TNG_TRAJ_BOX_SHAPE,
18079 TNG_NON_PARTICLE_BLOCK_DATA,
18080 TNG_GZIP_COMPRESSION));
18083 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18084 (tng_trajectory_t tng_data,
18087 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18088 "See documentation. %s: %d", __FILE__, __LINE__);
18089 return(tng_util_box_shape_write_interval_set(tng_data, i));
18092 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18093 (tng_trajectory_t tng_data,
18094 const int64_t frame_nr,
18095 const float *values,
18096 const int64_t n_values_per_frame,
18097 const int64_t block_id,
18098 const char *block_name,
18099 const char particle_dependency,
18100 const char compression)
18102 tng_trajectory_frame_set_t frame_set;
18103 tng_particle_data_t p_data;
18104 tng_non_particle_data_t np_data;
18105 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18106 int64_t last_frame;
18107 int is_first_frame_flag = 0;
18108 char block_type_flag;
18109 tng_function_status stat;
18111 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18112 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18113 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18115 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18117 tng_num_particles_get(tng_data, &n_particles);
18118 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18123 return(TNG_FAILURE);
18126 frame_set = &tng_data->current_trajectory_frame_set;
18130 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18131 n_frames = stride_length = 1;
18135 block_type_flag = TNG_TRAJECTORY_BLOCK;
18137 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18139 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
18140 if(stat != TNG_SUCCESS)
18142 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18147 last_frame = frame_set->first_frame +
18148 frame_set->n_frames - 1;
18149 if(frame_nr > last_frame)
18151 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18152 if(stat != TNG_SUCCESS)
18154 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18158 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18160 last_frame = frame_nr - 1;
18162 stat = tng_frame_set_new(tng_data, last_frame + 1,
18163 tng_data->frame_set_n_frames);
18164 if(stat != TNG_SUCCESS)
18166 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18171 if(frame_set->n_unwritten_frames == 0)
18173 is_first_frame_flag = 1;
18175 frame_set->n_unwritten_frames = frame_nr -
18176 frame_set->first_frame + 1;
18178 n_frames = frame_set->n_frames;
18181 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18183 if(tng_particle_data_find(tng_data, block_id, &p_data)
18186 stat = tng_particle_data_block_add(tng_data, block_id,
18190 n_frames, n_values_per_frame,
18194 if(stat != TNG_SUCCESS)
18196 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18197 __FILE__, __LINE__);
18200 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18202 p_data = &frame_set->tr_particle_data[frame_set->
18203 n_particle_data_blocks - 1];
18207 p_data = &tng_data->non_tr_particle_data[tng_data->
18208 n_particle_data_blocks - 1];
18210 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18211 stride_length, n_particles,
18212 n_values_per_frame);
18213 if(stat != TNG_SUCCESS)
18215 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18216 __FILE__, __LINE__);
18221 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18223 stride_length = p_data->stride_length;
18225 if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
18227 p_data->first_frame_with_data = frame_nr;
18232 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18235 memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
18236 n_values_per_frame, values, sizeof(float) *
18237 n_particles * n_values_per_frame);
18241 memcpy(p_data->values, values, sizeof(float) * n_particles *
18242 n_values_per_frame);
18247 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18249 stat = tng_data_block_add(tng_data, block_id, block_name,
18250 TNG_FLOAT_DATA, block_type_flag,
18251 n_frames, n_values_per_frame,
18252 stride_length, compression, 0);
18253 if(stat != TNG_SUCCESS)
18255 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18256 __FILE__, __LINE__);
18259 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18261 np_data = &frame_set->tr_data[frame_set->
18262 n_data_blocks - 1];
18266 np_data = &tng_data->non_tr_data[tng_data->
18267 n_data_blocks - 1];
18269 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18270 stride_length, n_values_per_frame);
18271 if(stat != TNG_SUCCESS)
18273 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18274 __FILE__, __LINE__);
18279 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18281 stride_length = np_data->stride_length;
18283 if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
18285 np_data->first_frame_with_data = frame_nr;
18290 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18293 memcpy((char *)np_data->values + sizeof(float) * frame_pos *
18294 n_values_per_frame, values, sizeof(float) *
18295 n_values_per_frame);
18299 memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
18303 return(TNG_SUCCESS);
18306 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18307 (tng_trajectory_t tng_data,
18308 const int64_t frame_nr,
18309 const double *values,
18310 const int64_t n_values_per_frame,
18311 const int64_t block_id,
18312 const char *block_name,
18313 const char particle_dependency,
18314 const char compression)
18316 tng_trajectory_frame_set_t frame_set;
18317 tng_particle_data_t p_data;
18318 tng_non_particle_data_t np_data;
18319 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
18320 int64_t last_frame;
18321 int is_first_frame_flag = 0;
18322 char block_type_flag;
18323 tng_function_status stat;
18325 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18326 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18327 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18329 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18331 tng_num_particles_get(tng_data, &n_particles);
18332 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
18337 return(TNG_FAILURE);
18340 frame_set = &tng_data->current_trajectory_frame_set;
18344 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18345 n_frames = stride_length = 1;
18349 block_type_flag = TNG_TRAJECTORY_BLOCK;
18351 n_frames = tng_data->frame_set_n_frames;
18353 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
18355 stat = tng_frame_set_new(tng_data, 0, n_frames);
18356 if(stat != TNG_SUCCESS)
18358 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18365 n_frames = frame_set->n_frames;
18367 last_frame = frame_set->first_frame +
18368 frame_set->n_frames - 1;
18369 if(frame_nr > last_frame)
18371 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
18372 if(stat != TNG_SUCCESS)
18374 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
18378 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
18380 last_frame = frame_nr - 1;
18382 stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
18383 if(stat != TNG_SUCCESS)
18385 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
18390 if(frame_set->n_unwritten_frames == 0)
18392 is_first_frame_flag = 1;
18394 frame_set->n_unwritten_frames = frame_nr -
18395 frame_set->first_frame + 1;
18398 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
18400 if(tng_particle_data_find(tng_data, block_id, &p_data)
18403 stat = tng_particle_data_block_add(tng_data, block_id,
18407 n_frames, n_values_per_frame,
18411 if(stat != TNG_SUCCESS)
18413 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18414 __FILE__, __LINE__);
18417 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18419 p_data = &frame_set->tr_particle_data[frame_set->
18420 n_particle_data_blocks - 1];
18424 p_data = &tng_data->non_tr_particle_data[tng_data->
18425 n_particle_data_blocks - 1];
18427 stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
18428 stride_length, n_particles,
18429 n_values_per_frame);
18430 if(stat != TNG_SUCCESS)
18432 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18433 __FILE__, __LINE__);
18438 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18440 stride_length = p_data->stride_length;
18442 if(is_first_frame_flag)
18444 p_data->first_frame_with_data = frame_nr;
18449 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18452 memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
18453 n_values_per_frame, values, sizeof(double) *
18454 n_particles * n_values_per_frame);
18458 memcpy(p_data->values, values, sizeof(double) * n_particles *
18459 n_values_per_frame);
18464 if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
18466 stat = tng_data_block_add(tng_data, block_id, block_name,
18467 TNG_DOUBLE_DATA, block_type_flag,
18468 n_frames, n_values_per_frame,
18469 stride_length, compression, 0);
18470 if(stat != TNG_SUCCESS)
18472 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18473 __FILE__, __LINE__);
18476 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18478 np_data = &frame_set->tr_data[frame_set->
18479 n_data_blocks - 1];
18483 np_data = &tng_data->non_tr_data[tng_data->
18484 n_data_blocks - 1];
18486 stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
18487 stride_length, n_values_per_frame);
18488 if(stat != TNG_SUCCESS)
18490 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
18491 __FILE__, __LINE__);
18496 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18498 stride_length = np_data->stride_length;
18500 if(is_first_frame_flag)
18502 np_data->first_frame_with_data = frame_nr;
18507 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
18510 memcpy((char *)np_data->values + sizeof(double) * frame_pos *
18511 n_values_per_frame, values, sizeof(double) *
18512 n_values_per_frame);
18516 memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
18520 return(TNG_SUCCESS);
18523 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18524 (tng_trajectory_t tng_data,
18525 const int64_t frame_nr,
18526 const float *positions)
18528 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18529 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18530 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18532 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
18533 TNG_TRAJ_POSITIONS, "POSITIONS",
18534 TNG_PARTICLE_BLOCK_DATA,
18535 TNG_TNG_COMPRESSION));
18538 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18539 (tng_trajectory_t tng_data,
18540 const int64_t frame_nr,
18541 const double *positions)
18543 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18544 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18545 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18547 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
18548 TNG_TRAJ_POSITIONS, "POSITIONS",
18549 TNG_PARTICLE_BLOCK_DATA,
18550 TNG_TNG_COMPRESSION));
18553 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18554 (tng_trajectory_t tng_data,
18555 const int64_t frame_nr,
18556 const float *velocities)
18558 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18559 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18560 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18562 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
18563 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18564 TNG_PARTICLE_BLOCK_DATA,
18565 TNG_TNG_COMPRESSION));
18568 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18569 (tng_trajectory_t tng_data,
18570 const int64_t frame_nr,
18571 const double *velocities)
18573 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18574 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18575 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18577 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
18578 TNG_TRAJ_VELOCITIES, "VELOCITIES",
18579 TNG_PARTICLE_BLOCK_DATA,
18580 TNG_TNG_COMPRESSION));
18583 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18584 (tng_trajectory_t tng_data,
18585 const int64_t frame_nr,
18586 const float *forces)
18588 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18589 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18590 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18592 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
18593 TNG_TRAJ_FORCES, "FORCES",
18594 TNG_PARTICLE_BLOCK_DATA,
18595 TNG_GZIP_COMPRESSION));
18598 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18599 (tng_trajectory_t tng_data,
18600 const int64_t frame_nr,
18601 const double *forces)
18603 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18604 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18605 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18607 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
18608 TNG_TRAJ_FORCES, "FORCES",
18609 TNG_PARTICLE_BLOCK_DATA,
18610 TNG_GZIP_COMPRESSION));
18613 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18614 (tng_trajectory_t tng_data,
18615 const int64_t frame_nr,
18616 const float *box_shape)
18618 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18619 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18620 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18622 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
18623 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18624 TNG_NON_PARTICLE_BLOCK_DATA,
18625 TNG_GZIP_COMPRESSION));
18628 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18629 (tng_trajectory_t tng_data,
18630 const int64_t frame_nr,
18631 const double *box_shape)
18633 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18634 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18635 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18637 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
18638 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18639 TNG_NON_PARTICLE_BLOCK_DATA,
18640 TNG_GZIP_COMPRESSION));
18643 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18644 (tng_trajectory_t tng_data,
18645 const int64_t frame_nr,
18647 const float *values,
18648 const int64_t n_values_per_frame,
18649 const int64_t block_id,
18650 const char *block_name,
18651 const char particle_dependency,
18652 const char compression)
18654 tng_trajectory_frame_set_t frame_set;
18655 tng_function_status stat;
18657 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18658 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18659 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18660 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18662 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
18663 block_id, block_name,
18664 particle_dependency,
18667 if(stat != TNG_SUCCESS)
18672 frame_set = &tng_data->current_trajectory_frame_set;
18674 /* first_frame_time is -1 when it is not yet set. */
18675 if(frame_set->first_frame_time < -0.1)
18677 if(frame_nr > frame_set->first_frame)
18679 stat = tng_frame_set_first_frame_time_set(tng_data,
18682 frame_set->first_frame) *
18683 tng_data->time_per_frame);
18687 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18693 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18694 (tng_trajectory_t tng_data,
18695 const int64_t frame_nr,
18697 const double *values,
18698 const int64_t n_values_per_frame,
18699 const int64_t block_id,
18700 const char *block_name,
18701 const char particle_dependency,
18702 const char compression)
18704 tng_trajectory_frame_set_t frame_set;
18705 tng_function_status stat;
18707 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18708 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18709 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18710 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
18712 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
18713 block_id, block_name,
18714 particle_dependency,
18717 if(stat != TNG_SUCCESS)
18722 frame_set = &tng_data->current_trajectory_frame_set;
18724 /* first_frame_time is -1 when it is not yet set. */
18725 if(frame_set->first_frame_time < -0.1)
18727 if(frame_nr > frame_set->first_frame)
18729 stat = tng_frame_set_first_frame_time_set(tng_data,
18732 frame_set->first_frame) *
18733 tng_data->time_per_frame);
18737 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18743 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18744 (tng_trajectory_t tng_data,
18745 const int64_t frame_nr,
18747 const float *positions)
18749 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18750 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18751 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18752 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18754 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
18755 3, TNG_TRAJ_POSITIONS, "POSITIONS",
18756 TNG_PARTICLE_BLOCK_DATA,
18757 TNG_TNG_COMPRESSION));
18760 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18761 (tng_trajectory_t tng_data,
18762 const int64_t frame_nr,
18764 const double *positions)
18766 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18767 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18768 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18769 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
18771 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18773 TNG_TRAJ_POSITIONS,
18775 TNG_PARTICLE_BLOCK_DATA,
18776 TNG_TNG_COMPRESSION));
18779 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18780 (tng_trajectory_t tng_data,
18781 const int64_t frame_nr,
18783 const float *velocities)
18785 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18786 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18787 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18788 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18790 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
18792 TNG_TRAJ_VELOCITIES,
18794 TNG_PARTICLE_BLOCK_DATA,
18795 TNG_TNG_COMPRESSION));
18798 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18799 (tng_trajectory_t tng_data,
18800 const int64_t frame_nr,
18802 const double *velocities)
18804 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18805 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18806 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18807 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
18809 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18811 TNG_TRAJ_VELOCITIES,
18813 TNG_PARTICLE_BLOCK_DATA,
18814 TNG_TNG_COMPRESSION));
18817 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18818 (tng_trajectory_t tng_data,
18819 const int64_t frame_nr,
18821 const float *forces)
18823 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18824 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18825 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18826 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18828 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
18829 3, TNG_TRAJ_FORCES, "FORCES",
18830 TNG_PARTICLE_BLOCK_DATA,
18831 TNG_GZIP_COMPRESSION));
18834 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18835 (tng_trajectory_t tng_data,
18836 const int64_t frame_nr,
18838 const double *forces)
18840 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18841 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18842 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18843 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
18845 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
18847 TNG_TRAJ_FORCES, "FORCES",
18848 TNG_PARTICLE_BLOCK_DATA,
18849 TNG_GZIP_COMPRESSION));
18852 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18853 (tng_trajectory_t tng_data,
18854 const int64_t frame_nr,
18856 const float *box_shape)
18858 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18859 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18860 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18861 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18863 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
18864 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
18865 TNG_NON_PARTICLE_BLOCK_DATA,
18866 TNG_GZIP_COMPRESSION));
18869 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18870 (tng_trajectory_t tng_data,
18871 const int64_t frame_nr,
18873 const double *box_shape)
18875 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18876 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
18877 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
18878 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
18880 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
18881 time, box_shape, 9,
18882 TNG_TRAJ_BOX_SHAPE,
18884 TNG_NON_PARTICLE_BLOCK_DATA,
18885 TNG_GZIP_COMPRESSION));
18888 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18889 (tng_trajectory_t tng_data,
18890 const int64_t block_id,
18894 tng_trajectory_frame_set_t frame_set;
18895 tng_particle_data_t p_data = 0;
18896 tng_non_particle_data_t np_data = 0;
18897 tng_function_status stat;
18899 int block_type = -1;
18901 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
18902 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
18903 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
18905 frame_set = &tng_data->current_trajectory_frame_set;
18907 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18908 if(stat == TNG_SUCCESS)
18910 block_type = TNG_PARTICLE_BLOCK_DATA;
18914 stat = tng_data_find(tng_data, block_id, &np_data);
18915 if(stat == TNG_SUCCESS)
18917 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18921 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18922 if(stat != TNG_SUCCESS)
18926 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18927 if(stat == TNG_SUCCESS)
18929 block_type = TNG_PARTICLE_BLOCK_DATA;
18933 stat = tng_data_find(tng_data, block_id, &np_data);
18934 if(stat == TNG_SUCCESS)
18936 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18945 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18947 if(p_data->last_retrieved_frame < 0)
18949 i = p_data->first_frame_with_data;
18953 i = p_data->last_retrieved_frame;
18956 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
18958 if(np_data->last_retrieved_frame < 0)
18960 i = np_data->first_frame_with_data;
18964 i = np_data->last_retrieved_frame;
18969 return(TNG_FAILURE);
18971 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
18973 stat = tng_frame_set_of_frame_find(tng_data, i);
18974 if(stat != TNG_SUCCESS)
18978 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18979 if(stat != TNG_SUCCESS)
18981 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
18982 __FILE__, __LINE__);
18986 if(block_type == TNG_PARTICLE_BLOCK_DATA)
18988 *codec_id = p_data->codec_id;
18989 *factor = (float)p_data->compression_multiplier;
18991 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
18993 *codec_id = np_data->codec_id;
18994 *factor = (float)np_data->compression_multiplier;
18996 return(TNG_SUCCESS);
18999 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19000 (tng_trajectory_t tng_data,
19001 int64_t current_frame,
19002 const int64_t n_requested_data_block_ids,
19003 const int64_t *requested_data_block_ids,
19004 int64_t *next_frame,
19005 int64_t *n_data_blocks_in_next_frame,
19006 int64_t **data_block_ids_in_next_frame)
19008 tng_trajectory_frame_set_t frame_set;
19009 tng_function_status stat;
19010 tng_particle_data_t p_data;
19011 tng_non_particle_data_t np_data;
19012 tng_gen_block_t block;
19013 int64_t i, j, block_id, *temp;
19014 int64_t data_frame, frame_diff, min_diff;
19015 int64_t size, frame_set_file_pos;
19016 int found, read_all = 0;
19019 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19020 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
19021 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19022 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19024 if(n_requested_data_block_ids)
19026 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.");
19027 size = sizeof(int64_t) * n_requested_data_block_ids;
19028 temp = realloc(*data_block_ids_in_next_frame, size);
19031 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19032 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19033 __FILE__, __LINE__);
19034 free(*data_block_ids_in_next_frame);
19035 *data_block_ids_in_next_frame = 0;
19036 return(TNG_CRITICAL);
19038 *data_block_ids_in_next_frame = temp;
19041 frame_set = &tng_data->current_trajectory_frame_set;
19043 current_frame += 1;
19045 if(current_frame < frame_set->first_frame ||
19046 current_frame >= frame_set->first_frame + frame_set->n_frames)
19048 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
19049 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
19050 if(stat != TNG_SUCCESS)
19052 /* If the frame set search found the frame set after the starting
19053 * frame set there is a gap in the frame sets. So, even if the frame
19054 * was not found the next frame with data is still in the found
19056 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19057 frame_set_file_pos)
19061 current_frame = frame_set->first_frame;
19065 /* Check for data blocks only if they have not already been found. */
19066 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
19068 file_pos = ftell(tng_data->input_file);
19069 if(file_pos < tng_data->input_file_len)
19071 tng_block_init(&block);
19072 stat = tng_block_header_read(tng_data, block);
19073 while(file_pos < tng_data->input_file_len &&
19074 stat != TNG_CRITICAL &&
19075 block->id != TNG_TRAJECTORY_FRAME_SET &&
19078 stat = tng_block_read_next(tng_data, block,
19080 if(stat != TNG_CRITICAL)
19082 file_pos = ftell(tng_data->input_file);
19083 if(file_pos < tng_data->input_file_len)
19085 stat = tng_block_header_read(tng_data, block);
19089 tng_block_destroy(&block);
19090 if(stat == TNG_CRITICAL)
19092 fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
19093 file_pos, __FILE__, __LINE__);
19102 *n_data_blocks_in_next_frame = 0;
19104 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
19106 p_data = &frame_set->tr_particle_data[i];
19107 block_id = p_data->block_id;
19109 if(n_requested_data_block_ids > 0)
19112 for(j = 0; j < n_requested_data_block_ids; j++)
19114 if(block_id == requested_data_block_ids[j])
19126 if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
19127 p_data->last_retrieved_frame >=
19128 frame_set->first_frame + frame_set->n_frames))
19130 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19131 TNG_USE_HASH, block_id);
19132 if(stat == TNG_CRITICAL)
19134 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19135 __FILE__, __LINE__);
19138 if(stat == TNG_FAILURE)
19143 if(frame_set->first_frame != current_frame &&
19144 p_data->last_retrieved_frame >= 0)
19146 data_frame = p_data->last_retrieved_frame + p_data->stride_length;
19150 data_frame = p_data->first_frame_with_data;
19152 frame_diff = data_frame - current_frame;
19157 if(min_diff == -1 || frame_diff <= min_diff)
19159 if(frame_diff < min_diff)
19161 *n_data_blocks_in_next_frame = 1;
19165 *n_data_blocks_in_next_frame += 1;
19167 if(n_requested_data_block_ids <= 0)
19169 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19170 temp = realloc(*data_block_ids_in_next_frame, size);
19173 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19174 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19175 __FILE__, __LINE__);
19176 free(*data_block_ids_in_next_frame);
19177 *data_block_ids_in_next_frame = 0;
19178 return(TNG_CRITICAL);
19180 *data_block_ids_in_next_frame = temp;
19184 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19186 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19188 min_diff = frame_diff;
19191 for(i = 0; i < frame_set->n_data_blocks; i++)
19193 np_data = &frame_set->tr_data[i];
19194 block_id = np_data->block_id;
19196 if(n_requested_data_block_ids > 0)
19199 for(j = 0; j < n_requested_data_block_ids; j++)
19201 if(block_id == requested_data_block_ids[j])
19213 if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
19214 np_data->last_retrieved_frame >=
19215 frame_set->first_frame + frame_set->n_frames))
19217 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
19218 TNG_USE_HASH, block_id);
19219 if(stat == TNG_CRITICAL)
19221 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
19222 __FILE__, __LINE__);
19225 if(stat == TNG_FAILURE)
19230 if(frame_set->first_frame != current_frame &&
19231 np_data->last_retrieved_frame >= 0)
19233 data_frame = np_data->last_retrieved_frame + np_data->stride_length;
19237 data_frame = np_data->first_frame_with_data;
19239 frame_diff = data_frame - current_frame;
19244 if(min_diff == -1 || frame_diff <= min_diff)
19246 if(frame_diff < min_diff)
19248 *n_data_blocks_in_next_frame = 1;
19252 *n_data_blocks_in_next_frame += 1;
19254 if(n_requested_data_block_ids <= 0)
19256 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
19257 temp = realloc(*data_block_ids_in_next_frame, size);
19260 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
19261 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
19262 __FILE__, __LINE__);
19263 free(*data_block_ids_in_next_frame);
19264 *data_block_ids_in_next_frame = 0;
19265 return(TNG_CRITICAL);
19267 *data_block_ids_in_next_frame = temp;
19271 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
19273 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
19275 min_diff = frame_diff;
19280 return(TNG_FAILURE);
19282 *next_frame = current_frame + min_diff;
19284 return(TNG_SUCCESS);
19288 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19289 (tng_trajectory_t tng_data,
19290 int64_t *n_data_blocks,
19291 int64_t **data_block_ids,
19292 char ***data_block_names,
19293 int64_t **stride_lengths,
19294 int64_t **n_values_per_frame,
19295 char **block_types,
19296 char **dependencies,
19297 char **compressions)
19299 tng_gen_block_t block;
19300 long orig_file_pos, file_pos;
19302 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19303 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19304 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19305 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19306 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19308 orig_file_pos = ftell(tng_data->input_file);
19310 if(!tng_data->input_file_len)
19312 fseek(tng_data->input_file, 0, SEEK_END);
19313 tng_data->input_file_len = ftell(tng_data->input_file);
19316 fseek(tng_data->input_file, 0, SEEK_SET);
19319 *n_data_blocks = 0;
19321 tng_block_init(&block);
19323 while(file_pos < tng_data->input_file_len &&
19324 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19326 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19330 file_pos += (long)(block->block_contents_size + block->header_contents_size);
19331 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
19334 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
19336 return(TNG_SUCCESS);
19339 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19340 (tng_trajectory_t tng_data,
19341 const int64_t prev_frame)
19343 tng_function_status stat;
19344 FILE *temp = tng_data->input_file;
19346 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19347 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
19349 tng_data->input_file = tng_data->output_file;
19351 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
19352 if(stat != TNG_SUCCESS)
19357 tng_data->current_trajectory_frame_set_output_file_pos =
19358 tng_data->current_trajectory_frame_set_input_file_pos;
19360 tng_data->input_file = temp;
19362 return(TNG_SUCCESS);