1 /* This code is part of the tng binary trajectory format.
3 * Written by Magnus Lundborg
4 * Copyright (c) 2012-2017, 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 /* These three definitions are required to enforce 64 bit file sizes. */
13 /* Force 64 bit variants of file access calls. */
14 #define _FILE_OFFSET_BITS 64
15 /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
16 #define _LARGEFILE_SOURCE
17 /* Define for large files, on AIX-style hosts. */
20 #include "tng/tng_io.h"
22 #ifdef USE_STD_INTTYPES_H
34 #include "compression/tng_compress.h"
35 #include "tng/version.h"
37 #if defined( _WIN32 ) || defined( _WIN64 )
39 #define fseeko _fseeki64
43 #define ftello ftello64
45 #define ftello _ftelli64
51 /** One of the atoms of the bond */
53 /** The other atom of the bond */
58 /** The residue containing this atom */
59 tng_residue_t residue
;
60 /** A unique (per molecule) ID number of the atom */
62 /** The atom_type (depending on the forcefield) */
64 /** The name of the atom */
69 /** The chain containing this residue */
71 /** A unique (per chain) ID number of the residue */
73 /** The name of the residue */
75 /** The number of atoms in the residue */
77 /** A list of atoms in the residue */
82 /** The molecule containing this chain */
83 tng_molecule_t molecule
;
84 /** A unique (per molecule) ID number of the chain */
86 /** The name of the chain */
88 /** The number of residues in the chain */
90 /** A list of residues in the chain */
91 tng_residue_t residues
;
95 /** A unique ID number of the molecule */
97 /** Quaternary structure of the molecule.
102 int64_t quaternary_str
;
103 /** The number of chains in the molecule */
105 /** The number of residues in the molecule */
107 /** The number of atoms in the molecule */
109 /** The number of bonds in the molecule. If the bonds are not specified this
112 /** The name of the molecule */
114 /** A list of chains in the molecule */
116 /** A list of residues in the molecule */
117 tng_residue_t residues
;
118 /** A list of the atoms in the molecule */
120 /** A list of the bonds in the molecule */
124 struct tng_gen_block
{
125 /** The size of the block header in bytes */
126 int64_t header_contents_size
;
127 /** The size of the block contents in bytes */
128 int64_t block_contents_size
;
129 /** The ID of the block to determine its type */
131 /** The MD5 hash of the block to verify integrity */
132 char md5_hash
[TNG_MD5_HASH_LEN
];
133 /** The name of the block */
135 /** The library version used to write the block */
136 int64_t block_version
;
137 int64_t alt_hash_type
;
138 int64_t alt_hash_len
;
140 int64_t signature_type
;
141 int64_t signature_len
;
143 /** The full block header contents */
144 char *header_contents
;
145 /** The full block contents */
146 char *block_contents
;
149 struct tng_particle_mapping
{
150 /** The index number of the first particle in this mapping block */
151 int64_t num_first_particle
;
152 /** The number of particles list in this mapping block */
154 /** the mapping of index numbers to the real particle numbers in the
155 * trajectory. real_particle_numbers[0] is the real particle number
156 * (as it is numbered in the molecular system) of the first particle
157 * in the data blocks covered by this particle mapping block */
158 int64_t *real_particle_numbers
;
161 struct tng_trajectory_frame_set
{
162 /** The number of different particle mapping blocks present. */
163 int64_t n_mapping_blocks
;
164 /** The atom mappings of this frame set */
165 struct tng_particle_mapping
*mappings
;
166 /** The first frame of this frame set */
168 /** The number of frames in this frame set */
170 /** The number of written frames in this frame set (used when writing one
171 * frame at a time). */
172 int64_t n_written_frames
;
173 /** The number of frames not yet written to file in this frame set
174 * (used from the utility functions to finish the writing properly. */
175 int64_t n_unwritten_frames
;
178 /** A list of the number of each molecule type - only used when using
179 * variable number of atoms */
180 int64_t *molecule_cnt_list
;
181 /** The number of particles/atoms - only used when using variable number
184 /** The file position of the next frame set */
185 int64_t next_frame_set_file_pos
;
186 /** The file position of the previous frame set */
187 int64_t prev_frame_set_file_pos
;
188 /** The file position of the frame set one long stride step ahead */
189 int64_t medium_stride_next_frame_set_file_pos
;
190 /** The file position of the frame set one long stride step behind */
191 int64_t medium_stride_prev_frame_set_file_pos
;
192 /** The file position of the frame set one long stride step ahead */
193 int64_t long_stride_next_frame_set_file_pos
;
194 /** The file position of the frame set one long stride step behind */
195 int64_t long_stride_prev_frame_set_file_pos
;
196 /** Time stamp (in seconds) of first frame in frame set */
197 double first_frame_time
;
199 /* The data blocks in a frame set are trajectory data blocks */
200 /** The number of trajectory data blocks of particle dependent data */
201 int n_particle_data_blocks
;
202 /** A list of data blocks containing particle dependent data */
203 struct tng_data
*tr_particle_data
;
204 /** The number of trajectory data blocks independent of particles */
206 /** A list of data blocks containing particle indepdendent data */
207 struct tng_data
*tr_data
;
210 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
212 /** The block ID of the data block containing this particle data.
213 * This is used to determine the kind of data that is stored */
215 /** The name of the data block. This is used to determine the kind of
216 * data that is stored */
218 /** The type of data stored. */
220 /** A flag to indicate if this data block contains frame and/or particle dependent
223 /** The frame number of the first data value */
224 int64_t first_frame_with_data
;
225 /** The number of frames in this frame set */
227 /** The number of values stored per frame */
228 int64_t n_values_per_frame
;
229 /** The number of frames between each data point - e.g. when
230 * storing sparse data. */
231 int64_t stride_length
;
232 /** ID of the CODEC used for compression 0 == no compression. */
234 /** If reading one frame at a time this is the last read frame */
235 int64_t last_retrieved_frame
;
236 /** The multiplier used for getting integer values for compression */
237 double compression_multiplier
;
238 /** A 1-dimensional array of values of length
239 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
241 /** If storing character data store it in a 3-dimensional array */
246 struct tng_trajectory
{
247 /** The path of the input trajectory file */
248 char *input_file_path
;
249 /** A handle to the input file */
251 /** The length of the input file */
252 int64_t input_file_len
;
253 /** The path of the output trajectory file */
254 char *output_file_path
;
255 /** A handle to the output file */
257 /** Function to swap 32 bit values to and from the endianness of the
259 tng_function_status (*input_endianness_swap_func_32
)(const tng_trajectory_t
, uint32_t *);
260 /** Function to swap 64 bit values to and from the endianness of the
262 tng_function_status (*input_endianness_swap_func_64
)(const tng_trajectory_t
, uint64_t *);
263 /** Function to swap 32 bit values to and from the endianness of the
265 tng_function_status (*output_endianness_swap_func_32
)(const tng_trajectory_t
, uint32_t *);
266 /** Function to swap 64 bit values to and from the endianness of the
268 tng_function_status (*output_endianness_swap_func_64
)(const tng_trajectory_t
, uint64_t *);
269 /** The endianness of 32 bit values of the current computer */
271 /** The endianness of 64 bit values of the current computer */
274 /** The name of the program producing this trajectory */
275 char *first_program_name
;
276 /** The forcefield used in the simulations */
277 char *forcefield_name
;
278 /** The name of the user running the simulations */
279 char *first_user_name
;
280 /** The name of the computer on which the simulations were performed */
281 char *first_computer_name
;
282 /** The PGP signature of the user creating the file. */
283 char *first_pgp_signature
;
284 /** The name of the program used when making last modifications to the
286 char *last_program_name
;
287 /** The name of the user making the last modifications to the file */
288 char *last_user_name
;
289 /** The name of the computer on which the last modifications were made */
290 char *last_computer_name
;
291 /** The PGP signature of the user making the last modifications to the
293 char *last_pgp_signature
;
294 /** The time (n seconds since 1970) when the file was created */
296 /** The exponential of the value of the distance unit used. The default
297 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
298 * the measurements are in Ã… the distance_unit_exponential = -10. */
299 int64_t distance_unit_exponential
;
301 /** A flag indicating if the number of atoms can vary throughout the
302 * simulation, e.g. using a grand canonical ensemble */
303 char var_num_atoms_flag
;
304 /** The number of frames in a frame set. It is allowed to have frame sets
305 * with fewer frames, but this will help searching for specific frames */
306 int64_t frame_set_n_frames
;
307 /** The number of frame sets in a medium stride step */
308 int64_t medium_stride_length
;
309 /** The number of frame sets in a long stride step */
310 int64_t long_stride_length
;
311 /** The current (can change from one frame set to another) time length
312 * (in seconds) of one frame */
313 double time_per_frame
;
315 /** The number of different kinds of molecules in the trajectory */
317 /** A list of molecules in the trajectory */
318 tng_molecule_t molecules
;
319 /** A list of the count of each molecule - if using variable number of
320 * particles this will be specified in each frame set */
321 int64_t *molecule_cnt_list
;
322 /** The total number of particles/atoms. If using variable number of
323 * particles this will be specified in each frame set */
326 /** The pos in the src file of the first frame set */
327 int64_t first_trajectory_frame_set_input_file_pos
;
328 /** The pos in the dest file of the first frame set */
329 int64_t first_trajectory_frame_set_output_file_pos
;
330 /** The pos in the src file of the last frame set */
331 int64_t last_trajectory_frame_set_input_file_pos
;
332 /** The pos in the dest file of the last frame set */
333 int64_t last_trajectory_frame_set_output_file_pos
;
334 /** The currently active frame set */
335 struct tng_trajectory_frame_set current_trajectory_frame_set
;
336 /** The pos in the src file of the current frame set */
337 int64_t current_trajectory_frame_set_input_file_pos
;
338 /** The pos in the dest file of the current frame set */
339 int64_t current_trajectory_frame_set_output_file_pos
;
340 /** The number of frame sets in the trajectory N.B. Not saved in file and
341 * cannot be trusted to be up-to-date */
342 int64_t n_trajectory_frame_sets
;
344 /* These data blocks are non-trajectory data blocks */
345 /** The number of non-frame dependent particle dependent data blocks */
346 int n_particle_data_blocks
;
347 /** A list of data blocks containing particle dependent data */
348 struct tng_data
*non_tr_particle_data
;
350 /** The number of frame and particle independent data blocks */
352 /** A list of frame and particle indepdendent data blocks */
353 struct tng_data
*non_tr_data
;
355 /** TNG compression algorithm for compressing positions */
356 int *compress_algo_pos
;
357 /** TNG compression algorithm for compressing velocities */
358 int *compress_algo_vel
;
359 /** The precision used for lossy compression */
360 double compression_precision
;
364 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
366 #endif /* win32... */
367 #endif /* not defined USE_WINDOWS */
370 #define TNG_INLINE __inline
371 #define TNG_SNPRINTF _snprintf
373 #define TNG_INLINE inline
374 #define TNG_SNPRINTF snprintf
377 static TNG_INLINE
size_t tng_min_size(const size_t a
, const size_t b
)
379 return (a
< b
? a
: b
);
382 static TNG_INLINE
int64_t tng_min_i64(const int64_t a
, const int64_t b
)
384 return (a
< b
? a
: b
);
387 static TNG_INLINE
int64_t tng_max_i64(const int64_t a
, const int64_t b
)
389 return (a
> b
? a
: b
);
393 * @brief This function swaps the byte order of a 32 bit numerical variable
395 * @param tng_data is a trajectory data container.
396 * @param v is a pointer to a 32 bit numerical value (float or integer).
397 * @details The function does not only work with integer, but e.g. floats need casting.
398 * If the byte order is already big endian no change is needed.
399 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
400 * byte order is not recognised.
402 static tng_function_status tng_swap_byte_order_big_endian_32
403 (const tng_trajectory_t tng_data
, uint32_t *v
)
405 switch(tng_data
->endianness_32
)
407 case TNG_LITTLE_ENDIAN_32
: /* Byte order is reversed. */
408 *v
= ((*v
& 0xFF000000) >> 24) | /* Move first byte to end */
409 ((*v
& 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
410 ((*v
& 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
411 ((*v
& 0x000000FF) << 24); /* Move last byte to first */
415 case TNG_BYTE_PAIR_SWAP_32
: /* byte pair swap */
416 *v
= ((*v
& 0xFFFF0000) >> 16) |
417 ((*v
& 0x0000FFFF) << 16);
421 case TNG_BIG_ENDIAN_32
: /* Already correct */
430 * @brief This function swaps the byte order of a 64 bit numerical variable
432 * @param tng_data is a trajectory data container.
433 * @param v is a pointer to a 64 bit numerical value (double or integer).
434 * @details The function does not only work with integer, but e.g. floats need casting.
435 * The byte order swapping routine can convert four different byte
436 * orders to big endian.
437 * If the byte order is already big endian no change is needed.
438 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
439 * byte order is not recognised.
441 static tng_function_status tng_swap_byte_order_big_endian_64
442 (const tng_trajectory_t tng_data
, uint64_t *v
)
444 switch(tng_data
->endianness_64
)
446 case TNG_LITTLE_ENDIAN_64
: /* Byte order is reversed. */
447 *v
= ((*v
& 0xFF00000000000000LL
) >> 56) | /* Move first byte to end */
448 ((*v
& 0x00FF000000000000LL
) >> 40) | /* Move 2nd byte to pos 7 */
449 ((*v
& 0x0000FF0000000000LL
) >> 24) | /* Move 3rd byte to pos 6 */
450 ((*v
& 0x000000FF00000000LL
) >> 8 ) | /* Move 4th byte to pos 5 */
451 ((*v
& 0x00000000FF000000LL
) << 8 ) | /* Move 5th byte to pos 4 */
452 ((*v
& 0x0000000000FF0000LL
) << 24) | /* Move 6th byte to pos 3 */
453 ((*v
& 0x000000000000FF00LL
) << 40) | /* Move 7th byte to pos 2 */
454 ((*v
& 0x00000000000000FFLL
) << 56); /* Move last byte to first */
458 case TNG_QUAD_SWAP_64
: /* Byte quad swap */
459 *v
= ((*v
& 0xFFFFFFFF00000000LL
) >> 32) |
460 ((*v
& 0x00000000FFFFFFFFLL
) << 32);
464 case TNG_BYTE_PAIR_SWAP_64
: /* Byte pair swap */
465 *v
= ((*v
& 0xFFFF0000FFFF0000LL
) >> 16) |
466 ((*v
& 0x0000FFFF0000FFFFLL
) << 16);
470 case TNG_BYTE_SWAP_64
: /* Byte swap */
471 *v
= ((*v
& 0xFF00FF00FF00FF00LL
) >> 8) |
472 ((*v
& 0x00FF00FF00FF00FFLL
) << 8);
476 case TNG_BIG_ENDIAN_64
: /* Already correct */
485 * @brief This function swaps the byte order of a 32 bit numerical variable
487 * @param tng_data is a trajectory data container.
488 * @param v is a pointer to a 32 bit numerical value (float or integer).
489 * @details The function does not only work with integer, but e.g. floats need casting.
490 * If the byte order is already little endian no change is needed.
491 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
492 * byte order is not recognised.
494 static tng_function_status tng_swap_byte_order_little_endian_32
495 (const tng_trajectory_t tng_data
, uint32_t *v
)
497 switch(tng_data
->endianness_32
)
499 case TNG_LITTLE_ENDIAN_32
: /* Already correct */
502 case TNG_BYTE_PAIR_SWAP_32
: /* byte pair swapped big endian to little endian */
503 *v
= ((*v
& 0xFF00FF00) >> 8) |
504 ((*v
& 0x00FF00FF) << 8);
508 case TNG_BIG_ENDIAN_32
: /* Byte order is reversed. */
509 *v
= ((*v
& 0xFF000000) >> 24) | /* Move first byte to end */
510 ((*v
& 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
511 ((*v
& 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
512 ((*v
& 0x000000FF) << 24); /* Move last byte to first */
522 * @brief This function swaps the byte order of a 64 bit numerical variable
524 * @param tng_data is a trajectory data container.
525 * @param v is a pointer to a 64 bit numerical value (double or integer).
526 * @details The function does not only work with integer, but e.g. floats need casting.
527 * The byte order swapping routine can convert four different byte
528 * orders to little endian.
529 * If the byte order is already little endian no change is needed.
530 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
531 * byte order is not recognised.
533 static tng_function_status tng_swap_byte_order_little_endian_64
534 (const tng_trajectory_t tng_data
, uint64_t *v
)
536 switch(tng_data
->endianness_64
)
538 case TNG_LITTLE_ENDIAN_64
: /* Already correct */
541 case TNG_QUAD_SWAP_64
: /* Byte quad swapped big endian to little endian */
542 *v
= ((*v
& 0xFF000000FF000000LL
) >> 24) |
543 ((*v
& 0x00FF000000FF0000LL
) >> 8) |
544 ((*v
& 0x0000FF000000FF00LL
) << 8) |
545 ((*v
& 0x000000FF000000FFLL
) << 24);
549 case TNG_BYTE_PAIR_SWAP_64
: /* Byte pair swapped big endian to little endian */
550 *v
= ((*v
& 0xFF00FF0000000000LL
) >> 40) |
551 ((*v
& 0x00FF00FF00000000LL
) >> 24) |
552 ((*v
& 0x00000000FF00FF00LL
) << 24) |
553 ((*v
& 0x0000000000FF00FFLL
) << 40);
557 case TNG_BYTE_SWAP_64
: /* Byte swapped big endian to little endian */
558 *v
= ((*v
& 0xFFFF000000000000LL
) >> 48) |
559 ((*v
& 0x0000FFFF00000000LL
) >> 16) |
560 ((*v
& 0x00000000FFFF0000LL
) << 16) |
561 ((*v
& 0x000000000000FFFFLL
) << 48);
565 case TNG_BIG_ENDIAN_64
: /* Byte order is reversed. */
566 *v
= ((*v
& 0xFF00000000000000LL
) >> 56) | /* Move first byte to end */
567 ((*v
& 0x00FF000000000000LL
) >> 40) | /* Move 2nd byte to pos 7 */
568 ((*v
& 0x0000FF0000000000LL
) >> 24) | /* Move 3rd byte to pos 6 */
569 ((*v
& 0x000000FF00000000LL
) >> 8 ) | /* Move 4th byte to pos 5 */
570 ((*v
& 0x00000000FF000000LL
) << 8 ) | /* Move 5th byte to pos 4 */
571 ((*v
& 0x0000000000FF0000LL
) << 24) | /* Move 6th byte to pos 3 */
572 ((*v
& 0x000000000000FF00LL
) << 40) | /* Move 7th byte to pos 2 */
573 ((*v
& 0x00000000000000FFLL
) << 56); /* Move last byte to first */
583 * @brief Read a NULL terminated string from a file.
584 * @param tng_data is a trajectory data container
585 * @param str is a pointer to the character string that will
586 * contain the read string. *str is reallocated in the function
587 * and must be NULL or pointing at already allocated memory.
588 * @param hash_mode is an option to decide whether to use the md5 hash or not.
589 * @param md5_state is a pointer to the current md5 storage, which will be
590 * appended with str if hash_mode == TNG_USE_HASH.
591 * @param line_nr is the line number where this function was called, to be
592 * able to give more useful error messages.
594 static tng_function_status
tng_freadstr(const tng_trajectory_t tng_data
,
596 const char hash_mode
,
597 md5_state_t
*md5_state
,
600 char temp
[TNG_MAX_STR_LEN
], *temp_alloc
;
605 c
= fgetc(tng_data
->input_file
);
609 /* Clear file error flag and return -1 if EOF is read.*/
610 clearerr(tng_data
->input_file
);
616 temp
[count
++] = (char) c
;
618 } while ((temp
[count
-1] != '\0') && (count
< TNG_MAX_STR_LEN
));
620 temp_alloc
= (char *)realloc(*str
, count
);
623 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, line_nr
);
630 strncpy(*str
, temp
, count
);
632 if(hash_mode
== TNG_USE_HASH
)
634 md5_append(md5_state
, (md5_byte_t
*)*str
, count
);
641 * @brief Write a NULL terminated string to a file.
642 * @param tng_data is a trajectory data container
643 * @param str is a pointer to the character string should be written.
644 * @param hash_mode is an option to decide whether to use the md5 hash or not.
645 * @param md5_state is a pointer to the current md5 storage, which will be
646 * appended with str if hash_mode == TNG_USE_HASH.
647 * @param line_nr is the line number where this function was called, to be
648 * able to give more useful error messages.
650 static TNG_INLINE tng_function_status
tng_fwritestr(tng_trajectory_t tng_data
,
652 const char hash_mode
,
653 md5_state_t
*md5_state
,
658 len
= tng_min_size(strlen(str
) + 1, TNG_MAX_STR_LEN
);
660 if(fwrite(str
, len
, 1, tng_data
->output_file
) != 1)
662 fprintf(stderr
, "TNG library: Could not write block data. %s: %d\n", __FILE__
, line_nr
);
663 return(TNG_CRITICAL
);
666 if(hash_mode
== TNG_USE_HASH
)
668 md5_append(md5_state
, (md5_byte_t
*)str
, len
);
675 * @brief Read a numerical value from file.
676 * The byte order will be swapped if need be.
677 * @param tng_data is a trajectory data container
678 * @param dest is a pointer to where to store the read data.
679 * @param len is the length (in bytes) of the numerical data type. Should
680 * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
681 * @param hash_mode is an option to decide whether to use the md5 hash or not.
682 * @param md5_state is a pointer to the current md5 storage, which will be
683 * appended with str if hash_mode == TNG_USE_HASH.
684 * @param line_nr is the line number where this function was called, to be
685 * able to give more useful error messages.
687 static TNG_INLINE tng_function_status tng_file_input_numerical
688 (const tng_trajectory_t tng_data
,
691 const char hash_mode
,
692 md5_state_t
*md5_state
,
695 if(fread(dest
, len
, 1, tng_data
->input_file
) == 0)
697 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, line_nr
);
698 return(TNG_CRITICAL
);
700 if(hash_mode
== TNG_USE_HASH
)
702 md5_append(md5_state
, (md5_byte_t
*)dest
, len
);
707 if(tng_data
->input_endianness_swap_func_64
&&
708 tng_data
->input_endianness_swap_func_64(tng_data
, (uint64_t *)dest
) != TNG_SUCCESS
)
710 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
715 if(tng_data
->input_endianness_swap_func_32
&&
716 tng_data
->input_endianness_swap_func_32(tng_data
, (uint32_t *)dest
) != TNG_SUCCESS
)
718 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
730 * @brief Write a numerical value to file.
731 * The byte order will be swapped if need be.
732 * @param tng_data is a trajectory data container
733 * @param src is a pointer to the data to write.
734 * @param len is the length (in bytes) of the numerical data type. Should
735 * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
736 * @param hash_mode is an option to decide whether to use the md5 hash or not.
737 * @param md5_state is a pointer to the current md5 storage, which will be
738 * appended with str if hash_mode == TNG_USE_HASH.
739 * @param line_nr is the line number where this function was called, to be
740 * able to give more useful error messages.
742 static TNG_INLINE tng_function_status tng_file_output_numerical
743 (const tng_trajectory_t tng_data
,
746 const char hash_mode
,
747 md5_state_t
*md5_state
,
756 temp_i64
= *((uint64_t *)src
);
757 if(tng_data
->output_endianness_swap_func_64
&&
758 tng_data
->output_endianness_swap_func_64(tng_data
, &temp_i64
) != TNG_SUCCESS
)
760 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
763 if(fwrite(&temp_i64
, len
, 1, tng_data
->output_file
) != 1)
765 fprintf(stderr
, "TNG library: Could not write data. %s: %d\n", __FILE__
, line_nr
);
766 return(TNG_CRITICAL
);
768 if(hash_mode
== TNG_USE_HASH
)
770 md5_append(md5_state
, (md5_byte_t
*)&temp_i64
, len
);
774 temp_i32
= *((uint32_t *)src
);
775 if(tng_data
->output_endianness_swap_func_32
&&
776 tng_data
->output_endianness_swap_func_32(tng_data
, &temp_i32
) != TNG_SUCCESS
)
778 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
781 if(fwrite(&temp_i32
, len
, 1, tng_data
->output_file
) != 1)
783 fprintf(stderr
, "TNG library: Could not write data. %s: %d\n", __FILE__
, line_nr
);
784 return(TNG_CRITICAL
);
786 if(hash_mode
== TNG_USE_HASH
)
788 md5_append(md5_state
, (md5_byte_t
*)&temp_i32
, len
);
792 if(fwrite(src
, len
, 1, tng_data
->output_file
) != 1)
794 fprintf(stderr
, "TNG library: Could not write data. %s: %d\n", __FILE__
, line_nr
);
795 return(TNG_CRITICAL
);
797 if(hash_mode
== TNG_USE_HASH
)
799 md5_append(md5_state
, (md5_byte_t
*)src
, len
);
808 * @brief Generate the md5 hash of a block.
809 * The hash is created based on the actual block contents.
810 * @param block is a general block container.
811 * @return TNG_SUCCESS (0) if successful.
813 static tng_function_status
tng_block_md5_hash_generate(const tng_gen_block_t block
)
815 md5_state_t md5_state
;
817 md5_init(&md5_state
);
818 md5_append(&md5_state
, (md5_byte_t
*)block
->block_contents
,
819 (int)block
->block_contents_size
);
820 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
826 * @brief If there is data left in the block read that to append that to the MD5 hash.
827 * @param tng_data is a trajectory data container.
828 * @param block is the data block that is being read.
829 * @param start_pos is the file position where the block started.
830 * @param md5_state is the md5 to which the md5 of the remaining block
832 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
835 static tng_function_status
tng_md5_remaining_append(const tng_trajectory_t tng_data
,
836 const tng_gen_block_t block
,
837 const int64_t start_pos
,
838 md5_state_t
*md5_state
)
840 int64_t curr_file_pos
;
843 curr_file_pos
= ftello(tng_data
->input_file
);
844 if(curr_file_pos
< start_pos
+ block
->block_contents_size
)
846 temp_data
= (char *)malloc(start_pos
+ block
->block_contents_size
- curr_file_pos
);
849 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
851 return(TNG_CRITICAL
);
853 if(fread(temp_data
, start_pos
+ block
->block_contents_size
- curr_file_pos
,
854 1, tng_data
->input_file
) == 0)
856 fprintf(stderr
, "TNG library: Cannot read remaining part of block to generate MD5 sum. %s: %d\n", __FILE__
, __LINE__
);
858 return(TNG_CRITICAL
);
860 md5_append(md5_state
, (md5_byte_t
*)temp_data
,
861 start_pos
+ block
->block_contents_size
- curr_file_pos
);
869 * @brief Open the input file if it is not already opened.
870 * @param tng_data is a trajectory data container.
871 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
874 static tng_function_status
tng_input_file_init(const tng_trajectory_t tng_data
)
878 if(!tng_data
->input_file
)
880 if(!tng_data
->input_file_path
)
882 fprintf(stderr
, "TNG library: No file specified for reading. %s: %d\n",
884 return(TNG_CRITICAL
);
886 tng_data
->input_file
= fopen(tng_data
->input_file_path
, "rb");
887 if(!tng_data
->input_file
)
889 fprintf(stderr
, "TNG library: Cannot open file %s. %s: %d\n",
890 tng_data
->input_file_path
, __FILE__
, __LINE__
);
891 return(TNG_CRITICAL
);
895 if(!tng_data
->input_file_len
)
897 file_pos
= ftello(tng_data
->input_file
);
898 fseeko(tng_data
->input_file
, 0, SEEK_END
);
899 tng_data
->input_file_len
= ftello(tng_data
->input_file
);
900 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
907 * @brief Open the output file if it is not already opened
908 * @param tng_data is a trajectory data container.
909 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
912 static tng_function_status
tng_output_file_init(const tng_trajectory_t tng_data
)
914 if(!tng_data
->output_file
)
916 if(!tng_data
->output_file_path
)
918 fprintf(stderr
, "TNG library: No file specified for writing. %s: %d\n",
920 return(TNG_CRITICAL
);
923 tng_data
->output_file
= fopen(tng_data
->output_file_path
, "wb+");
925 if(!tng_data
->output_file
)
927 fprintf(stderr
, "TNG library: Cannot open file %s. %s: %d\n",
928 tng_data
->output_file_path
, __FILE__
, __LINE__
);
929 return(TNG_CRITICAL
);
936 * @brief Setup a file block container.
937 * @param block_p a pointer to memory to initialise as a file block container.
938 * @details Memory is allocated during initialisation.
939 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
942 static tng_function_status
tng_block_init(struct tng_gen_block
**block_p
)
944 tng_gen_block_t block
;
946 *block_p
= (struct tng_gen_block
*)malloc(sizeof(struct tng_gen_block
));
949 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
950 return(TNG_CRITICAL
);
956 /* Reset the md5_hash */
957 memset(block
->md5_hash
, '\0', TNG_MD5_HASH_LEN
);
959 block
->block_version
= TNG_API_VERSION
;
960 block
->header_contents
= 0;
961 block
->header_contents_size
= 0;
962 block
->block_contents
= 0;
963 block
->block_contents_size
= 0;
969 * @brief Clean up a file block container.
970 * @param block_p a pointer to the file block container to destroy.
971 * @details All allocated memory in the data structure is freed, as well as
973 * @return TNG_SUCCESS (0) if successful.
975 static tng_function_status
tng_block_destroy(struct tng_gen_block
**block_p
)
977 tng_gen_block_t block
= *block_p
;
984 /* fprintf(stderr, "TNG library: Destroying block\n"); */
990 if(block
->header_contents
)
992 free(block
->header_contents
);
993 block
->header_contents
= 0;
995 if(block
->block_contents
)
997 free(block
->block_contents
);
998 block
->block_contents
= 0;
1004 return(TNG_SUCCESS
);
1008 * @brief Read the header of a data block, regardless of its type
1009 * @param tng_data is a trajectory data container.
1010 * @param block is a general block container.
1011 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
1012 * error has occured (not able to read the header size, thus skipping
1013 * the block) or TNG_CRITICAL (2) if a major error has occured.
1015 static tng_function_status tng_block_header_read
1016 (const tng_trajectory_t tng_data
, const tng_gen_block_t block
)
1020 TNG_ASSERT(block
!= 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
1022 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
1024 return(TNG_CRITICAL
);
1027 start_pos
= ftello(tng_data
->input_file
);
1029 /* First read the header size to be able to read the whole header. */
1030 if(fread(&block
->header_contents_size
, sizeof(block
->header_contents_size
),
1031 1, tng_data
->input_file
) == 0)
1033 fprintf(stderr
, "TNG library: Cannot read header size. %s: %d\n",
1034 __FILE__
, __LINE__
);
1035 return(TNG_CRITICAL
);
1038 if(block
->header_contents_size
== 0)
1041 return(TNG_FAILURE
);
1044 /* If this was the size of the general info block check the endianness */
1045 if(ftello(tng_data
->input_file
) < 9)
1047 /* File is little endian */
1048 if ( *((const char*)&block
->header_contents_size
) != 0x00 &&
1049 *((const char*)(&block
->header_contents_size
) + 7) == 0x00)
1051 /* If the architecture endianness is little endian no byte swap
1052 * will be needed. Otherwise use the functions to swap to little
1054 if(tng_data
->endianness_32
== TNG_LITTLE_ENDIAN_32
)
1056 tng_data
->input_endianness_swap_func_32
= 0;
1060 tng_data
->input_endianness_swap_func_32
=
1061 &tng_swap_byte_order_little_endian_32
;
1063 if(tng_data
->endianness_64
== TNG_LITTLE_ENDIAN_64
)
1065 tng_data
->input_endianness_swap_func_64
= 0;
1069 tng_data
->input_endianness_swap_func_64
=
1070 &tng_swap_byte_order_little_endian_64
;
1073 /* File is big endian */
1076 /* If the architecture endianness is big endian no byte swap
1077 * will be needed. Otherwise use the functions to swap to big
1079 if(tng_data
->endianness_32
== TNG_BIG_ENDIAN_32
)
1081 tng_data
->input_endianness_swap_func_32
= 0;
1085 tng_data
->input_endianness_swap_func_32
=
1086 &tng_swap_byte_order_big_endian_32
;
1088 if(tng_data
->endianness_64
== TNG_BIG_ENDIAN_64
)
1090 tng_data
->input_endianness_swap_func_64
= 0;
1094 tng_data
->input_endianness_swap_func_64
=
1095 &tng_swap_byte_order_big_endian_64
;
1100 if(tng_data
->input_endianness_swap_func_64
&&
1101 tng_data
->input_endianness_swap_func_64(tng_data
, (uint64_t *)&block
->header_contents_size
) != TNG_SUCCESS
)
1103 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1104 __FILE__
, __LINE__
);
1107 if(tng_file_input_numerical(tng_data
, &block
->block_contents_size
,
1108 sizeof(block
->block_contents_size
),
1109 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
1111 return(TNG_CRITICAL
);
1114 if(tng_file_input_numerical(tng_data
, &block
->id
,
1116 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
1118 return(TNG_CRITICAL
);
1121 if(fread(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->input_file
) == 0)
1123 fprintf(stderr
, "TNG library: Cannot read block header. %s: %d\n", __FILE__
, __LINE__
);
1124 return(TNG_CRITICAL
);
1127 tng_freadstr(tng_data
, &block
->name
, TNG_SKIP_HASH
, 0, __LINE__
);
1129 if(tng_file_input_numerical(tng_data
, &block
->block_version
,
1130 sizeof(block
->block_version
),
1131 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
1133 return(TNG_CRITICAL
);
1136 fseeko(tng_data
->input_file
, start_pos
+ block
->header_contents_size
, SEEK_SET
);
1138 return(TNG_SUCCESS
);
1142 * @brief Write a whole block, both header and contents, regardless of it type
1143 * @param tng_data is a trajectory data container.
1144 * @param block is a general block container.
1145 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1146 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1148 /* Disabled until it is used.*/
1150 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1151 // tng_gen_block_t block)
1153 // if(!block->header_contents)
1155 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1156 // return(TNG_FAILURE);
1158 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1159 // tng_data->output_file) != 1)
1161 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1162 // __FILE__, __LINE__);
1163 // return(TNG_CRITICAL);
1166 // if(!block->block_contents)
1168 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1169 // __FILE__, __LINE__);
1170 // return(TNG_FAILURE);
1172 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1173 // tng_data->output_file) != 1)
1175 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1176 // __FILE__, __LINE__);
1177 // return(TNG_CRITICAL);
1179 // return(TNG_SUCCESS);
1184 * @brief Update the md5 hash of a block already written to the file
1185 * @param tng_data is a trajectory data container.
1186 * @param block is the block, of which to update the md5 hash.
1187 * @param header_start_pos is the file position where the block header starts.
1188 * @param contents_start_pos is the file position where the block contents
1190 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1191 * error has occured.
1193 static tng_function_status
tng_md5_hash_update(const tng_trajectory_t tng_data
,
1194 const tng_gen_block_t block
,
1195 const int64_t header_start_pos
,
1196 const int64_t contents_start_pos
)
1198 if(block
->block_contents
)
1200 free(block
->block_contents
);
1203 block
->block_contents
= (char *)malloc(block
->block_contents_size
);
1204 if(!block
->block_contents
)
1206 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
1207 return(TNG_CRITICAL
);
1210 fseeko(tng_data
->output_file
, contents_start_pos
, SEEK_SET
);
1211 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
1212 tng_data
->output_file
) == 0)
1214 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
1215 return(TNG_CRITICAL
);
1218 tng_block_md5_hash_generate(block
);
1220 fseeko(tng_data
->output_file
, header_start_pos
+ 3 * sizeof(int64_t),
1222 fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
);
1224 return(TNG_SUCCESS
);
1228 * @brief Update the frame set pointers in the file header (general info block),
1229 * already written to disk
1230 * @param tng_data is a trajectory data container.
1231 * @param hash_mode specifies whether to update the block md5 hash when
1232 * updating the pointers.
1233 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1234 * error has occured.
1236 static tng_function_status tng_header_pointers_update
1237 (const tng_trajectory_t tng_data
, const char hash_mode
)
1239 tng_gen_block_t block
;
1240 FILE *temp
= tng_data
->input_file
;
1241 uint64_t output_file_pos
, pos
, contents_start_pos
;
1243 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
1245 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
1246 __FILE__
, __LINE__
);
1247 return(TNG_CRITICAL
);
1250 tng_data
->input_file
= tng_data
->output_file
;
1252 tng_block_init(&block
);
1254 output_file_pos
= ftello(tng_data
->output_file
);
1255 fseeko(tng_data
->output_file
, 0, SEEK_SET
);
1257 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1259 fprintf(stderr
, "TNG library: Cannot read general info header. %s: %d\n",
1260 __FILE__
, __LINE__
);
1261 tng_data
->input_file
= temp
;
1262 tng_block_destroy(&block
);
1263 return(TNG_CRITICAL
);
1266 contents_start_pos
= ftello(tng_data
->output_file
);
1268 fseeko(tng_data
->output_file
, block
->block_contents_size
- 5 *
1269 sizeof(int64_t), SEEK_CUR
);
1271 tng_data
->input_file
= temp
;
1273 pos
= tng_data
->first_trajectory_frame_set_output_file_pos
;
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_block_destroy(&block
);
1289 return(TNG_CRITICAL
);
1292 pos
= tng_data
->last_trajectory_frame_set_output_file_pos
;
1294 if(tng_data
->input_endianness_swap_func_64
)
1296 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1300 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1301 __FILE__
, __LINE__
);
1306 sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1308 tng_block_destroy(&block
);
1309 return(TNG_CRITICAL
);
1312 if(hash_mode
== TNG_USE_HASH
)
1314 tng_md5_hash_update(tng_data
, block
, 0, contents_start_pos
);
1317 tng_block_destroy(&block
);
1319 fseeko(tng_data
->output_file
, output_file_pos
, SEEK_SET
);
1321 return(TNG_SUCCESS
);
1325 * @brief Update the frame set pointers in the current frame set block, already
1326 * written to disk. It also updates the pointers of the blocks pointing to
1327 * the current frame set block.
1328 * @param tng_data is a trajectory data container.
1329 * @param hash_mode specifies whether to update the block md5 hash when
1330 * updating the pointers.
1331 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1332 * error has occured.
1334 static tng_function_status tng_frame_set_pointers_update
1335 (const tng_trajectory_t tng_data
, const char hash_mode
)
1337 tng_gen_block_t block
;
1338 tng_trajectory_frame_set_t frame_set
;
1339 FILE *temp
= tng_data
->input_file
;
1340 uint64_t pos
, output_file_pos
, contents_start_pos
;
1342 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
1344 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
1345 __FILE__
, __LINE__
);
1346 return(TNG_CRITICAL
);
1349 tng_block_init(&block
);
1350 output_file_pos
= ftello(tng_data
->output_file
);
1352 tng_data
->input_file
= tng_data
->output_file
;
1354 frame_set
= &tng_data
->current_trajectory_frame_set
;
1356 pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
1358 /* Update next frame set */
1359 if(frame_set
->next_frame_set_file_pos
> 0)
1361 fseeko(tng_data
->output_file
, frame_set
->next_frame_set_file_pos
, SEEK_SET
);
1363 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1365 fprintf(stderr
, "TNG library: Cannot read frame header. %s: %d\n",
1366 __FILE__
, __LINE__
);
1367 tng_data
->input_file
= temp
;
1368 tng_block_destroy(&block
);
1369 return(TNG_CRITICAL
);
1372 contents_start_pos
= ftello(tng_data
->output_file
);
1374 fseeko(tng_data
->output_file
, block
->block_contents_size
- (5 *
1375 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1377 if(tng_data
->input_endianness_swap_func_64
)
1379 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1383 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1384 __FILE__
, __LINE__
);
1388 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1390 tng_data
->input_file
= temp
;
1391 tng_block_destroy(&block
);
1392 return(TNG_CRITICAL
);
1395 if(hash_mode
== TNG_USE_HASH
)
1397 tng_md5_hash_update(tng_data
, block
, frame_set
->next_frame_set_file_pos
,
1398 contents_start_pos
);
1401 /* Update previous frame set */
1402 if(frame_set
->prev_frame_set_file_pos
> 0)
1404 fseeko(tng_data
->output_file
, frame_set
->prev_frame_set_file_pos
,
1407 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1409 fprintf(stderr
, "TNG library: Cannot read frame header. %s: %d\n",
1410 __FILE__
, __LINE__
);
1411 tng_data
->input_file
= temp
;
1412 tng_block_destroy(&block
);
1413 return(TNG_CRITICAL
);
1416 contents_start_pos
= ftello(tng_data
->output_file
);
1418 fseeko(tng_data
->output_file
, block
->block_contents_size
- (6 *
1419 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1421 if(tng_data
->input_endianness_swap_func_64
)
1423 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1427 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1428 __FILE__
, __LINE__
);
1432 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1434 tng_data
->input_file
= temp
;
1435 tng_block_destroy(&block
);
1436 return(TNG_CRITICAL
);
1439 if(hash_mode
== TNG_USE_HASH
)
1441 tng_md5_hash_update(tng_data
, block
, frame_set
->prev_frame_set_file_pos
,
1442 contents_start_pos
);
1446 /* Update the frame set one medium stride step after */
1447 if(frame_set
->medium_stride_next_frame_set_file_pos
> 0)
1449 fseeko(tng_data
->output_file
,
1450 frame_set
->medium_stride_next_frame_set_file_pos
,
1453 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1455 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1456 __FILE__
, __LINE__
);
1457 tng_data
->input_file
= temp
;
1458 tng_block_destroy(&block
);
1459 return(TNG_CRITICAL
);
1462 contents_start_pos
= ftello(tng_data
->output_file
);
1464 fseeko(tng_data
->output_file
, block
->block_contents_size
- (3 *
1465 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1467 if(tng_data
->input_endianness_swap_func_64
)
1469 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1473 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1474 __FILE__
, __LINE__
);
1478 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1480 tng_data
->input_file
= temp
;
1481 tng_block_destroy(&block
);
1482 return(TNG_CRITICAL
);
1485 if(hash_mode
== TNG_USE_HASH
)
1487 tng_md5_hash_update(tng_data
, block
,
1488 frame_set
->medium_stride_next_frame_set_file_pos
,
1489 contents_start_pos
);
1492 /* Update the frame set one medium stride step before */
1493 if(frame_set
->medium_stride_prev_frame_set_file_pos
> 0)
1495 fseeko(tng_data
->output_file
,
1496 frame_set
->medium_stride_prev_frame_set_file_pos
,
1499 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1501 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1502 __FILE__
, __LINE__
);
1503 tng_data
->input_file
= temp
;
1504 tng_block_destroy(&block
);
1505 return(TNG_CRITICAL
);
1508 contents_start_pos
= ftello(tng_data
->output_file
);
1510 fseeko(tng_data
->output_file
, block
->block_contents_size
- (4 *
1511 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1513 if(tng_data
->input_endianness_swap_func_64
)
1515 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1519 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1520 __FILE__
, __LINE__
);
1524 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1526 tng_data
->input_file
= temp
;
1527 tng_block_destroy(&block
);
1528 return(TNG_CRITICAL
);
1531 if(hash_mode
== TNG_USE_HASH
)
1533 tng_md5_hash_update(tng_data
, block
,
1534 frame_set
->medium_stride_prev_frame_set_file_pos
,
1535 contents_start_pos
);
1539 /* Update the frame set one long stride step after */
1540 if(frame_set
->long_stride_next_frame_set_file_pos
> 0)
1542 fseeko(tng_data
->output_file
,
1543 frame_set
->long_stride_next_frame_set_file_pos
,
1546 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1548 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1549 __FILE__
, __LINE__
);
1550 tng_data
->input_file
= temp
;
1551 tng_block_destroy(&block
);
1552 return(TNG_CRITICAL
);
1555 contents_start_pos
= ftello(tng_data
->output_file
);
1557 fseeko(tng_data
->output_file
, block
->block_contents_size
- (1 *
1558 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1560 if(tng_data
->input_endianness_swap_func_64
)
1562 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1566 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1567 __FILE__
, __LINE__
);
1571 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1573 tng_data
->input_file
= temp
;
1574 tng_block_destroy(&block
);
1575 return(TNG_CRITICAL
);
1578 if(hash_mode
== TNG_USE_HASH
)
1580 tng_md5_hash_update(tng_data
, block
,
1581 frame_set
->long_stride_next_frame_set_file_pos
,
1582 contents_start_pos
);
1585 /* Update the frame set one long stride step before */
1586 if(frame_set
->long_stride_prev_frame_set_file_pos
> 0)
1588 fseeko(tng_data
->output_file
,
1589 frame_set
->long_stride_prev_frame_set_file_pos
,
1592 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1594 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1595 __FILE__
, __LINE__
);
1596 tng_data
->input_file
= temp
;
1597 tng_block_destroy(&block
);
1598 return(TNG_CRITICAL
);
1601 contents_start_pos
= ftello(tng_data
->output_file
);
1603 fseeko(tng_data
->output_file
, block
->block_contents_size
- (2 *
1604 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1606 if(tng_data
->input_endianness_swap_func_64
)
1608 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1612 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1613 __FILE__
, __LINE__
);
1617 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1619 tng_data
->input_file
= temp
;
1620 tng_block_destroy(&block
);
1621 return(TNG_CRITICAL
);
1624 if(hash_mode
== TNG_USE_HASH
)
1626 tng_md5_hash_update(tng_data
, block
,
1627 frame_set
->long_stride_prev_frame_set_file_pos
,
1628 contents_start_pos
);
1632 fseeko(tng_data
->output_file
, output_file_pos
, SEEK_SET
);
1634 tng_data
->input_file
= temp
;
1636 tng_block_destroy(&block
);
1638 return(TNG_SUCCESS
);
1641 static tng_function_status tng_reread_frame_set_at_file_pos
1642 (const tng_trajectory_t tng_data
,
1645 tng_gen_block_t block
;
1646 tng_function_status stat
;
1648 tng_block_init(&block
);
1650 fseeko(tng_data
->input_file
, pos
, SEEK_SET
);
1653 stat
= tng_block_header_read(tng_data
, block
);
1654 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1656 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n", pos
,
1657 __FILE__
, __LINE__
);
1658 tng_block_destroy(&block
);
1659 return(TNG_FAILURE
);
1662 if(tng_block_read_next(tng_data
, block
,
1663 TNG_SKIP_HASH
) != TNG_SUCCESS
)
1665 tng_block_destroy(&block
);
1666 return(TNG_CRITICAL
);
1670 tng_block_destroy(&block
);
1672 return(TNG_SUCCESS
);
1675 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1676 (const tng_trajectory_t tng_data
,
1679 int64_t orig_pos
, curr_frame_set_pos
;
1680 tng_gen_block_t block
;
1681 tng_function_status stat
;
1682 tng_trajectory_frame_set_t frame_set
=
1683 &tng_data
->current_trajectory_frame_set
;
1685 orig_pos
= ftello(tng_data
->input_file
);
1686 curr_frame_set_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
1688 *pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
1692 return(TNG_SUCCESS
);
1695 fseeko(tng_data
->input_file
, *pos
, SEEK_SET
);
1697 tng_block_init(&block
);
1698 /* Read block headers first to see that a frame set block is found. */
1699 stat
= tng_block_header_read(tng_data
, block
);
1700 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1702 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n", *pos
,
1703 __FILE__
, __LINE__
);
1704 tng_block_destroy(&block
);
1705 return(TNG_FAILURE
);
1708 if(tng_block_read_next(tng_data
, block
,
1709 TNG_SKIP_HASH
) != TNG_SUCCESS
)
1711 tng_block_destroy(&block
);
1712 return(TNG_CRITICAL
);
1715 /* Read all frame set blocks (not the blocks between them) */
1716 while(frame_set
->next_frame_set_file_pos
> 0)
1718 fseeko(tng_data
->input_file
, frame_set
->next_frame_set_file_pos
, SEEK_SET
);
1719 stat
= tng_block_header_read(tng_data
, block
);
1720 if(stat
== TNG_CRITICAL
)
1722 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n", *pos
,
1723 __FILE__
, __LINE__
);
1724 tng_block_destroy(&block
);
1725 return(TNG_CRITICAL
);
1727 if(stat
!= TNG_SUCCESS
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1729 return(TNG_FAILURE
);
1732 stat
= tng_block_read_next(tng_data
, block
, TNG_SKIP_HASH
);
1733 if(stat
!= TNG_SUCCESS
)
1735 tng_block_destroy(&block
);
1738 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1739 if(tng_data
->current_trajectory_frame_set_input_file_pos
< *pos
&&
1740 tng_data
->current_trajectory_frame_set_input_file_pos
> orig_pos
)
1742 *pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
1746 /* Re-read the frame set that used to be the current one */
1747 tng_reread_frame_set_at_file_pos(tng_data
, curr_frame_set_pos
);
1749 fseeko(tng_data
->input_file
, orig_pos
, SEEK_SET
);
1751 tng_block_destroy(&block
);
1753 return(TNG_SUCCESS
);
1757 * @brief Migrate a whole frame set from one position in the file to another.
1758 * @param tng_data is a trajectory data container.
1759 * @param block_start_pos is the starting position in the file of the frame set.
1760 * @param block_len is the length of the whole frame set (including all data blocks etc).
1761 * @param new_pos is the new position in the file of the frame set.
1762 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
1764 static tng_function_status tng_frame_set_complete_migrate
1765 (const tng_trajectory_t tng_data
,
1766 const int64_t block_start_pos
,
1767 const int64_t block_len
,
1768 const int64_t new_pos
,
1769 const char hash_mode
)
1771 tng_bool updated
= TNG_FALSE
;
1775 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
1777 return(TNG_CRITICAL
);
1780 fseeko(tng_data
->input_file
, block_start_pos
, SEEK_SET
);
1782 contents
= (char *)malloc(block_len
);
1785 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
1786 return(TNG_CRITICAL
);
1789 if(fread(contents
, block_len
, 1, tng_data
->input_file
) == 0)
1791 fprintf(stderr
, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1792 __FILE__
, __LINE__
);
1794 return(TNG_CRITICAL
);
1796 fseeko(tng_data
->output_file
, new_pos
, SEEK_SET
);
1798 if(fwrite(contents
, block_len
, 1, tng_data
->output_file
) != 1)
1800 fprintf(stderr
, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1801 __FILE__
, __LINE__
);
1803 return(TNG_CRITICAL
);
1806 tng_data
->current_trajectory_frame_set_output_file_pos
= new_pos
;
1807 if(tng_data
->input_file
== tng_data
->output_file
)
1809 tng_data
->current_trajectory_frame_set_input_file_pos
= new_pos
;
1812 tng_frame_set_pointers_update(tng_data
, hash_mode
);
1814 /* Update the general info block if needed */
1815 if(block_start_pos
== tng_data
->first_trajectory_frame_set_output_file_pos
)
1817 tng_data
->first_trajectory_frame_set_output_file_pos
= new_pos
;
1820 if(block_start_pos
== tng_data
->last_trajectory_frame_set_output_file_pos
)
1822 tng_data
->last_trajectory_frame_set_output_file_pos
= new_pos
;
1827 tng_header_pointers_update(tng_data
, hash_mode
);
1830 /* Fill the block with NULL to avoid confusion. */
1831 memset(contents
, '\0', block_len
);
1832 fseeko(tng_data
->output_file
, block_start_pos
, SEEK_SET
);
1834 /* FIXME: casting block_len to size_t is dangerous */
1835 fwrite(contents
, 1, block_len
, tng_data
->output_file
);
1839 return(TNG_SUCCESS
);
1842 static tng_function_status tng_length_of_current_frame_set_contents_get
1843 (const tng_trajectory_t tng_data
,
1846 int64_t orig_pos
, pos
, curr_frame_set_pos
;
1847 tng_gen_block_t block
;
1848 tng_function_status stat
;
1850 orig_pos
= ftello(tng_data
->input_file
);
1851 curr_frame_set_pos
= pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
1855 fseeko(tng_data
->input_file
, curr_frame_set_pos
, SEEK_SET
);
1857 tng_block_init(&block
);
1858 /* Read block headers first to see that a frame set block is found. */
1859 stat
= tng_block_header_read(tng_data
, block
);
1860 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1862 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
1863 curr_frame_set_pos
, __FILE__
, __LINE__
);
1864 tng_block_destroy(&block
);
1865 return(TNG_FAILURE
);
1868 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1869 while(stat
== TNG_SUCCESS
)
1871 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
1872 *len
+= block
->header_contents_size
+ block
->block_contents_size
;
1873 pos
+= block
->header_contents_size
+ block
->block_contents_size
;
1874 if(pos
>= tng_data
->input_file_len
)
1878 stat
= tng_block_header_read(tng_data
, block
);
1879 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
1885 /* Re-read the frame set that used to be the current one */
1886 tng_reread_frame_set_at_file_pos(tng_data
, curr_frame_set_pos
);
1888 fseeko(tng_data
->input_file
, orig_pos
, SEEK_SET
);
1890 tng_block_destroy(&block
);
1892 return(TNG_SUCCESS
);
1896 * @brief Migrate blocks in the file to make room for new data in a block. This
1897 * is required e.g. when adding data to a block or extending strings in a
1899 * @param tng_data is a trajectory data container.
1900 * @param start_pos is the position from which to start moving data, usually
1901 * the byte after the end of the block to which data was added.
1902 * @param offset is the number of bytes that were inserted.
1903 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
1904 * @details Trajectory blocks (frame sets and their related blocks) are moved
1905 * to the end of the file (if needed) in order to make room for non-trajectory
1908 static tng_function_status tng_migrate_data_in_file
1909 (const tng_trajectory_t tng_data
,
1910 const int64_t start_pos
,
1911 const int64_t offset
,
1912 const char hash_mode
)
1914 int64_t traj_start_pos
, empty_space
, orig_file_pos
, frame_set_length
;
1915 tng_gen_block_t block
;
1916 tng_function_status stat
;
1920 return(TNG_SUCCESS
);
1923 stat
= tng_file_pos_of_subsequent_trajectory_block_get(tng_data
, &traj_start_pos
);
1924 if(stat
!= TNG_SUCCESS
)
1929 tng_data
->current_trajectory_frame_set_input_file_pos
= traj_start_pos
;
1931 empty_space
= traj_start_pos
- (start_pos
- 1);
1933 if(empty_space
>= offset
)
1935 return(TNG_SUCCESS
);
1938 orig_file_pos
= ftello(tng_data
->input_file
);
1939 tng_block_init(&block
);
1941 while(empty_space
< offset
)
1943 fseeko(tng_data
->input_file
, traj_start_pos
, SEEK_SET
);
1944 stat
= tng_block_header_read(tng_data
, block
);
1945 if(stat
== TNG_CRITICAL
)
1947 fprintf(stderr
, "TNG library: Cannot read block header. %s: %d\n",
1948 __FILE__
, __LINE__
);
1949 tng_block_destroy(&block
);
1950 return(TNG_CRITICAL
);
1952 if(stat
!= TNG_SUCCESS
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1954 tng_block_destroy(&block
);
1955 return(TNG_FAILURE
);
1957 stat
= tng_length_of_current_frame_set_contents_get(tng_data
, &frame_set_length
);
1958 if(stat
!= TNG_SUCCESS
)
1960 tng_block_destroy(&block
);
1963 stat
= tng_frame_set_complete_migrate(tng_data
, traj_start_pos
,
1964 frame_set_length
, tng_data
->input_file_len
,
1966 if(stat
!= TNG_SUCCESS
)
1968 tng_block_destroy(&block
);
1972 empty_space
+= frame_set_length
;
1974 fseeko(tng_data
->input_file
, orig_file_pos
, SEEK_SET
);
1975 tng_block_destroy(&block
);
1977 return(TNG_SUCCESS
);
1980 static tng_function_status tng_block_header_len_calculate
1981 (const tng_trajectory_t tng_data
,
1982 const tng_gen_block_t block
,
1988 /* If the string is unallocated allocate memory for just string
1992 block
->name
= (char *)malloc(1);
1995 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
1996 __FILE__
, __LINE__
);
1997 return(TNG_CRITICAL
);
2002 name_len
= tng_min_size(strlen(block
->name
) + 1, TNG_MAX_STR_LEN
);
2004 /* Calculate the size of the header to write */
2005 *len
= sizeof(block
->header_contents_size
) +
2006 sizeof(block
->block_contents_size
) +
2008 sizeof(block
->block_version
) +
2012 return (TNG_SUCCESS
);
2016 * @brief Write the header of a data block, regardless of its type
2017 * @param tng_data is a trajectory data container.
2018 * @param block is a general block container.
2019 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2020 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2021 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2022 * error has occured.
2024 static tng_function_status tng_block_header_write
2025 (const tng_trajectory_t tng_data
,
2026 const tng_gen_block_t block
)
2028 TNG_ASSERT(block
!= 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
2030 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
2032 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
2033 __FILE__
, __LINE__
);
2034 return(TNG_CRITICAL
);
2037 if(tng_block_header_len_calculate(tng_data
, block
, &block
->header_contents_size
) !=
2040 fprintf(stderr
, "TNG library: Cannot calculate length of block header. %s: %d\n",
2041 __FILE__
, __LINE__
);
2042 return(TNG_CRITICAL
);
2045 if(tng_file_output_numerical(tng_data
, &block
->header_contents_size
,
2046 sizeof(block
->header_contents_size
),
2047 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
2049 return(TNG_CRITICAL
);
2052 if(tng_file_output_numerical(tng_data
, &block
->block_contents_size
,
2053 sizeof(block
->block_contents_size
),
2054 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
2056 return(TNG_CRITICAL
);
2059 if(tng_file_output_numerical(tng_data
, &block
->id
,
2061 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
2063 return(TNG_CRITICAL
);
2066 if(fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
) != 1)
2068 fprintf(stderr
, "TNG library: Could not write header data. %s: %d\n", __FILE__
, __LINE__
);
2069 return(TNG_CRITICAL
);
2072 if(tng_fwritestr(tng_data
, block
->name
, TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
2074 return(TNG_CRITICAL
);
2077 if(tng_file_output_numerical(tng_data
, &block
->block_version
,
2078 sizeof(block
->block_version
),
2079 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
2081 return(TNG_CRITICAL
);
2084 return(TNG_SUCCESS
);
2087 static tng_function_status tng_general_info_block_len_calculate
2088 (const tng_trajectory_t tng_data
,
2091 size_t first_program_name_len
, first_user_name_len
;
2092 size_t first_computer_name_len
, first_pgp_signature_len
;
2093 size_t last_program_name_len
, last_user_name_len
;
2094 size_t last_computer_name_len
, last_pgp_signature_len
;
2095 size_t forcefield_name_len
;
2097 /* If the strings are unallocated allocate memory for just string
2099 if(!tng_data
->first_program_name
)
2101 tng_data
->first_program_name
= (char *)malloc(1);
2102 if(!tng_data
->first_program_name
)
2104 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2105 __FILE__
, __LINE__
);
2106 return(TNG_CRITICAL
);
2108 tng_data
->first_program_name
[0] = 0;
2110 if(!tng_data
->last_program_name
)
2112 tng_data
->last_program_name
= (char *)malloc(1);
2113 if(!tng_data
->last_program_name
)
2115 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2116 __FILE__
, __LINE__
);
2117 return(TNG_CRITICAL
);
2119 tng_data
->last_program_name
[0] = 0;
2121 if(!tng_data
->first_user_name
)
2123 tng_data
->first_user_name
= (char *)malloc(1);
2124 if(!tng_data
->first_user_name
)
2126 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2127 __FILE__
, __LINE__
);
2128 return(TNG_CRITICAL
);
2130 tng_data
->first_user_name
[0] = 0;
2132 if(!tng_data
->last_user_name
)
2134 tng_data
->last_user_name
= (char *)malloc(1);
2135 if(!tng_data
->last_user_name
)
2137 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2138 __FILE__
, __LINE__
);
2139 return(TNG_CRITICAL
);
2141 tng_data
->last_user_name
[0] = 0;
2143 if(!tng_data
->first_computer_name
)
2145 tng_data
->first_computer_name
= (char *)malloc(1);
2146 if(!tng_data
->first_computer_name
)
2148 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2149 __FILE__
, __LINE__
);
2150 return(TNG_CRITICAL
);
2152 tng_data
->first_computer_name
[0] = 0;
2154 if(!tng_data
->last_computer_name
)
2156 tng_data
->last_computer_name
= (char *)malloc(1);
2157 if(!tng_data
->last_computer_name
)
2159 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2160 __FILE__
, __LINE__
);
2161 return(TNG_CRITICAL
);
2163 tng_data
->last_computer_name
[0] = 0;
2165 if(!tng_data
->first_pgp_signature
)
2167 tng_data
->first_pgp_signature
= (char *)malloc(1);
2168 if(!tng_data
->first_pgp_signature
)
2170 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2171 __FILE__
, __LINE__
);
2172 return(TNG_CRITICAL
);
2174 tng_data
->first_pgp_signature
[0] = 0;
2176 if(!tng_data
->last_pgp_signature
)
2178 tng_data
->last_pgp_signature
= (char *)malloc(1);
2179 if(!tng_data
->last_pgp_signature
)
2181 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2182 __FILE__
, __LINE__
);
2183 return(TNG_CRITICAL
);
2185 tng_data
->last_pgp_signature
[0] = 0;
2187 if(!tng_data
->forcefield_name
)
2189 tng_data
->forcefield_name
= (char *)malloc(1);
2190 if(!tng_data
->forcefield_name
)
2192 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2193 __FILE__
, __LINE__
);
2194 return(TNG_CRITICAL
);
2196 tng_data
->forcefield_name
[0] = 0;
2199 first_program_name_len
= tng_min_size(strlen(tng_data
->first_program_name
) + 1,
2201 last_program_name_len
= tng_min_size(strlen(tng_data
->last_program_name
) + 1,
2203 first_user_name_len
= tng_min_size(strlen(tng_data
->first_user_name
) + 1,
2205 last_user_name_len
= tng_min_size(strlen(tng_data
->last_user_name
) + 1,
2207 first_computer_name_len
= tng_min_size(strlen(tng_data
->first_computer_name
) + 1,
2209 last_computer_name_len
= tng_min_size(strlen(tng_data
->last_computer_name
) + 1,
2211 first_pgp_signature_len
= tng_min_size(strlen(tng_data
->first_pgp_signature
) + 1,
2213 last_pgp_signature_len
= tng_min_size(strlen(tng_data
->last_pgp_signature
) + 1,
2215 forcefield_name_len
= tng_min_size(strlen(tng_data
->forcefield_name
) + 1,
2218 *len
= sizeof(tng_data
->time
) +
2219 sizeof(tng_data
->var_num_atoms_flag
) +
2220 sizeof(tng_data
->frame_set_n_frames
) +
2221 sizeof(tng_data
->first_trajectory_frame_set_input_file_pos
) +
2222 sizeof(tng_data
->last_trajectory_frame_set_input_file_pos
) +
2223 sizeof(tng_data
->medium_stride_length
) +
2224 sizeof(tng_data
->long_stride_length
) +
2225 sizeof(tng_data
->distance_unit_exponential
) +
2226 first_program_name_len
+
2227 last_program_name_len
+
2228 first_user_name_len
+
2229 last_user_name_len
+
2230 first_computer_name_len
+
2231 last_computer_name_len
+
2232 first_pgp_signature_len
+
2233 last_pgp_signature_len
+
2234 forcefield_name_len
;
2236 return(TNG_SUCCESS
);
2240 * @brief Read a general info block. This is the first block of a TNG file.
2241 * Populate the fields in tng_data.
2242 * @param tng_data is a trajectory data container.
2243 * @param block is a general block container.
2244 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2245 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2246 * compared to the md5 hash of the read contents to ensure valid data.
2247 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2248 * error has occured.
2250 static tng_function_status tng_general_info_block_read
2251 (const tng_trajectory_t tng_data
,
2252 const tng_gen_block_t block
,
2253 const char hash_mode
)
2256 char hash
[TNG_MD5_HASH_LEN
];
2257 md5_state_t md5_state
;
2259 TNG_ASSERT(block
!= 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2261 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
2263 return(TNG_CRITICAL
);
2266 start_pos
= ftello(tng_data
->input_file
);
2268 if(hash_mode
== TNG_USE_HASH
)
2270 md5_init(&md5_state
);
2273 tng_freadstr(tng_data
, &tng_data
->first_program_name
, hash_mode
, &md5_state
, __LINE__
);
2275 tng_freadstr(tng_data
, &tng_data
->last_program_name
, hash_mode
, &md5_state
, __LINE__
);
2277 tng_freadstr(tng_data
, &tng_data
->first_user_name
, hash_mode
, &md5_state
, __LINE__
);
2279 tng_freadstr(tng_data
, &tng_data
->last_user_name
, hash_mode
, &md5_state
, __LINE__
);
2281 tng_freadstr(tng_data
, &tng_data
->first_computer_name
, hash_mode
, &md5_state
, __LINE__
);
2283 tng_freadstr(tng_data
, &tng_data
->last_computer_name
, hash_mode
, &md5_state
, __LINE__
);
2285 tng_freadstr(tng_data
, &tng_data
->first_pgp_signature
, hash_mode
, &md5_state
, __LINE__
);
2287 tng_freadstr(tng_data
, &tng_data
->last_pgp_signature
, hash_mode
, &md5_state
, __LINE__
);
2289 tng_freadstr(tng_data
, &tng_data
->forcefield_name
, hash_mode
, &md5_state
, __LINE__
);
2291 if(tng_file_input_numerical(tng_data
, &tng_data
->time
, sizeof(tng_data
->time
),
2292 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2294 return(TNG_CRITICAL
);
2298 if(tng_file_input_numerical(tng_data
, &tng_data
->var_num_atoms_flag
,
2299 sizeof(tng_data
->var_num_atoms_flag
),
2300 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2302 return(TNG_CRITICAL
);
2305 if(tng_file_input_numerical(tng_data
, &tng_data
->frame_set_n_frames
,
2306 sizeof(tng_data
->frame_set_n_frames
),
2307 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2309 return(TNG_CRITICAL
);
2312 if(tng_file_input_numerical(tng_data
,
2313 &tng_data
->first_trajectory_frame_set_input_file_pos
,
2314 sizeof(tng_data
->first_trajectory_frame_set_input_file_pos
),
2315 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2317 return(TNG_CRITICAL
);
2320 tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
=
2321 tng_data
->first_trajectory_frame_set_input_file_pos
;
2323 if(tng_file_input_numerical(tng_data
,
2324 &tng_data
->last_trajectory_frame_set_input_file_pos
,
2325 sizeof(tng_data
->last_trajectory_frame_set_input_file_pos
),
2326 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2328 return(TNG_CRITICAL
);
2331 if(tng_file_input_numerical(tng_data
,
2332 &tng_data
->medium_stride_length
,
2333 sizeof(tng_data
->medium_stride_length
),
2334 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2336 return(TNG_CRITICAL
);
2339 if(tng_file_input_numerical(tng_data
,
2340 &tng_data
->long_stride_length
,
2341 sizeof(tng_data
->long_stride_length
),
2342 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2344 return(TNG_CRITICAL
);
2347 if(block
->block_version
>= 3)
2349 if(tng_file_input_numerical(tng_data
,
2350 &tng_data
->distance_unit_exponential
,
2351 sizeof(tng_data
->distance_unit_exponential
),
2352 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2354 return(TNG_CRITICAL
);
2358 if(hash_mode
== TNG_USE_HASH
)
2360 /* If there is data left in the block that the current version of the library
2361 * cannot interpret still read that to generate the MD5 hash. */
2362 tng_md5_remaining_append(tng_data
, block
, start_pos
, &md5_state
);
2364 md5_finish(&md5_state
, (md5_byte_t
*)hash
);
2365 if(strncmp(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN
) != 0)
2367 if(strncmp(block
->md5_hash
, hash
, TNG_MD5_HASH_LEN
) != 0)
2369 fprintf(stderr
, "TNG library: General info block contents corrupt. Hashes do not match. "
2370 "%s: %d\n", __FILE__
, __LINE__
);
2376 /* Seek to the end of the block */
2377 fseeko(tng_data
->input_file
, start_pos
+ block
->block_contents_size
, SEEK_SET
);
2380 return(TNG_SUCCESS
);
2384 * @brief Write a general info block. This is the first block of a TNG file.
2385 * @param tng_data is a trajectory data container.
2386 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2387 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2388 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2389 * error has occured.
2391 static tng_function_status tng_general_info_block_write
2392 (const tng_trajectory_t tng_data
,
2393 const char hash_mode
)
2395 int64_t header_file_pos
, curr_file_pos
;
2397 tng_gen_block_t block
;
2398 md5_state_t md5_state
;
2400 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
2402 return(TNG_CRITICAL
);
2405 fseeko(tng_data
->output_file
, 0, SEEK_SET
);
2407 tng_block_init(&block
);
2409 name_len
= strlen("GENERAL INFO");
2411 block
->name
= (char *)malloc(name_len
+ 1);
2414 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
2415 tng_block_destroy(&block
);
2416 return(TNG_CRITICAL
);
2419 strcpy(block
->name
, "GENERAL INFO");
2420 block
->id
= TNG_GENERAL_INFO
;
2422 if(tng_general_info_block_len_calculate(tng_data
, &block
->block_contents_size
) !=
2425 fprintf(stderr
, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2426 __FILE__
, __LINE__
);
2427 tng_block_destroy(&block
);
2428 return(TNG_CRITICAL
);
2431 header_file_pos
= 0;
2433 if(tng_block_header_write(tng_data
, block
) != TNG_SUCCESS
)
2435 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
2436 tng_data
->output_file_path
, __FILE__
, __LINE__
);
2437 tng_block_destroy(&block
);
2438 return(TNG_CRITICAL
);
2441 if(hash_mode
== TNG_USE_HASH
)
2443 md5_init(&md5_state
);
2446 if(tng_fwritestr(tng_data
, tng_data
->first_program_name
,
2447 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2449 return(TNG_CRITICAL
);
2452 if(tng_fwritestr(tng_data
, tng_data
->last_program_name
,
2453 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2455 return(TNG_CRITICAL
);
2458 if(tng_fwritestr(tng_data
, tng_data
->first_user_name
,
2459 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2461 return(TNG_CRITICAL
);
2464 if(tng_fwritestr(tng_data
, tng_data
->last_user_name
,
2465 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2467 return(TNG_CRITICAL
);
2470 if(tng_fwritestr(tng_data
, tng_data
->first_computer_name
,
2471 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2473 return(TNG_CRITICAL
);
2476 if(tng_fwritestr(tng_data
, tng_data
->last_computer_name
,
2477 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2479 return(TNG_CRITICAL
);
2482 if(tng_fwritestr(tng_data
, tng_data
->first_pgp_signature
,
2483 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2485 return(TNG_CRITICAL
);
2488 if(tng_fwritestr(tng_data
, tng_data
->last_pgp_signature
,
2489 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2491 return(TNG_CRITICAL
);
2494 if(tng_fwritestr(tng_data
, tng_data
->forcefield_name
,
2495 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2497 return(TNG_CRITICAL
);
2501 if(tng_file_output_numerical(tng_data
, &tng_data
->time
, sizeof(tng_data
->time
),
2502 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2504 return(TNG_CRITICAL
);
2507 if(tng_file_output_numerical(tng_data
, &tng_data
->var_num_atoms_flag
,
2508 sizeof(tng_data
->var_num_atoms_flag
),
2509 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2511 return(TNG_CRITICAL
);
2514 if(tng_file_output_numerical(tng_data
, &tng_data
->frame_set_n_frames
,
2515 sizeof(tng_data
->frame_set_n_frames
),
2516 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2518 return(TNG_CRITICAL
);
2521 if(tng_file_output_numerical(tng_data
, &tng_data
->first_trajectory_frame_set_output_file_pos
,
2522 sizeof(tng_data
->first_trajectory_frame_set_output_file_pos
),
2523 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2525 return(TNG_CRITICAL
);
2528 if(tng_file_output_numerical(tng_data
, &tng_data
->last_trajectory_frame_set_output_file_pos
,
2529 sizeof(tng_data
->last_trajectory_frame_set_output_file_pos
),
2530 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2532 return(TNG_CRITICAL
);
2535 if(tng_file_output_numerical(tng_data
, &tng_data
->medium_stride_length
,
2536 sizeof(tng_data
->medium_stride_length
),
2537 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2539 return(TNG_CRITICAL
);
2542 if(tng_file_output_numerical(tng_data
, &tng_data
->long_stride_length
,
2543 sizeof(tng_data
->long_stride_length
),
2544 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2546 return(TNG_CRITICAL
);
2549 if(tng_file_output_numerical(tng_data
, &tng_data
->distance_unit_exponential
,
2550 sizeof(tng_data
->distance_unit_exponential
),
2551 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2553 return(TNG_CRITICAL
);
2555 if(hash_mode
== TNG_USE_HASH
)
2557 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
2558 curr_file_pos
= ftello(tng_data
->output_file
);
2559 fseeko(tng_data
->output_file
, header_file_pos
+
2560 3 * sizeof(int64_t), SEEK_SET
);
2561 if(fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
) != 1)
2563 fprintf(stderr
, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__
,
2565 return(TNG_CRITICAL
);
2567 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
2570 tng_block_destroy(&block
);
2572 return(TNG_SUCCESS
);
2576 * @brief Read the chain data of a molecules block.
2577 * @param tng_data is a trajectory data container.
2578 * @param chain is the chain data container.
2579 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2580 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2581 * if hash_mode == TNG_USE_HASH.
2582 * @return TNG_SUCCESS(0) is successful.
2584 static tng_function_status
tng_chain_data_read(const tng_trajectory_t tng_data
,
2585 const tng_chain_t chain
,
2586 const char hash_mode
,
2587 md5_state_t
*md5_state
)
2589 if(tng_file_input_numerical(tng_data
, &chain
->id
,
2591 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2593 return(TNG_CRITICAL
);
2596 tng_freadstr(tng_data
, &chain
->name
, hash_mode
, md5_state
, __LINE__
);
2598 if(tng_file_input_numerical(tng_data
, &chain
->n_residues
,
2599 sizeof(chain
->n_residues
),
2600 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2602 return(TNG_CRITICAL
);
2605 return(TNG_SUCCESS
);
2609 * @brief Write the chain data of a molecules block.
2610 * @param tng_data is a trajectory data container.
2611 * @param chain is the chain data container.
2612 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2613 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2614 * if hash_mode == TNG_USE_HASH.
2615 * @return TNG_SUCCESS(0) is successful.
2617 static tng_function_status
tng_chain_data_write(const tng_trajectory_t tng_data
,
2618 const tng_chain_t chain
,
2619 const char hash_mode
,
2620 md5_state_t
*md5_state
)
2622 if(tng_file_output_numerical(tng_data
, &chain
->id
,
2624 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2626 return(TNG_CRITICAL
);
2629 if(tng_fwritestr(tng_data
, chain
->name
, hash_mode
,
2630 md5_state
, __LINE__
) == TNG_CRITICAL
)
2632 return(TNG_CRITICAL
);
2635 if(tng_file_output_numerical(tng_data
, &chain
->n_residues
,
2636 sizeof(chain
->n_residues
),
2637 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2639 return(TNG_CRITICAL
);
2642 return(TNG_SUCCESS
);
2646 * @brief Read the residue data of a molecules block.
2647 * @param tng_data is a trajectory data container.
2648 * @param residue is the residue data container.
2649 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2650 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2651 * if hash_mode == TNG_USE_HASH.
2652 * @return TNG_SUCCESS(0) is successful.
2654 static tng_function_status
tng_residue_data_read(const tng_trajectory_t tng_data
,
2655 const tng_residue_t residue
,
2656 const char hash_mode
,
2657 md5_state_t
*md5_state
)
2659 if(tng_file_input_numerical(tng_data
, &residue
->id
,
2660 sizeof(residue
->id
),
2661 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2663 return(TNG_CRITICAL
);
2666 tng_freadstr(tng_data
, &residue
->name
, hash_mode
, md5_state
, __LINE__
);
2668 if(tng_file_input_numerical(tng_data
, &residue
->n_atoms
,
2669 sizeof(residue
->n_atoms
),
2670 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2672 return(TNG_CRITICAL
);
2675 return(TNG_SUCCESS
);
2679 * @brief Write the residue data of a molecules block.
2680 * @param tng_data is a trajectory data container.
2681 * @param residue is the residue data container.
2682 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2683 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2684 * if hash_mode == TNG_USE_HASH.
2685 * @return TNG_SUCCESS(0) is successful.
2687 static tng_function_status
tng_residue_data_write(const tng_trajectory_t tng_data
,
2688 const tng_residue_t residue
,
2689 const char hash_mode
,
2690 md5_state_t
*md5_state
)
2692 if(tng_file_output_numerical(tng_data
, &residue
->id
,
2693 sizeof(residue
->id
),
2694 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2696 return(TNG_CRITICAL
);
2699 if(tng_fwritestr(tng_data
, residue
->name
, hash_mode
,
2700 md5_state
, __LINE__
) == TNG_CRITICAL
)
2702 return(TNG_CRITICAL
);
2705 if(tng_file_output_numerical(tng_data
, &residue
->n_atoms
,
2706 sizeof(residue
->n_atoms
),
2707 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2709 return(TNG_CRITICAL
);
2712 return(TNG_SUCCESS
);
2716 * @brief Read the atom data of a molecules block.
2717 * @param tng_data is a trajectory data container.
2718 * @param atom is the atom data container.
2719 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2720 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2721 * if hash_mode == TNG_USE_HASH.
2722 * @return TNG_SUCCESS(0) is successful.
2724 static tng_function_status
tng_atom_data_read(const tng_trajectory_t tng_data
,
2725 const tng_atom_t atom
,
2726 const char hash_mode
,
2727 md5_state_t
*md5_state
)
2729 if(tng_file_input_numerical(tng_data
, &atom
->id
,
2731 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2733 return(TNG_CRITICAL
);
2736 tng_freadstr(tng_data
, &atom
->name
, hash_mode
, md5_state
, __LINE__
);
2738 tng_freadstr(tng_data
, &atom
->atom_type
, hash_mode
, md5_state
, __LINE__
);
2740 return(TNG_SUCCESS
);
2744 * @brief Write the atom data of a molecules block.
2745 * @param tng_data is a trajectory data container.
2746 * @param atom is the atom data container.
2747 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2748 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2749 * if hash_mode == TNG_USE_HASH.
2750 * @return TNG_SUCCESS(0) is successful.
2752 static tng_function_status
tng_atom_data_write(const tng_trajectory_t tng_data
,
2753 const tng_atom_t atom
,
2754 const char hash_mode
,
2755 md5_state_t
*md5_state
)
2757 if(tng_file_output_numerical(tng_data
, &atom
->id
,
2759 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
2761 return(TNG_CRITICAL
);
2764 if(tng_fwritestr(tng_data
, atom
->name
, hash_mode
,
2765 md5_state
, __LINE__
) == TNG_CRITICAL
)
2767 return(TNG_CRITICAL
);
2770 if(tng_fwritestr(tng_data
, atom
->atom_type
, hash_mode
,
2771 md5_state
, __LINE__
) == TNG_CRITICAL
)
2773 return(TNG_CRITICAL
);
2776 return(TNG_SUCCESS
);
2779 static tng_function_status tng_molecules_block_len_calculate
2780 (const tng_trajectory_t tng_data
,
2784 tng_molecule_t molecule
;
2786 tng_residue_t residue
;
2792 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
2794 molecule
= &tng_data
->molecules
[i
];
2797 molecule
->name
= (char *)malloc(1);
2800 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2801 __FILE__
, __LINE__
);
2802 return(TNG_CRITICAL
);
2804 molecule
->name
[0] = 0;
2806 *len
+= tng_min_size(strlen(molecule
->name
) + 1, TNG_MAX_STR_LEN
);
2808 chain
= molecule
->chains
;
2809 for(j
= 0; j
< molecule
->n_chains
; j
++)
2811 *len
+= sizeof(chain
->id
);
2815 chain
->name
= (char *)malloc(1);
2818 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2819 __FILE__
, __LINE__
);
2820 return(TNG_CRITICAL
);
2824 *len
+= tng_min_size(strlen(chain
->name
) + 1, TNG_MAX_STR_LEN
);
2826 *len
+= sizeof(chain
->n_residues
);
2831 residue
= molecule
->residues
;
2832 for(j
= 0; j
< molecule
->n_residues
; j
++)
2834 *len
+= sizeof(residue
->id
);
2838 residue
->name
= (char *)malloc(1);
2841 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2842 __FILE__
, __LINE__
);
2843 return(TNG_CRITICAL
);
2845 residue
->name
[0] = 0;
2847 *len
+= tng_min_size(strlen(residue
->name
) + 1, TNG_MAX_STR_LEN
);
2849 *len
+= sizeof(residue
->n_atoms
);
2854 atom
= molecule
->atoms
;
2855 for(j
= 0; j
< molecule
->n_atoms
; j
++)
2857 *len
+= sizeof(atom
->id
);
2860 atom
->name
= (char *)malloc(1);
2863 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2864 __FILE__
, __LINE__
);
2865 return(TNG_CRITICAL
);
2869 *len
+= tng_min_size(strlen(atom
->name
) + 1, TNG_MAX_STR_LEN
);
2871 if(!atom
->atom_type
)
2873 atom
->atom_type
= (char *)malloc(1);
2874 if(!atom
->atom_type
)
2876 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
2877 __FILE__
, __LINE__
);
2878 return(TNG_CRITICAL
);
2880 atom
->atom_type
[0] = 0;
2882 *len
+= tng_min_size(strlen(atom
->atom_type
) + 1, TNG_MAX_STR_LEN
);
2887 for(j
= 0; j
< molecule
->n_bonds
; j
++)
2889 *len
+= sizeof(bond
->from_atom_id
) + sizeof(bond
->to_atom_id
);
2892 *len
+= sizeof(tng_data
->n_molecules
) +
2893 (sizeof(molecule
->id
) +
2894 sizeof(molecule
->quaternary_str
) +
2895 sizeof(molecule
->n_chains
) +
2896 sizeof(molecule
->n_residues
) +
2897 sizeof(molecule
->n_atoms
) +
2898 sizeof(molecule
->n_bonds
)) *
2899 tng_data
->n_molecules
;
2901 if(!tng_data
->var_num_atoms_flag
)
2903 *len
+= tng_data
->n_molecules
* sizeof(int64_t);
2906 return(TNG_SUCCESS
);
2910 * @brief Read a molecules block. Contains chain, residue and atom data
2911 * @param tng_data is a trajectory data container.
2912 * @param block is a general block container.
2913 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2914 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2915 * compared to the md5 hash of the read contents to ensure valid data.
2916 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2917 * error has occured.
2919 static tng_function_status tng_molecules_block_read
2920 (const tng_trajectory_t tng_data
,
2921 const tng_gen_block_t block
,
2922 const char hash_mode
)
2924 int64_t start_pos
, i
, j
, k
, l
;
2925 tng_molecule_t molecule
;
2927 tng_residue_t residue
;
2930 char hash
[TNG_MD5_HASH_LEN
];
2931 md5_state_t md5_state
;
2933 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
2935 return(TNG_CRITICAL
);
2938 start_pos
= ftello(tng_data
->input_file
);
2940 /* FIXME: Does not check if the size of the contents matches the expected
2941 * size or if the contents can be read. */
2943 if(tng_data
->molecules
)
2945 for(i
=0; i
<tng_data
->n_molecules
; i
++)
2947 tng_molecule_destroy(tng_data
, &tng_data
->molecules
[i
]);
2949 free(tng_data
->molecules
);
2950 tng_data
->molecules
= 0;
2951 tng_data
->n_molecules
= 0;
2954 if(hash_mode
== TNG_USE_HASH
)
2956 md5_init(&md5_state
);
2959 if(tng_file_input_numerical(tng_data
, &tng_data
->n_molecules
,
2960 sizeof(tng_data
->n_molecules
),
2961 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
2963 return(TNG_CRITICAL
);
2966 if(tng_data
->molecules
)
2968 free(tng_data
->molecules
);
2971 tng_data
->n_particles
= 0;
2973 tng_data
->molecules
= (struct tng_molecule
*)malloc(tng_data
->n_molecules
*
2974 sizeof(struct tng_molecule
));
2975 if(!tng_data
->molecules
)
2977 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
2978 return(TNG_CRITICAL
);
2981 if(!tng_data
->var_num_atoms_flag
)
2983 if(tng_data
->molecule_cnt_list
)
2985 free(tng_data
->molecule_cnt_list
);
2987 tng_data
->molecule_cnt_list
= (int64_t *)malloc(sizeof(int64_t) *
2988 tng_data
->n_molecules
);
2989 if(!tng_data
->molecule_cnt_list
)
2991 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
2992 return(TNG_CRITICAL
);
2996 /* Read each molecule from file */
2997 for(i
=0; i
< tng_data
->n_molecules
; i
++)
2999 molecule
= &tng_data
->molecules
[i
];
3003 if(tng_file_input_numerical(tng_data
, &molecule
->id
,
3004 sizeof(molecule
->id
),
3005 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3007 return(TNG_CRITICAL
);
3010 /* fprintf(stderr, "TNG library: Read id: %" PRId64 " offset: %d\n", molecule->id, offset);*/
3011 tng_freadstr(tng_data
, &molecule
->name
, hash_mode
, &md5_state
, __LINE__
);
3013 if(tng_file_input_numerical(tng_data
, &molecule
->quaternary_str
,
3014 sizeof(molecule
->quaternary_str
),
3015 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3017 return(TNG_CRITICAL
);
3020 if(!tng_data
->var_num_atoms_flag
)
3022 if(tng_file_input_numerical(tng_data
, &tng_data
->molecule_cnt_list
[i
],
3024 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3026 return(TNG_CRITICAL
);
3030 if(tng_file_input_numerical(tng_data
, &molecule
->n_chains
,
3031 sizeof(molecule
->n_chains
),
3032 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3034 return(TNG_CRITICAL
);
3037 if(tng_file_input_numerical(tng_data
, &molecule
->n_residues
,
3038 sizeof(molecule
->n_residues
),
3039 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3041 return(TNG_CRITICAL
);
3044 if(tng_file_input_numerical(tng_data
, &molecule
->n_atoms
,
3045 sizeof(molecule
->n_atoms
),
3046 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3048 return(TNG_CRITICAL
);
3051 tng_data
->n_particles
+= molecule
->n_atoms
*
3052 tng_data
->molecule_cnt_list
[i
];
3054 if(molecule
->n_chains
> 0)
3056 molecule
->chains
= (struct tng_chain
*)malloc(molecule
->n_chains
*
3057 sizeof(struct tng_chain
));
3058 if(!molecule
->chains
)
3060 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3061 __FILE__
, __LINE__
);
3062 return(TNG_CRITICAL
);
3065 chain
= molecule
->chains
;
3072 if(molecule
->n_residues
> 0)
3074 molecule
->residues
= (struct tng_residue
*)malloc(molecule
->n_residues
*
3075 sizeof(struct tng_residue
));
3076 if(!molecule
->residues
)
3078 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3079 __FILE__
, __LINE__
);
3080 if(molecule
->chains
)
3082 free(molecule
->chains
);
3083 molecule
->chains
= 0;
3085 return(TNG_CRITICAL
);
3088 residue
= molecule
->residues
;
3095 molecule
->atoms
= (struct tng_atom
*)malloc(molecule
->n_atoms
*
3096 sizeof(struct tng_atom
));
3097 if(!molecule
->atoms
)
3099 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3100 __FILE__
, __LINE__
);
3101 if(molecule
->chains
)
3103 free(molecule
->chains
);
3104 molecule
->chains
= 0;
3106 if(molecule
->residues
)
3108 free(molecule
->residues
);
3109 molecule
->residues
= 0;
3111 return(TNG_CRITICAL
);
3114 atom
= molecule
->atoms
;
3116 if(molecule
->n_chains
> 0)
3118 /* Read the chains of the molecule */
3119 for(j
=0; j
<molecule
->n_chains
; j
++)
3121 chain
->molecule
= molecule
;
3125 tng_chain_data_read(tng_data
, chain
, hash_mode
, &md5_state
);
3129 chain
->residues
= molecule
->residues
;
3130 residue
= chain
->residues
;
3134 chain
->residues
= residue
;
3137 /* Read the residues of the chain */
3138 for(k
=0; k
<chain
->n_residues
; k
++)
3140 residue
->chain
= chain
;
3144 tng_residue_data_read(tng_data
, residue
, hash_mode
, &md5_state
);
3146 residue
->atoms_offset
= atom
- molecule
->atoms
;
3147 /* Read the atoms of the residue */
3148 for(l
=0; l
<residue
->n_atoms
; l
++)
3150 atom
->residue
= residue
;
3153 atom
->atom_type
= 0;
3155 tng_atom_data_read(tng_data
,atom
, hash_mode
, &md5_state
);
3166 if(molecule
->n_residues
> 0)
3168 for(k
=0; k
<molecule
->n_residues
; k
++)
3174 tng_residue_data_read(tng_data
, residue
, hash_mode
, &md5_state
);
3176 residue
->atoms_offset
= atom
- molecule
->atoms
;
3177 /* Read the atoms of the residue */
3178 for(l
=0; l
<residue
->n_atoms
; l
++)
3180 atom
->residue
= residue
;
3182 tng_atom_data_read(tng_data
, atom
, hash_mode
, &md5_state
);
3191 for(l
=0; l
<molecule
->n_atoms
; l
++)
3196 atom
->atom_type
= 0;
3198 tng_atom_data_read(tng_data
, atom
, hash_mode
, &md5_state
);
3205 if(tng_file_input_numerical(tng_data
, &molecule
->n_bonds
,
3206 sizeof(molecule
->n_bonds
),
3207 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3209 return(TNG_CRITICAL
);
3212 if(molecule
->n_bonds
> 0)
3214 tng_data
->molecules
[i
].bonds
= (struct tng_bond
*)malloc(molecule
->n_bonds
*
3215 sizeof(struct tng_bond
));
3216 if(!molecule
->bonds
)
3218 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3219 __FILE__
, __LINE__
);
3220 if(molecule
->chains
)
3222 free(molecule
->chains
);
3223 molecule
->chains
= 0;
3225 if(molecule
->residues
)
3227 free(molecule
->residues
);
3228 molecule
->residues
= 0;
3232 free(molecule
->atoms
);
3233 molecule
->atoms
= 0;
3235 return(TNG_CRITICAL
);
3238 bond
= molecule
->bonds
;
3240 for(j
=0; j
<molecule
->n_bonds
; j
++)
3242 if(tng_file_input_numerical(tng_data
, &bond
->from_atom_id
,
3243 sizeof(bond
->from_atom_id
),
3244 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3246 return(TNG_CRITICAL
);
3249 if(tng_file_input_numerical(tng_data
, &bond
->to_atom_id
,
3250 sizeof(bond
->to_atom_id
),
3251 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3253 return(TNG_CRITICAL
);
3261 molecule
->bonds
= 0;
3265 if(hash_mode
== TNG_USE_HASH
)
3267 /* If there is data left in the block that the current version of the library
3268 * cannot interpret still read that to generate the MD5 hash. */
3269 tng_md5_remaining_append(tng_data
, block
, start_pos
, &md5_state
);
3271 md5_finish(&md5_state
, (md5_byte_t
*)hash
);
3272 if(strncmp(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN
) != 0)
3274 if(strncmp(block
->md5_hash
, hash
, TNG_MD5_HASH_LEN
) != 0)
3276 fprintf(stderr
, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3277 "%s: %d\n", __FILE__
, __LINE__
);
3284 /* Seek to the end of the block */
3285 fseeko(tng_data
->input_file
, start_pos
+ block
->block_contents_size
, SEEK_SET
);
3288 return(TNG_SUCCESS
);
3292 * @brief Write a molecules block.
3293 * @param tng_data is a trajectory data container.
3294 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3295 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3296 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3297 * error has occured.
3299 static tng_function_status tng_molecules_block_write
3300 (const tng_trajectory_t tng_data
,
3301 const char hash_mode
)
3304 int64_t i
, j
, k
, l
, header_file_pos
, curr_file_pos
;
3305 tng_molecule_t molecule
;
3307 tng_residue_t residue
;
3310 tng_gen_block_t block
;
3311 md5_state_t md5_state
;
3313 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
3315 return(TNG_CRITICAL
);
3318 tng_block_init(&block
);
3320 name_len
= (unsigned int)strlen("MOLECULES");
3322 block
->name
= (char *)malloc(name_len
+ 1);
3325 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__
, __LINE__
);
3326 tng_block_destroy(&block
);
3327 return(TNG_CRITICAL
);
3330 strcpy(block
->name
, "MOLECULES");
3331 block
->id
= TNG_MOLECULES
;
3333 if(tng_molecules_block_len_calculate(tng_data
, &block
->block_contents_size
) !=
3336 fprintf(stderr
, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3337 __FILE__
, __LINE__
);
3338 tng_block_destroy(&block
);
3339 return(TNG_CRITICAL
);
3342 header_file_pos
= ftello(tng_data
->output_file
);
3344 if(tng_block_header_write(tng_data
, block
) != TNG_SUCCESS
)
3346 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
3347 tng_data
->output_file_path
, __FILE__
, __LINE__
);
3348 tng_block_destroy(&block
);
3349 return(TNG_CRITICAL
);
3352 if(hash_mode
== TNG_USE_HASH
)
3354 md5_init(&md5_state
);
3357 if(tng_file_output_numerical(tng_data
, &tng_data
->n_molecules
,
3358 sizeof(tng_data
->n_molecules
),
3359 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3361 return(TNG_CRITICAL
);
3364 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
3366 molecule
= &tng_data
->molecules
[i
];
3368 if(tng_file_output_numerical(tng_data
, &molecule
->id
,
3369 sizeof(molecule
->id
),
3370 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3372 return(TNG_CRITICAL
);
3375 if(tng_fwritestr(tng_data
, molecule
->name
, hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3377 return(TNG_CRITICAL
);
3380 if(tng_file_output_numerical(tng_data
, &molecule
->quaternary_str
,
3381 sizeof(molecule
->quaternary_str
),
3382 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3384 return(TNG_CRITICAL
);
3387 if(!tng_data
->var_num_atoms_flag
)
3389 if(tng_file_output_numerical(tng_data
, &tng_data
->molecule_cnt_list
[i
],
3391 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3393 return(TNG_CRITICAL
);
3397 if(tng_file_output_numerical(tng_data
, &molecule
->n_chains
,
3398 sizeof(molecule
->n_chains
),
3399 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3401 return(TNG_CRITICAL
);
3404 if(tng_file_output_numerical(tng_data
, &molecule
->n_residues
,
3405 sizeof(molecule
->n_residues
),
3406 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3408 return(TNG_CRITICAL
);
3411 if(tng_file_output_numerical(tng_data
, &molecule
->n_atoms
,
3412 sizeof(molecule
->n_atoms
),
3413 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3415 return(TNG_CRITICAL
);
3418 if(molecule
->n_chains
> 0)
3420 chain
= molecule
->chains
;
3421 for(j
= 0; j
< molecule
->n_chains
; j
++)
3423 tng_chain_data_write(tng_data
, chain
, hash_mode
, &md5_state
);
3425 residue
= chain
->residues
;
3426 for(k
= 0; k
< chain
->n_residues
; k
++)
3428 tng_residue_data_write(tng_data
, residue
, hash_mode
, &md5_state
);
3430 atom
= molecule
->atoms
+ residue
->atoms_offset
;
3431 for(l
= 0; l
< residue
->n_atoms
; l
++)
3433 tng_atom_data_write(tng_data
, atom
, hash_mode
, &md5_state
);
3444 if(molecule
->n_residues
> 0)
3446 residue
= molecule
->residues
;
3447 for(k
= 0; k
< molecule
->n_residues
; k
++)
3449 tng_residue_data_write(tng_data
, residue
, hash_mode
, &md5_state
);
3451 atom
= molecule
->atoms
+ residue
->atoms_offset
;
3452 for(l
= 0; l
< residue
->n_atoms
; l
++)
3454 tng_atom_data_write(tng_data
, atom
, hash_mode
, &md5_state
);
3463 atom
= molecule
->atoms
;
3464 for(l
= 0; l
< molecule
->n_atoms
; l
++)
3466 tng_atom_data_write(tng_data
, atom
, hash_mode
, &md5_state
);
3473 if(tng_file_output_numerical(tng_data
, &molecule
->n_bonds
,
3474 sizeof(molecule
->n_bonds
),
3475 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3477 return(TNG_CRITICAL
);
3480 bond
= molecule
->bonds
;
3481 for(j
= 0; j
< molecule
->n_bonds
; j
++)
3483 if(tng_file_output_numerical(tng_data
, &bond
->from_atom_id
,
3484 sizeof(bond
->from_atom_id
),
3485 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3487 return(TNG_CRITICAL
);
3490 if(tng_file_output_numerical(tng_data
, &bond
->to_atom_id
,
3491 sizeof(bond
->to_atom_id
),
3492 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3494 return(TNG_CRITICAL
);
3500 if(hash_mode
== TNG_USE_HASH
)
3502 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
3503 curr_file_pos
= ftello(tng_data
->output_file
);
3504 fseeko(tng_data
->output_file
, header_file_pos
+
3505 3 * sizeof(int64_t), SEEK_SET
);
3506 if(fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
) != 1)
3508 fprintf(stderr
, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__
,
3510 return(TNG_CRITICAL
);
3512 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
3515 tng_block_destroy(&block
);
3517 return(TNG_SUCCESS
);
3520 static tng_function_status tng_frame_set_block_len_calculate
3521 (const tng_trajectory_t tng_data
,
3524 *len
= sizeof(int64_t) * 8;
3525 *len
+= sizeof(double) * 2;
3527 if(tng_data
->var_num_atoms_flag
)
3529 *len
+= sizeof(int64_t) * tng_data
->n_molecules
;
3531 return(TNG_SUCCESS
);
3535 * @brief Read a frame set block. Update tng_data->current_trajectory_frame_set
3536 * @param tng_data is a trajectory data container.
3537 * @param block is a general block container.
3538 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3539 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3540 * compared to the md5 hash of the read contents to ensure valid data.
3541 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3542 * error has occured.
3544 static tng_function_status tng_frame_set_block_read
3545 (tng_trajectory_t tng_data
,
3546 tng_gen_block_t block
,
3547 const char hash_mode
)
3549 int64_t file_pos
, start_pos
, i
, prev_n_particles
;
3550 tng_trajectory_frame_set_t frame_set
=
3551 &tng_data
->current_trajectory_frame_set
;
3552 char hash
[TNG_MD5_HASH_LEN
];
3553 md5_state_t md5_state
;
3555 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
3557 return(TNG_CRITICAL
);
3560 start_pos
= ftello(tng_data
->input_file
);
3562 /* FIXME: Does not check if the size of the contents matches the expected
3563 * size or if the contents can be read. */
3565 file_pos
= start_pos
- block
->header_contents_size
;
3567 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
3569 tng_frame_set_particle_mapping_free(tng_data
);
3571 if(hash_mode
== TNG_USE_HASH
)
3573 md5_init(&md5_state
);
3575 if(tng_file_input_numerical(tng_data
, &frame_set
->first_frame
,
3576 sizeof(frame_set
->first_frame
),
3577 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3579 return(TNG_CRITICAL
);
3582 if(tng_file_input_numerical(tng_data
, &frame_set
->n_frames
,
3583 sizeof(frame_set
->n_frames
),
3584 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3586 return(TNG_CRITICAL
);
3589 if(tng_data
->var_num_atoms_flag
)
3591 prev_n_particles
= frame_set
->n_particles
;
3592 frame_set
->n_particles
= 0;
3593 /* If the list of molecule counts has already been created assume that
3594 * it is of correct size. */
3595 if(!frame_set
->molecule_cnt_list
)
3597 frame_set
->molecule_cnt_list
=
3598 (int64_t *)malloc(sizeof(int64_t) * tng_data
->n_molecules
);
3600 if(!frame_set
->molecule_cnt_list
)
3602 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3603 __FILE__
, __LINE__
);
3604 return(TNG_CRITICAL
);
3607 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
3609 if(tng_file_input_numerical(tng_data
, &frame_set
->molecule_cnt_list
[i
],
3611 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3613 return(TNG_CRITICAL
);
3616 frame_set
->n_particles
+= tng_data
->molecules
[i
].n_atoms
*
3617 frame_set
->molecule_cnt_list
[i
];
3619 if(prev_n_particles
&& frame_set
->n_particles
!= prev_n_particles
)
3621 /* FIXME: Particle dependent data memory management */
3625 if(tng_file_input_numerical(tng_data
, &frame_set
->next_frame_set_file_pos
,
3626 sizeof(frame_set
->next_frame_set_file_pos
),
3627 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3629 return(TNG_CRITICAL
);
3632 if(tng_file_input_numerical(tng_data
, &frame_set
->prev_frame_set_file_pos
,
3633 sizeof(frame_set
->prev_frame_set_file_pos
),
3634 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3636 return(TNG_CRITICAL
);
3639 if(tng_file_input_numerical(tng_data
, &frame_set
->medium_stride_next_frame_set_file_pos
,
3640 sizeof(frame_set
->medium_stride_next_frame_set_file_pos
),
3641 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3643 return(TNG_CRITICAL
);
3646 if(tng_file_input_numerical(tng_data
, &frame_set
->medium_stride_prev_frame_set_file_pos
,
3647 sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
),
3648 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3650 return(TNG_CRITICAL
);
3653 if(tng_file_input_numerical(tng_data
, &frame_set
->long_stride_next_frame_set_file_pos
,
3654 sizeof(frame_set
->long_stride_next_frame_set_file_pos
),
3655 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3657 return(TNG_CRITICAL
);
3660 if(tng_file_input_numerical(tng_data
, &frame_set
->long_stride_prev_frame_set_file_pos
,
3661 sizeof(frame_set
->long_stride_prev_frame_set_file_pos
),
3662 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3664 return(TNG_CRITICAL
);
3667 if(block
->block_version
>= 3)
3669 if(tng_file_input_numerical(tng_data
, &frame_set
->first_frame_time
,
3670 sizeof(frame_set
->first_frame_time
),
3671 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3673 return(TNG_CRITICAL
);
3676 if(tng_file_input_numerical(tng_data
, &tng_data
->time_per_frame
,
3677 sizeof(tng_data
->time_per_frame
),
3678 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3680 return(TNG_CRITICAL
);
3685 frame_set
->first_frame_time
= -1;
3686 tng_data
->time_per_frame
= -1;
3689 if(hash_mode
== TNG_USE_HASH
)
3691 /* If there is data left in the block that the current version of the library
3692 * cannot interpret still read that to generate the MD5 hash. */
3693 tng_md5_remaining_append(tng_data
, block
, start_pos
, &md5_state
);
3695 md5_finish(&md5_state
, (md5_byte_t
*)hash
);
3696 if(strncmp(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN
) != 0)
3698 if(strncmp(block
->md5_hash
, hash
, TNG_MD5_HASH_LEN
) != 0)
3700 fprintf(stderr
, "TNG library: Frame set block contents corrupt (first frame %" PRId64
"). Hashes do not match. "
3701 "%s: %d\n", frame_set
->first_frame
, __FILE__
, __LINE__
);
3707 /* Seek to the end of the block */
3708 fseeko(tng_data
->input_file
, start_pos
+ block
->block_contents_size
, SEEK_SET
);
3711 /* If the output file and the input files are the same the number of
3712 * frames in the file are the same number as has just been read.
3713 * This is updated here to later on see if there have been new frames
3714 * added and thereby the frame set needs to be rewritten. */
3715 if(tng_data
->output_file
== tng_data
->input_file
)
3717 frame_set
->n_written_frames
= frame_set
->n_frames
;
3720 return(TNG_SUCCESS
);
3724 * @brief Write tng_data->current_trajectory_frame_set to file
3725 * @param tng_data is a trajectory data container.
3726 * @param block is a general block container.
3727 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3728 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3729 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3730 * error has occured.
3732 static tng_function_status tng_frame_set_block_write
3733 (const tng_trajectory_t tng_data
,
3734 const tng_gen_block_t block
,
3735 const char hash_mode
)
3738 int64_t i
, header_file_pos
, curr_file_pos
;
3739 unsigned int name_len
;
3740 tng_trajectory_frame_set_t frame_set
=
3741 &tng_data
->current_trajectory_frame_set
;
3742 md5_state_t md5_state
;
3744 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
3746 return(TNG_CRITICAL
);
3749 name_len
= (unsigned int)strlen("TRAJECTORY FRAME SET");
3751 if(!block
->name
|| strlen(block
->name
) < name_len
)
3753 temp_name
= (char *)realloc(block
->name
, name_len
+ 1);
3756 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3757 __FILE__
, __LINE__
);
3760 return(TNG_CRITICAL
);
3762 block
->name
= temp_name
;
3764 strcpy(block
->name
, "TRAJECTORY FRAME SET");
3765 block
->id
= TNG_TRAJECTORY_FRAME_SET
;
3767 if(tng_frame_set_block_len_calculate(tng_data
, &block
->block_contents_size
) !=
3770 fprintf(stderr
, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
3771 __FILE__
, __LINE__
);
3772 return(TNG_CRITICAL
);
3775 header_file_pos
= ftello(tng_data
->output_file
);
3777 if(tng_block_header_write(tng_data
, block
) != TNG_SUCCESS
)
3779 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
3780 tng_data
->output_file_path
, __FILE__
, __LINE__
);
3781 return(TNG_CRITICAL
);
3784 if(hash_mode
== TNG_USE_HASH
)
3786 md5_init(&md5_state
);
3788 if(tng_file_output_numerical(tng_data
, &frame_set
->first_frame
,
3789 sizeof(frame_set
->first_frame
),
3790 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3792 return(TNG_CRITICAL
);
3795 if(tng_file_output_numerical(tng_data
, &frame_set
->n_frames
,
3796 sizeof(frame_set
->n_frames
),
3797 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3799 return(TNG_CRITICAL
);
3802 if(tng_data
->var_num_atoms_flag
)
3804 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
3806 if(tng_file_output_numerical(tng_data
, &frame_set
->molecule_cnt_list
[i
],
3808 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3810 return(TNG_CRITICAL
);
3815 if(tng_file_output_numerical(tng_data
, &frame_set
->next_frame_set_file_pos
,
3816 sizeof(frame_set
->next_frame_set_file_pos
),
3817 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3819 return(TNG_CRITICAL
);
3822 if(tng_file_output_numerical(tng_data
, &frame_set
->prev_frame_set_file_pos
,
3823 sizeof(frame_set
->prev_frame_set_file_pos
),
3824 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3826 return(TNG_CRITICAL
);
3829 if(tng_file_output_numerical(tng_data
, &frame_set
->medium_stride_next_frame_set_file_pos
,
3830 sizeof(frame_set
->medium_stride_next_frame_set_file_pos
),
3831 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3833 return(TNG_CRITICAL
);
3836 if(tng_file_output_numerical(tng_data
, &frame_set
->medium_stride_prev_frame_set_file_pos
,
3837 sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
),
3838 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3840 return(TNG_CRITICAL
);
3843 if(tng_file_output_numerical(tng_data
, &frame_set
->long_stride_next_frame_set_file_pos
,
3844 sizeof(frame_set
->long_stride_next_frame_set_file_pos
),
3845 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3847 return(TNG_CRITICAL
);
3850 if(tng_file_output_numerical(tng_data
, &frame_set
->long_stride_prev_frame_set_file_pos
,
3851 sizeof(frame_set
->long_stride_prev_frame_set_file_pos
),
3852 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3854 return(TNG_CRITICAL
);
3857 if(tng_file_output_numerical(tng_data
, &frame_set
->first_frame_time
,
3858 sizeof(frame_set
->first_frame_time
),
3859 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3861 return(TNG_CRITICAL
);
3864 if(tng_file_output_numerical(tng_data
, &tng_data
->time_per_frame
,
3865 sizeof(tng_data
->time_per_frame
),
3866 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3868 return(TNG_CRITICAL
);
3870 if(hash_mode
== TNG_USE_HASH
)
3872 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
3873 curr_file_pos
= ftello(tng_data
->output_file
);
3874 fseeko(tng_data
->output_file
, header_file_pos
+
3875 3 * sizeof(int64_t), SEEK_SET
);
3876 if(fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
) != 1)
3878 fprintf(stderr
, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__
,
3880 return(TNG_CRITICAL
);
3882 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
3885 return(TNG_SUCCESS
);
3888 static tng_function_status tng_trajectory_mapping_block_len_calculate
3889 (const tng_trajectory_t tng_data
,
3890 const int64_t n_particles
,
3894 *len
= sizeof(int64_t) * (2 + n_particles
);
3896 return(TNG_SUCCESS
);
3900 * @brief Read an atom mappings block (translating between real atom indexes and how
3901 * the atom info is written in this frame set).
3902 * @param tng_data is a trajectory data container.
3903 * @param block is a general block container.
3904 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3905 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3906 * compared to the md5 hash of the read contents to ensure valid data.
3907 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3908 * error has occured.
3910 static tng_function_status tng_trajectory_mapping_block_read
3911 (const tng_trajectory_t tng_data
,
3912 const tng_gen_block_t block
,
3913 const char hash_mode
)
3915 int64_t start_pos
, i
;
3916 tng_trajectory_frame_set_t frame_set
=
3917 &tng_data
->current_trajectory_frame_set
;
3918 tng_particle_mapping_t mapping
, mappings
;
3919 char hash
[TNG_MD5_HASH_LEN
];
3920 md5_state_t md5_state
;
3922 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
3924 return(TNG_CRITICAL
);
3927 start_pos
= ftello(tng_data
->input_file
);
3929 /* FIXME: Does not check if the size of the contents matches the expected
3930 * size or if the contents can be read. */
3932 frame_set
->n_mapping_blocks
++;
3933 mappings
= (tng_particle_mapping_t
)realloc(frame_set
->mappings
,
3934 sizeof(struct tng_particle_mapping
) *
3935 frame_set
->n_mapping_blocks
);
3938 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3939 __FILE__
, __LINE__
);
3940 free(frame_set
->mappings
);
3941 frame_set
->mappings
= 0;
3942 return(TNG_CRITICAL
);
3944 frame_set
->mappings
= mappings
;
3945 mapping
= &mappings
[frame_set
->n_mapping_blocks
- 1];
3948 if(hash_mode
== TNG_USE_HASH
)
3950 md5_init(&md5_state
);
3953 if(tng_file_input_numerical(tng_data
, &mapping
->num_first_particle
,
3954 sizeof(mapping
->num_first_particle
),
3955 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3957 return(TNG_CRITICAL
);
3960 if(tng_file_input_numerical(tng_data
, &mapping
->n_particles
,
3961 sizeof(mapping
->n_particles
),
3962 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3964 return(TNG_CRITICAL
);
3967 mapping
->real_particle_numbers
= (int64_t *)malloc(mapping
->n_particles
*
3969 if(!mapping
->real_particle_numbers
)
3971 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
3972 __FILE__
, __LINE__
);
3973 return(TNG_CRITICAL
);
3976 /* If the byte order needs to be swapped the data must be read one value at
3977 * a time and swapped */
3978 if(tng_data
->input_endianness_swap_func_64
)
3980 for(i
= 0; i
< mapping
->n_particles
; i
++)
3982 if(tng_file_input_numerical(tng_data
, &mapping
->real_particle_numbers
[i
],
3984 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
3986 return(TNG_CRITICAL
);
3990 /* Otherwise the data can be read all at once */
3993 if(fread(mapping
->real_particle_numbers
, mapping
->n_particles
* sizeof(int64_t),
3994 1, tng_data
->input_file
) == 0)
3996 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
3997 return(TNG_CRITICAL
);
3999 if(hash_mode
== TNG_USE_HASH
)
4001 md5_append(&md5_state
, (md5_byte_t
*)mapping
->real_particle_numbers
, mapping
->n_particles
* sizeof(int64_t));
4005 if(hash_mode
== TNG_USE_HASH
)
4007 /* If there is data left in the block that the current version of the library
4008 * cannot interpret still read that to generate the MD5 hash. */
4009 tng_md5_remaining_append(tng_data
, block
, start_pos
, &md5_state
);
4011 md5_finish(&md5_state
, (md5_byte_t
*)hash
);
4012 if(strncmp(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN
) != 0)
4014 if(strncmp(block
->md5_hash
, hash
, TNG_MD5_HASH_LEN
) != 0)
4016 fprintf(stderr
, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4017 "%s: %d\n", __FILE__
, __LINE__
);
4023 /* Seek to the end of the block */
4024 fseeko(tng_data
->input_file
, start_pos
+ block
->block_contents_size
, SEEK_SET
);
4027 return(TNG_SUCCESS
);
4031 * @brief Write the atom mappings of the current trajectory frame set
4032 * @param tng_data is a trajectory data container.
4033 * @param block is a general block container.
4034 * @param mapping_block_nr is the index of the mapping block to write.
4035 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4036 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4037 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4038 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4040 static tng_function_status tng_trajectory_mapping_block_write
4041 (const tng_trajectory_t tng_data
,
4042 const tng_gen_block_t block
,
4043 const int mapping_block_nr
,
4044 const char hash_mode
)
4046 int64_t header_file_pos
, curr_file_pos
;
4049 unsigned int name_len
;
4050 md5_state_t md5_state
;
4051 tng_particle_mapping_t mapping
=
4052 &tng_data
->current_trajectory_frame_set
.mappings
[mapping_block_nr
];
4054 if(mapping_block_nr
>=
4055 tng_data
->current_trajectory_frame_set
.n_mapping_blocks
)
4057 fprintf(stderr
, "TNG library: Mapping block index out of bounds. %s: %d\n",
4058 __FILE__
, __LINE__
);
4059 return(TNG_FAILURE
);
4062 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
4064 return(TNG_CRITICAL
);
4067 name_len
= (unsigned int)strlen("PARTICLE MAPPING");
4069 if(!block
->name
|| strlen(block
->name
) < name_len
)
4071 temp_name
= (char *)realloc(block
->name
, name_len
+ 1);
4074 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4075 __FILE__
, __LINE__
);
4078 return(TNG_CRITICAL
);
4080 block
->name
= temp_name
;
4082 strcpy(block
->name
, "PARTICLE MAPPING");
4083 block
->id
= TNG_PARTICLE_MAPPING
;
4085 if(tng_trajectory_mapping_block_len_calculate(tng_data
,
4086 mapping
->n_particles
,
4087 &block
->block_contents_size
) !=
4090 fprintf(stderr
, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4091 __FILE__
, __LINE__
);
4092 return(TNG_CRITICAL
);
4095 header_file_pos
= ftello(tng_data
->output_file
);
4097 if(tng_block_header_write(tng_data
, block
) != TNG_SUCCESS
)
4099 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
4100 tng_data
->output_file_path
, __FILE__
, __LINE__
);
4101 return(TNG_CRITICAL
);
4104 if(hash_mode
== TNG_USE_HASH
)
4106 md5_init(&md5_state
);
4108 if(tng_file_output_numerical(tng_data
, &mapping
->num_first_particle
,
4109 sizeof(mapping
->num_first_particle
),
4110 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
4112 return(TNG_CRITICAL
);
4115 if(tng_file_output_numerical(tng_data
, &mapping
->n_particles
,
4116 sizeof(mapping
->n_particles
),
4117 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
4119 return(TNG_CRITICAL
);
4122 if(tng_data
->output_endianness_swap_func_64
)
4124 for(i
= 0; i
< mapping
->n_particles
; i
++)
4126 if(tng_file_output_numerical(tng_data
, &mapping
->real_particle_numbers
[i
],
4128 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
4130 return(TNG_CRITICAL
);
4136 if(fwrite(mapping
->real_particle_numbers
,
4137 mapping
->n_particles
* sizeof(int64_t),
4138 1, tng_data
->output_file
) != 1)
4140 fprintf(stderr
, "TNG library: Could not write block data. %s: %d\n", __FILE__
, __LINE__
);
4141 return(TNG_CRITICAL
);
4143 if(hash_mode
== TNG_USE_HASH
)
4145 md5_append(&md5_state
, (md5_byte_t
*)mapping
->real_particle_numbers
,
4146 mapping
->n_particles
* sizeof(int64_t));
4150 if(hash_mode
== TNG_USE_HASH
)
4152 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
4153 curr_file_pos
= ftello(tng_data
->output_file
);
4154 fseeko(tng_data
->output_file
, header_file_pos
+
4155 3 * sizeof(int64_t), SEEK_SET
);
4156 if(fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
) != 1)
4158 fprintf(stderr
, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__
,
4160 return(TNG_CRITICAL
);
4162 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
4165 return(TNG_SUCCESS
);
4169 * @brief Prepare a block for storing particle data
4170 * @param tng_data is a trajectory data container.
4171 * @param block_type_flag specifies if this is a trajectory block or a
4172 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4173 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4174 * error has occured.
4176 static tng_function_status tng_particle_data_block_create
4177 (const tng_trajectory_t tng_data
,
4178 const char block_type_flag
)
4180 tng_trajectory_frame_set_t frame_set
=
4181 &tng_data
->current_trajectory_frame_set
;
4185 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
4187 frame_set
->n_particle_data_blocks
++;
4188 data
= (tng_data_t
)realloc(frame_set
->tr_particle_data
,
4189 sizeof(struct tng_data
) *
4190 frame_set
->n_particle_data_blocks
);
4193 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4194 __FILE__
, __LINE__
);
4195 free(frame_set
->tr_particle_data
);
4196 frame_set
->tr_particle_data
= 0;
4197 return(TNG_CRITICAL
);
4199 frame_set
->tr_particle_data
= data
;
4203 tng_data
->n_particle_data_blocks
++;
4204 data
= (tng_data_t
)realloc(tng_data
->non_tr_particle_data
,
4205 sizeof(struct tng_data
) *
4206 tng_data
->n_particle_data_blocks
);
4209 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4210 __FILE__
, __LINE__
);
4211 free(tng_data
->non_tr_particle_data
);
4212 tng_data
->non_tr_particle_data
= 0;
4213 return(TNG_CRITICAL
);
4215 tng_data
->non_tr_particle_data
= data
;
4218 return(TNG_SUCCESS
);
4221 static tng_function_status
tng_compress(const tng_trajectory_t tng_data
,
4222 const tng_gen_block_t block
,
4223 const int64_t n_frames
,
4224 const int64_t n_particles
,
4233 int64_t algo_find_n_frames
= -1;
4237 if(block
->id
!= TNG_TRAJ_POSITIONS
&&
4238 block
->id
!= TNG_TRAJ_VELOCITIES
)
4240 fprintf(stderr
, "TNG library: Can only compress positions and velocities with the "
4241 "TNG method. %s: %d\n", __FILE__
, __LINE__
);
4242 return(TNG_FAILURE
);
4244 if(type
!= TNG_FLOAT_DATA
&& type
!= TNG_DOUBLE_DATA
)
4246 fprintf(stderr
, "TNG library: Data type not supported. %s: %d\n", __FILE__
, __LINE__
);
4247 return(TNG_FAILURE
);
4250 if(n_frames
<= 0 || n_particles
<= 0)
4252 fprintf(stderr
, "TNG library: Missing frames or particles. Cannot compress data "
4253 "with the TNG method. %s: %d\n", __FILE__
, __LINE__
);
4254 return(TNG_FAILURE
);
4257 f_precision
= 1/(float)tng_data
->compression_precision
;
4258 d_precision
= 1/tng_data
->compression_precision
;
4260 if(block
->id
== TNG_TRAJ_POSITIONS
)
4262 /* If there is only one frame in this frame set and there might be more
4263 * do not store the algorithm as the compression algorithm, but find
4264 * the best one without storing it */
4265 if(n_frames
== 1 && tng_data
->frame_set_n_frames
> 1)
4267 nalgo
= tng_compress_nalgo();
4268 alt_algo
= (int *)malloc(nalgo
* sizeof *tng_data
->compress_algo_pos
);
4270 /* If we have already determined the initial coding and
4271 * initial coding parameter do not determine them again. */
4272 if(tng_data
->compress_algo_pos
)
4274 alt_algo
[0] = tng_data
->compress_algo_pos
[0];
4275 alt_algo
[1] = tng_data
->compress_algo_pos
[1];
4276 alt_algo
[2] = tng_data
->compress_algo_pos
[2];
4277 alt_algo
[3] = tng_data
->compress_algo_pos
[3];
4287 /* If the initial coding and initial coding parameter are -1
4288 * they will be determined in tng_compress_pos/_float/. */
4289 if(type
== TNG_FLOAT_DATA
)
4291 dest
= tng_compress_pos_float((float *)*data
, (int)n_particles
,
4300 dest
= tng_compress_pos((double *)*data
, (int)n_particles
,
4306 /* If there had been no algorithm determined before keep the initial coding
4307 * and initial coding parameter so that they won't have to be determined again. */
4308 if(!tng_data
->compress_algo_pos
)
4310 nalgo
= tng_compress_nalgo();
4311 tng_data
->compress_algo_pos
= (int *)malloc(nalgo
*
4312 sizeof *tng_data
->compress_algo_pos
);
4313 tng_data
->compress_algo_pos
[0] = alt_algo
[0];
4314 tng_data
->compress_algo_pos
[1] = alt_algo
[1];
4315 tng_data
->compress_algo_pos
[2] = -1;
4316 tng_data
->compress_algo_pos
[3] = -1;
4319 else if(!tng_data
->compress_algo_pos
|| tng_data
->compress_algo_pos
[2] == -1 ||
4320 tng_data
->compress_algo_pos
[2] == -1)
4324 algo_find_n_frames
= 5;
4328 algo_find_n_frames
= n_frames
;
4331 /* If the algorithm parameters are -1 they will be determined during the
4333 if(!tng_data
->compress_algo_pos
)
4335 nalgo
= tng_compress_nalgo();
4336 tng_data
->compress_algo_pos
= (int *)malloc(nalgo
*
4337 sizeof *tng_data
->compress_algo_pos
);
4338 tng_data
->compress_algo_pos
[0] = -1;
4339 tng_data
->compress_algo_pos
[1] = -1;
4340 tng_data
->compress_algo_pos
[2] = -1;
4341 tng_data
->compress_algo_pos
[3] = -1;
4343 if(type
== TNG_FLOAT_DATA
)
4345 dest
= tng_compress_pos_float((float *)*data
, (int)n_particles
,
4346 (int)algo_find_n_frames
,
4352 if(algo_find_n_frames
< n_frames
)
4355 dest
= tng_compress_pos_float((float *)*data
, (int)n_particles
,
4358 0, tng_data
->compress_algo_pos
,
4364 dest
= tng_compress_pos((double *)*data
, (int)n_particles
,
4365 (int)algo_find_n_frames
,
4371 if(algo_find_n_frames
< n_frames
)
4374 dest
= tng_compress_pos((double *)*data
, (int)n_particles
,
4377 tng_data
->compress_algo_pos
,
4384 if(type
== TNG_FLOAT_DATA
)
4386 dest
= tng_compress_pos_float((float *)*data
, (int)n_particles
,
4389 tng_data
->compress_algo_pos
, &compressed_len
);
4393 dest
= tng_compress_pos((double *)*data
, (int)n_particles
,
4396 tng_data
->compress_algo_pos
,
4401 else if(block
->id
== TNG_TRAJ_VELOCITIES
)
4403 /* If there is only one frame in this frame set and there might be more
4404 * do not store the algorithm as the compression algorithm, but find
4405 * the best one without storing it */
4406 if(n_frames
== 1 && tng_data
->frame_set_n_frames
> 1)
4408 nalgo
= tng_compress_nalgo();
4409 alt_algo
= (int *)malloc(nalgo
* sizeof *tng_data
->compress_algo_vel
);
4411 /* If we have already determined the initial coding and
4412 * initial coding parameter do not determine them again. */
4413 if(tng_data
->compress_algo_vel
)
4415 alt_algo
[0] = tng_data
->compress_algo_vel
[0];
4416 alt_algo
[1] = tng_data
->compress_algo_vel
[1];
4417 alt_algo
[2] = tng_data
->compress_algo_vel
[2];
4418 alt_algo
[3] = tng_data
->compress_algo_vel
[3];
4428 /* If the initial coding and initial coding parameter are -1
4429 * they will be determined in tng_compress_pos/_float/. */
4430 if(type
== TNG_FLOAT_DATA
)
4432 dest
= tng_compress_vel_float((float *)*data
, (int)n_particles
,
4441 dest
= tng_compress_vel((double *)*data
, (int)n_particles
,
4447 /* If there had been no algorithm determined before keep the initial coding
4448 * and initial coding parameter so that they won't have to be determined again. */
4449 if(!tng_data
->compress_algo_vel
)
4451 nalgo
= tng_compress_nalgo();
4452 tng_data
->compress_algo_vel
= (int *)malloc(nalgo
*
4453 sizeof *tng_data
->compress_algo_vel
);
4454 tng_data
->compress_algo_vel
[0] = alt_algo
[0];
4455 tng_data
->compress_algo_vel
[1] = alt_algo
[1];
4456 tng_data
->compress_algo_vel
[2] = -1;
4457 tng_data
->compress_algo_vel
[3] = -1;
4460 else if(!tng_data
->compress_algo_vel
|| tng_data
->compress_algo_vel
[2] == -1 ||
4461 tng_data
->compress_algo_vel
[2] == -1)
4465 algo_find_n_frames
= 5;
4469 algo_find_n_frames
= n_frames
;
4472 /* If the algorithm parameters are -1 they will be determined during the
4474 if(!tng_data
->compress_algo_vel
)
4476 nalgo
= tng_compress_nalgo();
4477 tng_data
->compress_algo_vel
= (int *)malloc(nalgo
*
4478 sizeof *tng_data
->compress_algo_vel
);
4479 tng_data
->compress_algo_vel
[0] = -1;
4480 tng_data
->compress_algo_vel
[1] = -1;
4481 tng_data
->compress_algo_vel
[2] = -1;
4482 tng_data
->compress_algo_vel
[3] = -1;
4484 if(type
== TNG_FLOAT_DATA
)
4486 dest
= tng_compress_vel_float((float *)*data
, (int)n_particles
,
4487 (int)algo_find_n_frames
,
4492 if(algo_find_n_frames
< n_frames
)
4495 dest
= tng_compress_vel_float((float *)*data
, (int)n_particles
,
4498 0, tng_data
->compress_algo_vel
,
4504 dest
= tng_compress_vel((double *)*data
, (int)n_particles
,
4505 (int)algo_find_n_frames
,
4510 if(algo_find_n_frames
< n_frames
)
4513 dest
= tng_compress_vel((double *)*data
, (int)n_particles
,
4516 0, tng_data
->compress_algo_vel
,
4523 if(type
== TNG_FLOAT_DATA
)
4525 dest
= tng_compress_vel_float((float *)*data
, (int)n_particles
,
4534 dest
= tng_compress_vel((double *)*data
, (int)n_particles
,
4545 fprintf(stderr
, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4546 return(TNG_FAILURE
);
4556 *data
= (char *)dest
;
4558 *new_len
= compressed_len
;
4560 return(TNG_SUCCESS
);
4563 static tng_function_status
tng_uncompress(const tng_trajectory_t tng_data
,
4564 const tng_gen_block_t block
,
4567 const int64_t uncompressed_len
)
4574 TNG_ASSERT(uncompressed_len
, "TNG library: The full length of the uncompressed data must be > 0.");
4576 if(block
->id
!= TNG_TRAJ_POSITIONS
&&
4577 block
->id
!= TNG_TRAJ_VELOCITIES
)
4579 fprintf(stderr
, "TNG library: Can only uncompress positions and velocities with the"
4581 return(TNG_FAILURE
);
4583 if(type
!= TNG_FLOAT_DATA
&& type
!= TNG_DOUBLE_DATA
)
4585 fprintf(stderr
, "TNG library: Data type not supported.\n");
4586 return(TNG_FAILURE
);
4589 if(type
== TNG_FLOAT_DATA
)
4591 f_dest
= (float *)malloc(uncompressed_len
);
4594 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4595 __FILE__
, __LINE__
);
4596 return(TNG_CRITICAL
);
4598 result
= tng_compress_uncompress_float(*data
, f_dest
);
4602 *data
= (char *)f_dest
;
4606 d_dest
= (double *)malloc(uncompressed_len
);
4609 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4610 __FILE__
, __LINE__
);
4611 return(TNG_CRITICAL
);
4613 result
= tng_compress_uncompress(*data
, d_dest
);
4617 *data
= (char *)d_dest
;
4622 fprintf(stderr
, "TNG library: Cannot uncompress TNG compressed block.\n");
4623 return(TNG_FAILURE
);
4626 return(TNG_SUCCESS
);
4629 static tng_function_status
tng_gzip_compress(const tng_trajectory_t tng_data
,
4630 char **data
, const int64_t len
,
4634 uLongf stat
, max_len
;
4637 max_len
= compressBound(len
);
4638 dest
= (Bytef
*)malloc(max_len
);
4641 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4642 __FILE__
, __LINE__
);
4643 return(TNG_CRITICAL
);
4646 stat
= compress(dest
, &max_len
, (Bytef
*)*data
, len
);
4647 if(stat
!= (unsigned long)Z_OK
)
4650 if(stat
== (unsigned long)Z_MEM_ERROR
)
4652 fprintf(stderr
, "TNG library: Not enough memory. ");
4654 else if(stat
== (unsigned long)Z_BUF_ERROR
)
4656 fprintf(stderr
, "TNG library: Destination buffer too small. ");
4658 fprintf(stderr
, "TNG library: Error gzipping data. %s: %d\n", __FILE__
, __LINE__
);
4659 return(TNG_FAILURE
);
4666 *data
= (char *)dest
;
4668 return(TNG_SUCCESS
);
4671 static tng_function_status
tng_gzip_uncompress(const tng_trajectory_t tng_data
,
4673 const int64_t compressed_len
,
4674 const int64_t uncompressed_len
)
4679 uLongf new_len
= uncompressed_len
;
4681 dest
= (Bytef
*)malloc(uncompressed_len
);
4684 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4685 __FILE__
, __LINE__
);
4686 return(TNG_CRITICAL
);
4689 stat
= uncompress(dest
, &new_len
, (Bytef
*) *data
,
4695 if(stat
== (unsigned long)Z_MEM_ERROR
)
4697 fprintf(stderr
, "TNG library: Not enough memory. ");
4699 else if(stat
== (unsigned long)Z_BUF_ERROR
)
4701 fprintf(stderr
, "TNG library: Destination buffer too small. ");
4703 else if(stat
== (unsigned long)Z_DATA_ERROR
)
4705 fprintf(stderr
, "TNG library: Data corrupt. ");
4707 fprintf(stderr
, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__
,
4709 return(TNG_FAILURE
);
4714 *data
= (char *)dest
;
4716 return(TNG_SUCCESS
);
4720 * @brief Allocate memory for storing particle data.
4721 * The allocated block will be refered to by data->values.
4722 * @param tng_data is a trajectory data container.
4723 * @param data is the data struct, which will contain the allocated memory in
4725 * @param n_frames is the number of frames of data to store.
4726 * @param n_particles is the number of particles with data.
4727 * @param n_values_per_frame is the number of data values per particle and
4729 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4730 * error has occured.
4732 static tng_function_status tng_allocate_particle_data_mem
4733 (const tng_trajectory_t tng_data
,
4734 const tng_data_t data
,
4736 const int64_t stride_length
,
4737 const int64_t n_particles
,
4738 const int64_t n_values_per_frame
)
4741 int64_t i
, j
, k
, size
, frame_alloc
;
4744 if(n_particles
== 0 || n_values_per_frame
== 0)
4746 return(TNG_FAILURE
);
4749 if(data
->strings
&& data
->datatype
== TNG_CHAR_DATA
)
4751 for(i
= 0; i
< data
->n_frames
; i
++)
4753 for(j
= 0; j
< n_particles
; j
++)
4755 for(k
= 0; k
< data
->n_values_per_frame
; k
++)
4757 if(data
->strings
[i
][j
][k
])
4759 free(data
->strings
[i
][j
][k
]);
4762 free(data
->strings
[i
][j
]);
4764 free(data
->strings
[i
]);
4766 free(data
->strings
);
4768 data
->n_frames
= n_frames
;
4769 n_frames
= tng_max_i64(1, n_frames
);
4770 data
->stride_length
= tng_max_i64(1, stride_length
);
4771 data
->n_values_per_frame
= n_values_per_frame
;
4772 frame_alloc
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
4774 if(data
->datatype
== TNG_CHAR_DATA
)
4776 data
->strings
= (char ****)malloc(sizeof(char ***) * frame_alloc
);
4777 for(i
= 0; i
< frame_alloc
; i
++)
4779 data
->strings
[i
] = (char ***)malloc(sizeof(char **) *
4781 if(!data
->strings
[i
])
4783 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4784 __FILE__
, __LINE__
);
4785 return(TNG_CRITICAL
);
4787 for(j
= 0; j
< n_particles
; j
++)
4789 data
->strings
[i
][j
] = (char **)malloc(sizeof(char *) *
4790 n_values_per_frame
);
4791 if(!data
->strings
[i
][j
])
4793 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4794 __FILE__
, __LINE__
);
4795 return(TNG_CRITICAL
);
4797 for(k
= 0; k
< n_values_per_frame
; k
++)
4799 data
->strings
[i
][j
][k
] = 0;
4806 switch(data
->datatype
)
4809 size
= sizeof(int64_t);
4811 case TNG_FLOAT_DATA
:
4812 size
= sizeof(float);
4814 case TNG_DOUBLE_DATA
:
4816 size
= sizeof(double);
4819 values
= (void ***)realloc(data
->values
,
4820 size
* frame_alloc
*
4821 n_particles
* n_values_per_frame
);
4824 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
4825 __FILE__
, __LINE__
);
4828 return(TNG_CRITICAL
);
4830 data
->values
= values
;
4832 return(TNG_SUCCESS
);
4835 static tng_function_status tng_particle_data_find
4836 (const tng_trajectory_t tng_data
,
4840 int64_t block_index
, i
;
4841 tng_trajectory_frame_set_t frame_set
= &tng_data
->
4842 current_trajectory_frame_set
;
4843 char block_type_flag
;
4845 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0 ||
4846 tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
4848 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
4852 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
4856 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
4858 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
4860 *data
= &frame_set
->tr_particle_data
[i
];
4861 if((*data
)->block_id
== id
)
4870 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
4872 *data
= &tng_data
->non_tr_particle_data
[i
];
4873 if((*data
)->block_id
== id
)
4880 if(block_index
== -1)
4882 return(TNG_FAILURE
);
4884 return(TNG_SUCCESS
);
4887 static tng_function_status tng_data_find
4888 (const tng_trajectory_t tng_data
,
4892 int64_t block_index
, i
;
4893 tng_trajectory_frame_set_t frame_set
= &tng_data
->
4894 current_trajectory_frame_set
;
4895 char block_type_flag
;
4897 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0 ||
4898 tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
4900 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
4904 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
4908 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
4910 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
4912 *data
= &frame_set
->tr_data
[i
];
4913 if((*data
)->block_id
== id
)
4919 if(block_index
== -1)
4921 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
4923 *data
= &tng_data
->non_tr_data
[i
];
4924 if((*data
)->block_id
== id
)
4934 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
4936 *data
= &tng_data
->non_tr_data
[i
];
4937 if((*data
)->block_id
== id
)
4944 if(block_index
== -1)
4946 return(TNG_FAILURE
);
4948 return(TNG_SUCCESS
);
4951 static tng_function_status tng_data_block_len_calculate
4952 (const tng_trajectory_t tng_data
,
4953 const tng_data_t data
,
4954 const tng_bool is_particle_data
,
4955 const int64_t n_frames
,
4956 const int64_t frame_step
,
4957 const int64_t stride_length
,
4958 const int64_t num_first_particle
,
4959 const int64_t n_particles
,
4960 int64_t *data_start_pos
,
4965 char ***first_dim_values
, **second_dim_values
;
4970 return(TNG_SUCCESS
);
4973 switch(data
->datatype
)
4979 size
= sizeof(int64_t);
4981 case TNG_FLOAT_DATA
:
4982 size
= sizeof(float);
4984 case TNG_DOUBLE_DATA
:
4986 size
= sizeof(double);
4989 *len
= sizeof(char) * 2 + sizeof(data
->n_values_per_frame
) +
4990 sizeof(data
->codec_id
);
4991 if(is_particle_data
)
4993 *len
+= sizeof(num_first_particle
) + sizeof(n_particles
);
4996 if(stride_length
> 1)
4998 *len
+= sizeof(data
->first_frame_with_data
) +
4999 sizeof(data
->stride_length
);
5002 if(data
->codec_id
!= TNG_UNCOMPRESSED
)
5004 *len
+= sizeof(data
->compression_multiplier
);
5007 if(data
->dependency
& TNG_FRAME_DEPENDENT
)
5009 *len
+= sizeof(char);
5012 *data_start_pos
= *len
;
5014 if(data
->datatype
== TNG_CHAR_DATA
)
5016 if(is_particle_data
)
5018 for(i
= 0; i
< n_frames
; i
++)
5020 first_dim_values
= data
->strings
[i
];
5021 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
5024 second_dim_values
= first_dim_values
[j
];
5025 for(k
= 0; k
< data
->n_values_per_frame
; k
++)
5027 *len
+= strlen(second_dim_values
[k
]) + 1;
5034 for(i
= 0; i
< n_frames
; i
++)
5036 second_dim_values
= data
->strings
[0][i
];
5037 for(j
= 0; j
< data
->n_values_per_frame
; j
++)
5039 *len
+= strlen(second_dim_values
[j
]) + 1;
5046 *len
+= size
* frame_step
* n_particles
* data
->n_values_per_frame
;
5049 return(TNG_SUCCESS
);
5054 * @brief Create a non-particle data block
5055 * @param tng_data is a trajectory data container.
5056 * @param block_type_flag specifies if this is a trajectory block or a
5057 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
5058 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5059 * error has occured.
5061 static tng_function_status tng_data_block_create
5062 (const tng_trajectory_t tng_data
,
5063 const char block_type_flag
)
5065 tng_trajectory_frame_set_t frame_set
=
5066 &tng_data
->current_trajectory_frame_set
;
5070 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5072 frame_set
->n_data_blocks
++;
5073 data
= (tng_data_t
)realloc(frame_set
->tr_data
, sizeof(struct tng_data
) *
5074 frame_set
->n_data_blocks
);
5077 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5078 __FILE__
, __LINE__
);
5079 free(frame_set
->tr_data
);
5080 frame_set
->tr_data
= 0;
5081 return(TNG_CRITICAL
);
5083 frame_set
->tr_data
= data
;
5087 tng_data
->n_data_blocks
++;
5088 data
= (tng_data_t
)realloc(tng_data
->non_tr_data
, sizeof(struct tng_data
) *
5089 tng_data
->n_data_blocks
);
5092 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5093 __FILE__
, __LINE__
);
5094 free(tng_data
->non_tr_data
);
5095 tng_data
->non_tr_data
= 0;
5096 return(TNG_CRITICAL
);
5098 tng_data
->non_tr_data
= data
;
5101 return(TNG_SUCCESS
);
5106 * @brief Allocate memory for storing non-particle data.
5107 * The allocated block will be refered to by data->values.
5108 * @param tng_data is a trajectory data container.
5109 * @param data is the data struct, which will contain the allocated memory in
5111 * @param n_frames is the number of frames of data to store.
5112 * @param n_values_per_frame is the number of data values per frame.
5113 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5114 * error has occured.
5116 static tng_function_status tng_allocate_data_mem
5117 (const tng_trajectory_t tng_data
,
5118 const tng_data_t data
,
5120 const int64_t stride_length
,
5121 const int64_t n_values_per_frame
)
5124 int64_t i
, j
, size
, frame_alloc
;
5127 if(n_values_per_frame
== 0)
5129 return(TNG_FAILURE
);
5132 if(data
->strings
&& data
->datatype
== TNG_CHAR_DATA
)
5134 for(i
= 0; i
< data
->n_frames
; i
++)
5136 for(j
= 0; j
< data
->n_values_per_frame
; j
++)
5138 if(data
->strings
[0][i
][j
])
5140 free(data
->strings
[0][i
][j
]);
5141 data
->strings
[0][i
][j
] = 0;
5144 free(data
->strings
[0][i
]);
5145 data
->strings
[0][i
] = 0;
5147 free(data
->strings
[0]);
5148 data
->strings
[0] = 0;
5149 free(data
->strings
);
5151 data
->n_frames
= n_frames
;
5152 data
->stride_length
= tng_max_i64(1, stride_length
);
5153 n_frames
= tng_max_i64(1, n_frames
);
5154 data
->n_values_per_frame
= n_values_per_frame
;
5155 frame_alloc
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
5157 if(data
->datatype
== TNG_CHAR_DATA
)
5159 data
->strings
= (char ****)malloc(sizeof(char ***));
5160 data
->strings
[0] = (char ***)malloc(sizeof(char **) * frame_alloc
);
5161 for(i
= 0; i
< frame_alloc
; i
++)
5163 data
->strings
[0][i
] = (char **)malloc(sizeof(char *) * n_values_per_frame
);
5164 if(!data
->strings
[0][i
])
5166 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5167 __FILE__
, __LINE__
);
5168 return(TNG_CRITICAL
);
5170 for(j
= 0; j
< n_values_per_frame
; j
++)
5172 data
->strings
[0][i
][j
] = 0;
5178 switch(data
->datatype
)
5181 size
= sizeof(int64_t);
5183 case TNG_FLOAT_DATA
:
5184 size
= sizeof(float);
5186 case TNG_DOUBLE_DATA
:
5188 size
= sizeof(double);
5191 values
= (void **)realloc(data
->values
,
5192 size
* frame_alloc
*
5193 n_values_per_frame
);
5196 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5197 __FILE__
, __LINE__
);
5200 return(TNG_CRITICAL
);
5202 data
->values
= values
;
5205 return(TNG_SUCCESS
);
5209 * @brief Read the values of a data block
5210 * @param tng_data is a trajectory data container.
5211 * @param block is the block to store the data (should already contain
5212 * the block headers and the block contents).
5213 * @param block_data_len is the length of the data contents of the block.
5214 * @param datatype is the type of data of the data block (char, int, float or
5216 * @param num_first_particle is the number of the first particle in the data
5217 * block. This should be the same as in the corresponding particle mapping
5218 * block. Only used if reading particle dependent data.
5219 * @param n_particles is the number of particles in the data block. This should
5220 * be the same as in the corresponding particle mapping block. Only used if
5221 * reading particle dependent data.
5222 * @param first_frame_with_data is the frame number of the first frame with data
5223 * in this data block.
5224 * @param stride_length is the number of frames between each data entry.
5225 * @param n_frames is the number of frames in this data block.
5226 * @param n_values is the number of values per frame stored in this data block.
5227 * @param codec_id is the ID of the codec to compress the data.
5228 * @param multiplier is the multiplication factor applied to each data value
5229 * before compression. This factor is applied since some compression algorithms
5230 * work only on integers.
5231 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
5232 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
5233 * if hash_mode == TNG_USE_HASH.
5234 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5235 * error has occured.
5237 static tng_function_status
tng_data_read(const tng_trajectory_t tng_data
,
5238 const tng_gen_block_t block
,
5239 const int64_t block_data_len
,
5240 const char datatype
,
5241 const int64_t num_first_particle
,
5242 const int64_t n_particles
,
5243 const int64_t first_frame_with_data
,
5244 const int64_t stride_length
,
5246 const int64_t n_values
,
5247 const int64_t codec_id
,
5248 const double multiplier
,
5249 const char hash_mode
,
5250 md5_state_t
*md5_state
)
5252 int64_t i
, j
, k
, tot_n_particles
, n_frames_div
, offset
;
5253 int64_t full_data_len
;
5255 char ***first_dim_values
, **second_dim_values
;
5257 tng_trajectory_frame_set_t frame_set
=
5258 &tng_data
->current_trajectory_frame_set
;
5259 char block_type_flag
, *contents
;
5260 tng_bool is_particle_data
;
5261 tng_function_status stat
;
5263 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
5271 size
= sizeof(int64_t);
5273 case TNG_FLOAT_DATA
:
5274 size
= sizeof(float);
5276 case TNG_DOUBLE_DATA
:
5278 size
= sizeof(double);
5283 is_particle_data
= TNG_TRUE
;
5287 if(codec_id
== TNG_XTC_COMPRESSION
|| codec_id
== TNG_TNG_COMPRESSION
)
5289 fprintf(stderr
, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__
,
5291 return(TNG_FAILURE
);
5293 is_particle_data
= TNG_FALSE
;
5296 if(is_particle_data
== TNG_TRUE
)
5298 stat
= tng_particle_data_find(tng_data
, block
->id
, &data
);
5302 stat
= tng_data_find(tng_data
, block
->id
, &data
);
5305 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
5307 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
5311 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
5314 /* If the block does not exist, create it */
5315 if(stat
!= TNG_SUCCESS
)
5317 if(is_particle_data
== TNG_TRUE
)
5319 stat
= tng_particle_data_block_create(tng_data
, block_type_flag
);
5323 stat
= tng_data_block_create(tng_data
, block_type_flag
);
5326 if(stat
!= TNG_SUCCESS
)
5328 fprintf(stderr
, "TNG library: Cannot create data block. %s: %d\n",
5329 __FILE__
, __LINE__
);
5330 return(TNG_CRITICAL
);
5333 if(is_particle_data
== TNG_TRUE
)
5335 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5337 data
= &frame_set
->tr_particle_data
[frame_set
->
5338 n_particle_data_blocks
- 1];
5342 data
= &tng_data
->non_tr_particle_data
[tng_data
->
5343 n_particle_data_blocks
- 1];
5348 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5350 data
= &frame_set
->tr_data
[frame_set
->n_data_blocks
- 1];
5354 data
= &tng_data
->non_tr_data
[tng_data
->n_data_blocks
- 1];
5358 data
->block_id
= block
->id
;
5360 data
->block_name
= (char *)malloc(strlen(block
->name
) + 1);
5361 if(!data
->block_name
)
5363 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5364 __FILE__
, __LINE__
);
5365 return(TNG_CRITICAL
);
5367 strcpy(data
->block_name
, block
->name
);
5369 data
->datatype
= datatype
;
5372 /* FIXME: Memory leak from strings. */
5375 data
->dependency
= 0;
5376 if(is_particle_data
== TNG_TRUE
)
5378 data
->dependency
+= TNG_PARTICLE_DEPENDENT
;
5380 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
5382 frame_set
->n_frames
== n_frames
||
5385 data
->dependency
+= TNG_FRAME_DEPENDENT
;
5387 data
->codec_id
= codec_id
;
5388 data
->compression_multiplier
= multiplier
;
5389 data
->last_retrieved_frame
= -1;
5392 if(is_particle_data
== TNG_TRUE
)
5394 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
5395 tng_data
->var_num_atoms_flag
)
5397 tot_n_particles
= frame_set
->n_particles
;
5401 tot_n_particles
= tng_data
->n_particles
;
5404 /* If there are no particles in this data block, still set tot_n_particles = 1
5405 * to calculate block lengths etc properly. */
5408 tot_n_particles
= 1;
5411 n_frames_div
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
5413 contents
= (char *)malloc(block_data_len
);
5416 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5417 __FILE__
, __LINE__
);
5418 return(TNG_CRITICAL
);
5421 if(fread(contents
, block_data_len
, 1, tng_data
->input_file
) == 0)
5423 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
5424 return(TNG_CRITICAL
);
5427 if(hash_mode
== TNG_USE_HASH
)
5429 md5_append(md5_state
, (md5_byte_t
*)contents
, block_data_len
);
5432 if(codec_id
!= TNG_UNCOMPRESSED
)
5434 full_data_len
= n_frames_div
* size
* n_values
;
5435 if(is_particle_data
== TNG_TRUE
)
5437 full_data_len
*= n_particles
;
5441 case TNG_XTC_COMPRESSION
:
5442 fprintf(stderr
, "TNG library: XTC compression not implemented yet.\n");
5444 case TNG_TNG_COMPRESSION
:
5445 /* fprintf(stderr, "TNG library: Before TNG uncompression: %" PRId64 "\n", block->block_contents_size);*/
5446 if(tng_uncompress(tng_data
, block
, datatype
,
5447 &contents
, full_data_len
) != TNG_SUCCESS
)
5449 fprintf(stderr
, "TNG library: Could not read tng compressed block data. %s: %d\n",
5450 __FILE__
, __LINE__
);
5452 return(TNG_CRITICAL
);
5454 /* fprintf(stderr, "TNG library: After TNG uncompression: %" PRId64 "\n", block->block_contents_size);*/
5456 case TNG_GZIP_COMPRESSION
:
5457 /* fprintf(stderr, "TNG library: Before compression: %" PRId64 "\n", block->block_contents_size); */
5458 if(tng_gzip_uncompress(tng_data
, &contents
,
5459 block_data_len
, full_data_len
) != TNG_SUCCESS
)
5461 fprintf(stderr
, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__
,
5464 return(TNG_CRITICAL
);
5466 /* fprintf(stderr, "TNG library: After compression: %" PRId64 "\n", block->block_contents_size); */
5472 full_data_len
= block_data_len
;
5475 /* Allocate memory */
5476 if(!data
->values
|| data
->n_frames
!= n_frames
||
5477 data
->n_values_per_frame
!= n_values
)
5479 if(is_particle_data
== TNG_TRUE
)
5481 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
5483 tot_n_particles
, n_values
);
5487 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
, stride_length
,
5490 if(stat
!= TNG_SUCCESS
)
5492 fprintf(stderr
, "TNG library: Cannot allocate memory for data. %s: %d\n",
5493 __FILE__
, __LINE__
);
5495 return(TNG_CRITICAL
);
5499 data
->first_frame_with_data
= first_frame_with_data
;
5501 if(datatype
== TNG_CHAR_DATA
)
5504 /* Strings are stores slightly differently if the data block contains particle
5505 * data (frames * particles * n_values) or not (frames * n_values). */
5506 if(is_particle_data
== TNG_TRUE
)
5508 for(i
= 0; i
< n_frames_div
; i
++)
5510 first_dim_values
= data
->strings
[i
];
5511 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
5514 second_dim_values
= first_dim_values
[j
];
5515 for(k
= 0; k
< n_values
; k
++)
5517 len
= tng_min_size(strlen(contents
+offset
) + 1,
5519 if(second_dim_values
[k
])
5521 free(second_dim_values
[k
]);
5523 second_dim_values
[k
] = (char *)malloc(len
);
5524 if(!second_dim_values
[k
])
5526 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5527 __FILE__
, __LINE__
);
5529 return(TNG_CRITICAL
);
5531 strncpy(second_dim_values
[k
], contents
+offset
, len
);
5539 for(i
= 0; i
< n_frames_div
; i
++)
5541 for(j
= 0; j
< n_values
; j
++)
5543 len
= tng_min_size(strlen(contents
+offset
) + 1,
5545 if(data
->strings
[0][i
][j
])
5547 free(data
->strings
[0][i
][j
]);
5549 data
->strings
[0][i
][j
] = (char *)malloc(len
);
5550 if(!data
->strings
[0][i
][j
])
5552 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5553 __FILE__
, __LINE__
);
5555 return(TNG_CRITICAL
);
5557 strncpy(data
->strings
[0][i
][j
], contents
+offset
, len
);
5565 if(is_particle_data
)
5567 memcpy((char *)data
->values
+ n_frames_div
* size
* n_values
*
5568 num_first_particle
, contents
, full_data_len
);
5572 memcpy(data
->values
, contents
, full_data_len
);
5574 /* Endianness is handled by the TNG compression library. TNG compressed blocks are always written
5575 * as little endian by the compression library. */
5576 if(codec_id
!= TNG_TNG_COMPRESSION
)
5580 case TNG_FLOAT_DATA
:
5581 if(tng_data
->input_endianness_swap_func_32
)
5583 for(i
= 0; i
< full_data_len
; i
+=size
)
5585 if(tng_data
->input_endianness_swap_func_32(tng_data
,
5586 (uint32_t *)((char *)data
->values
+ i
))
5589 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
5590 __FILE__
, __LINE__
);
5596 case TNG_DOUBLE_DATA
:
5597 if(tng_data
->input_endianness_swap_func_64
)
5599 for(i
= 0; i
< full_data_len
; i
+=size
)
5601 if(tng_data
->input_endianness_swap_func_64(tng_data
,
5602 (uint64_t *)((char *)data
->values
+ i
))
5605 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
5606 __FILE__
, __LINE__
);
5619 return(TNG_SUCCESS
);
5623 * @brief Write a data block (particle or non-particle data)
5624 * @param tng_data is a trajectory data container.
5625 * @param block is the block to store the data (should already contain
5626 * the block headers and the block contents).
5627 * @param block_index is the index number of the data block in the frame set.
5628 * @param is_particle_data is a flag to specify if the data to write is
5629 * particle dependent or not.
5630 * @param mapping is the particle mapping that is relevant for the data block.
5631 * Only relevant if writing particle dependent data.
5632 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5633 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5634 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5635 * error has occured.
5637 static tng_function_status
tng_data_block_write(const tng_trajectory_t tng_data
,
5638 const tng_gen_block_t block
,
5639 const int64_t block_index
,
5640 const tng_bool is_particle_data
,
5641 const tng_particle_mapping_t mapping
,
5642 const char hash_mode
)
5644 int64_t n_particles
, num_first_particle
, n_frames
, stride_length
;
5645 int64_t full_data_len
, block_data_len
, frame_step
, data_start_pos
;
5646 int64_t i
, j
, k
, curr_file_pos
, header_file_pos
;
5649 tng_function_status stat
;
5650 char temp
, *temp_name
, ***first_dim_values
, **second_dim_values
, *contents
;
5652 tng_trajectory_frame_set_t frame_set
=
5653 &tng_data
->current_trajectory_frame_set
;
5655 char block_type_flag
;
5656 md5_state_t md5_state
;
5658 /* If we have already started writing frame sets it is too late to write
5659 * non-trajectory data blocks */
5660 if(tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
5662 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
5666 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
5669 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
5671 return(TNG_CRITICAL
);
5674 if(is_particle_data
== TNG_TRUE
)
5676 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5678 data
= &frame_set
->tr_particle_data
[block_index
];
5680 /* If this data block has not had any data added in this frame set
5681 * do not write it. */
5682 if(data
->first_frame_with_data
< frame_set
->first_frame
)
5684 return(TNG_SUCCESS
);
5687 stride_length
= tng_max_i64(1, data
->stride_length
);
5691 data
= &tng_data
->non_tr_particle_data
[block_index
];
5697 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5699 data
= &frame_set
->tr_data
[block_index
];
5701 /* If this data block has not had any data added in this frame set
5702 * do not write it. */
5703 if(data
->first_frame_with_data
< frame_set
->first_frame
)
5705 return(TNG_SUCCESS
);
5708 stride_length
= tng_max_i64(1, data
->stride_length
);
5712 data
= &tng_data
->non_tr_data
[block_index
];
5717 switch(data
->datatype
)
5723 size
= sizeof(int64_t);
5725 case TNG_FLOAT_DATA
:
5726 size
= sizeof(float);
5728 case TNG_DOUBLE_DATA
:
5730 size
= sizeof(double);
5733 len
= strlen(data
->block_name
) + 1;
5735 if(!block
->name
|| strlen(block
->name
) < len
)
5737 temp_name
= (char *)realloc(block
->name
, len
);
5740 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
5741 __FILE__
, __LINE__
);
5744 return(TNG_CRITICAL
);
5746 block
->name
= temp_name
;
5748 strncpy(block
->name
, data
->block_name
, len
);
5749 block
->id
= data
->block_id
;
5751 /* If writing frame independent data data->n_frames is 0, but n_frames
5752 is used for the loop writing the data (and reserving memory) and needs
5754 n_frames
= tng_max_i64(1, data
->n_frames
);
5756 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5758 /* If the frame set is finished before writing the full number of frames
5759 make sure the data block is not longer than the frame set. */
5760 n_frames
= tng_min_i64(n_frames
, frame_set
->n_frames
);
5762 n_frames
-= (data
->first_frame_with_data
- frame_set
->first_frame
);
5765 frame_step
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1:
5766 n_frames
/ stride_length
;
5768 /* TNG compression will use compression precision to get integers from
5769 * floating point data. The compression multiplier stores that information
5770 * to be able to return the precision of the compressed data. */
5771 if(data
->codec_id
== TNG_TNG_COMPRESSION
)
5773 data
->compression_multiplier
= tng_data
->compression_precision
;
5775 /* Uncompressed data blocks do not use compression multipliers at all.
5776 * GZip compression does not need it either. */
5777 else if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
->codec_id
== TNG_GZIP_COMPRESSION
)
5779 data
->compression_multiplier
= 1.0;
5782 if(data
->dependency
& TNG_PARTICLE_DEPENDENT
)
5784 if(mapping
&& mapping
->n_particles
!= 0)
5786 n_particles
= mapping
->n_particles
;
5787 num_first_particle
= mapping
->num_first_particle
;
5791 num_first_particle
= 0;
5792 if(tng_data
->var_num_atoms_flag
)
5794 n_particles
= frame_set
->n_particles
;
5798 n_particles
= tng_data
->n_particles
;
5804 /* This just appeases gcc-7 -Wmaybe-uninitialized.
5805 * FIXME: It would be better to refactor so that
5806 * TNG_PARTICLE_DEPENDENT triggers two distinct code paths.
5808 num_first_particle
= -1;
5812 if(data
->dependency
& TNG_PARTICLE_DEPENDENT
)
5814 if(tng_data_block_len_calculate(tng_data
, data
, TNG_TRUE
, n_frames
,
5815 frame_step
, stride_length
, num_first_particle
,
5816 n_particles
, &data_start_pos
,
5817 &block
->block_contents_size
) != TNG_SUCCESS
)
5819 fprintf(stderr
, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
5820 __FILE__
, __LINE__
);
5821 return(TNG_CRITICAL
);
5826 if(tng_data_block_len_calculate(tng_data
, data
, TNG_FALSE
, n_frames
,
5827 frame_step
, stride_length
, 0,
5829 &block
->block_contents_size
) != TNG_SUCCESS
)
5831 fprintf(stderr
, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
5832 __FILE__
, __LINE__
);
5833 return(TNG_CRITICAL
);
5837 header_file_pos
= ftello(tng_data
->output_file
);
5839 if(tng_block_header_write(tng_data
, block
) != TNG_SUCCESS
)
5841 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
5842 tng_data
->output_file_path
, __FILE__
, __LINE__
);
5843 return(TNG_CRITICAL
);
5846 if(hash_mode
== TNG_USE_HASH
)
5848 md5_init(&md5_state
);
5851 if(tng_file_output_numerical(tng_data
, &data
->datatype
,
5852 sizeof(data
->datatype
),
5853 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5855 return(TNG_CRITICAL
);
5858 if(tng_file_output_numerical(tng_data
, &data
->dependency
,
5859 sizeof(data
->dependency
),
5860 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5862 return(TNG_CRITICAL
);
5865 if(data
->dependency
& TNG_FRAME_DEPENDENT
)
5867 if(stride_length
> 1)
5875 if(tng_file_output_numerical(tng_data
, &temp
,
5877 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5879 return(TNG_CRITICAL
);
5883 if(tng_file_output_numerical(tng_data
, &data
->n_values_per_frame
,
5884 sizeof(data
->n_values_per_frame
),
5885 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5887 return(TNG_CRITICAL
);
5890 if(tng_file_output_numerical(tng_data
, &data
->codec_id
,
5891 sizeof(data
->codec_id
),
5892 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5894 return(TNG_CRITICAL
);
5897 if(data
->codec_id
!= TNG_UNCOMPRESSED
)
5899 if(tng_file_output_numerical(tng_data
, &data
->compression_multiplier
,
5900 sizeof(data
->compression_multiplier
),
5901 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5903 return(TNG_CRITICAL
);
5907 if(data
->n_frames
> 0 && stride_length
> 1)
5909 /* FIXME: first_frame_with_data is not reliably set */
5910 if(data
->first_frame_with_data
== 0)
5912 data
->first_frame_with_data
= frame_set
->first_frame
;
5914 if(tng_file_output_numerical(tng_data
, &data
->first_frame_with_data
,
5915 sizeof(data
->first_frame_with_data
),
5916 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5918 return(TNG_CRITICAL
);
5921 if(tng_file_output_numerical(tng_data
, &stride_length
,
5922 sizeof(stride_length
),
5923 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5925 return(TNG_CRITICAL
);
5929 if(data
->dependency
& TNG_PARTICLE_DEPENDENT
)
5931 if(tng_file_output_numerical(tng_data
, &num_first_particle
,
5932 sizeof(num_first_particle
),
5933 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5935 return(TNG_CRITICAL
);
5938 if(tng_file_output_numerical(tng_data
, &n_particles
,
5939 sizeof(n_particles
),
5940 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5942 return(TNG_CRITICAL
);
5946 if(data
->datatype
== TNG_CHAR_DATA
)
5950 if(data
->dependency
& TNG_PARTICLE_DEPENDENT
)
5952 for(i
= 0; i
< frame_step
; i
++)
5954 first_dim_values
= data
->strings
[i
];
5955 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
5958 second_dim_values
= first_dim_values
[j
];
5959 for(k
= 0; k
< data
->n_values_per_frame
; k
++)
5961 if(tng_fwritestr(tng_data
, second_dim_values
[k
],
5962 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5964 return(TNG_CRITICAL
);
5972 for(i
= 0; i
< frame_step
; i
++)
5974 for(j
= 0; j
< data
->n_values_per_frame
; j
++)
5976 if(tng_fwritestr(tng_data
, data
->strings
[0][i
][j
],
5977 hash_mode
, &md5_state
, __LINE__
) == TNG_CRITICAL
)
5979 return(TNG_CRITICAL
);
5988 if(data
->dependency
& TNG_PARTICLE_DEPENDENT
)
5990 full_data_len
= size
* frame_step
* n_particles
* data
->n_values_per_frame
;
5994 full_data_len
= size
* frame_step
* data
->n_values_per_frame
;
5996 contents
= (char *)malloc(full_data_len
);
5999 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
6000 __FILE__
, __LINE__
);
6001 return(TNG_CRITICAL
);
6006 memcpy(contents
, data
->values
, full_data_len
);
6007 /* If writing TNG compressed data the endianness is taken into account by the compression
6008 * routines. TNG compressed data is always written as little endian. */
6009 if(data
->codec_id
!= TNG_TNG_COMPRESSION
)
6011 switch(data
->datatype
)
6013 case TNG_FLOAT_DATA
:
6014 if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
->codec_id
== TNG_GZIP_COMPRESSION
)
6016 if(tng_data
->output_endianness_swap_func_32
)
6018 for(i
= 0; i
< full_data_len
; i
+=size
)
6020 if(tng_data
->output_endianness_swap_func_32(tng_data
,
6021 (uint32_t *)(contents
+ i
))
6024 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6025 __FILE__
, __LINE__
);
6032 multiplier
= data
->compression_multiplier
;
6033 if(fabs(multiplier
- 1.0) > 0.00001 ||
6034 tng_data
->output_endianness_swap_func_32
)
6036 for(i
= 0; i
< full_data_len
; i
+=size
)
6038 *(float *)(contents
+ i
) *= (float)multiplier
;
6039 if(tng_data
->output_endianness_swap_func_32
&&
6040 tng_data
->output_endianness_swap_func_32(tng_data
,
6041 (uint32_t *)(contents
+ i
))
6044 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6045 __FILE__
, __LINE__
);
6052 if(tng_data
->output_endianness_swap_func_64
)
6054 for(i
= 0; i
< full_data_len
; i
+=size
)
6056 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6057 (uint64_t *)(contents
+ i
))
6060 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6061 __FILE__
, __LINE__
);
6066 case TNG_DOUBLE_DATA
:
6067 if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
-> codec_id
== TNG_GZIP_COMPRESSION
)
6069 if(tng_data
->output_endianness_swap_func_64
)
6071 for(i
= 0; i
< full_data_len
; i
+=size
)
6073 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6074 (uint64_t *)(contents
+ i
))
6077 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6078 __FILE__
, __LINE__
);
6085 multiplier
= data
->compression_multiplier
;
6086 if(fabs(multiplier
- 1.0) > 0.00001 ||
6087 tng_data
->output_endianness_swap_func_64
)
6089 for(i
= 0; i
< full_data_len
; i
+=size
)
6091 *(double *)(contents
+ i
) *= multiplier
;
6092 if(tng_data
->output_endianness_swap_func_64
&&
6093 tng_data
->output_endianness_swap_func_64(tng_data
,
6094 (uint64_t *)(contents
+ i
))
6097 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6098 __FILE__
, __LINE__
);
6111 memset(contents
, 0, full_data_len
);
6114 block_data_len
= full_data_len
;
6116 switch(data
->codec_id
)
6118 case TNG_XTC_COMPRESSION
:
6119 fprintf(stderr
, "TNG library: XTC compression not implemented yet.\n");
6120 data
->codec_id
= TNG_UNCOMPRESSED
;
6122 case TNG_TNG_COMPRESSION
:
6123 stat
= tng_compress(tng_data
, block
, frame_step
,
6124 n_particles
, data
->datatype
,
6125 &contents
, &block_data_len
);
6126 if(stat
!= TNG_SUCCESS
)
6128 fprintf(stderr
, "TNG library: Could not write TNG compressed block data. %s: %d\n",
6129 __FILE__
, __LINE__
);
6130 if(stat
== TNG_CRITICAL
)
6132 return(TNG_CRITICAL
);
6134 /* Set the data again, but with no compression (to write only
6135 * the relevant data) */
6136 data
->codec_id
= TNG_UNCOMPRESSED
;
6137 stat
= tng_data_block_write(tng_data
, block
,
6138 block_index
, is_particle_data
, mapping
,
6144 case TNG_GZIP_COMPRESSION
:
6145 /* fprintf(stderr, "TNG library: Before compression: %" PRId64 "\n", block->block_contents_size); */
6146 stat
= tng_gzip_compress(tng_data
,
6150 if(stat
!= TNG_SUCCESS
)
6152 fprintf(stderr
, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__
,
6154 if(stat
== TNG_CRITICAL
)
6156 return(TNG_CRITICAL
);
6158 data
->codec_id
= TNG_UNCOMPRESSED
;
6160 /* fprintf(stderr, "TNG library: After compression: %" PRId64 "\n", block->block_contents_size); */
6163 if(block_data_len
!= full_data_len
)
6165 block
->block_contents_size
-= full_data_len
- block_data_len
;
6167 curr_file_pos
= ftello(tng_data
->output_file
);
6168 fseeko(tng_data
->output_file
, header_file_pos
+ sizeof(block
->header_contents_size
), SEEK_SET
);
6170 if(tng_file_output_numerical(tng_data
, &block
->block_contents_size
,
6171 sizeof(block
->block_contents_size
),
6172 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
6174 return(TNG_CRITICAL
);
6176 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
6178 if(fwrite(contents
, block_data_len
, 1, tng_data
->output_file
) != 1)
6180 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n", __FILE__
,
6182 return(TNG_CRITICAL
);
6184 if(hash_mode
== TNG_USE_HASH
)
6186 md5_append(&md5_state
, (md5_byte_t
*)contents
, block_data_len
);
6192 if(hash_mode
== TNG_USE_HASH
)
6194 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
6195 curr_file_pos
= ftello(tng_data
->output_file
);
6196 fseeko(tng_data
->output_file
, header_file_pos
+
6197 3 * sizeof(int64_t), SEEK_SET
);
6198 if(fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
) != 1)
6200 fprintf(stderr
, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__
,
6202 return(TNG_CRITICAL
);
6204 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
6207 frame_set
->n_written_frames
+= frame_set
->n_unwritten_frames
;
6208 frame_set
->n_unwritten_frames
= 0;
6210 return(TNG_SUCCESS
);
6214 * @brief Read the meta information of a data block (particle or non-particle data).
6215 * @param tng_data is a trajectory data container.
6216 * @param datatype is set to the datatype of the data block.
6217 * @param dependency is set to the dependency (particle and/or frame dependent)
6218 * @param sparse_data is set to TRUE if data is not written every frame.
6219 * @param n_values is set to the number of values per frame of the data.
6220 * @param codec_id is set to the ID of the codec used to compress the data.
6221 * @param first_frame_with_data is set to the first frame with data (only relevant if
6222 * sparse_data == TRUE).
6223 * @param stride_length is set to the writing interval of the data (1 if sparse_data
6225 * @param num_first_particle is set to the number of the first particle with data written
6227 * @param block_n_particles is set to the number of particles in this data block.
6228 * @param multiplier is set to the compression multiplier.
6229 * @param hash_mode specifies whether to check if the hash matches the contents or not.
6230 * @param md5_state is the md5 hash of the block (only used if hash_mode == TNG_USE_HASH).
6231 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6232 * error has occured.
6234 static tng_function_status tng_data_block_meta_information_read
6235 (const tng_trajectory_t tng_data
,
6241 int64_t *first_frame_with_data
,
6242 int64_t *stride_length
,
6244 int64_t *num_first_particle
,
6245 int64_t *block_n_particles
,
6247 const char hash_mode
,
6248 md5_state_t
*md5_state
)
6250 if(tng_file_input_numerical(tng_data
, datatype
,
6252 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6254 return(TNG_CRITICAL
);
6257 if(tng_file_input_numerical(tng_data
, dependency
,
6258 sizeof(*dependency
),
6259 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6261 return(TNG_CRITICAL
);
6264 if(*dependency
& TNG_FRAME_DEPENDENT
)
6266 if(tng_file_input_numerical(tng_data
, sparse_data
,
6267 sizeof(*sparse_data
),
6268 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6270 return(TNG_CRITICAL
);
6274 if(tng_file_input_numerical(tng_data
, n_values
,
6276 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6278 return(TNG_CRITICAL
);
6281 if(tng_file_input_numerical(tng_data
, codec_id
,
6283 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6285 return(TNG_CRITICAL
);
6288 if(*codec_id
!= TNG_UNCOMPRESSED
)
6290 if(tng_file_input_numerical(tng_data
, multiplier
,
6291 sizeof(*multiplier
),
6292 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6294 return(TNG_CRITICAL
);
6302 if(*dependency
& TNG_FRAME_DEPENDENT
)
6306 if(tng_file_input_numerical(tng_data
, first_frame_with_data
,
6307 sizeof(*first_frame_with_data
),
6308 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6310 return(TNG_CRITICAL
);
6313 if(tng_file_input_numerical(tng_data
, stride_length
,
6314 sizeof(*stride_length
),
6315 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6317 return(TNG_CRITICAL
);
6320 *n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
-
6321 (*first_frame_with_data
-
6322 tng_data
->current_trajectory_frame_set
.first_frame
);
6326 *first_frame_with_data
= tng_data
->current_trajectory_frame_set
.first_frame
;
6328 *n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
;
6333 *first_frame_with_data
= 0;
6338 if (*dependency
& TNG_PARTICLE_DEPENDENT
)
6340 if(tng_file_input_numerical(tng_data
, num_first_particle
,
6341 sizeof(*num_first_particle
),
6342 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6344 return(TNG_CRITICAL
);
6347 if(tng_file_input_numerical(tng_data
, block_n_particles
,
6348 sizeof(*block_n_particles
),
6349 hash_mode
, md5_state
, __LINE__
) == TNG_CRITICAL
)
6351 return(TNG_CRITICAL
);
6356 *num_first_particle
= -1;
6357 *block_n_particles
= 0;
6360 return(TNG_SUCCESS
);
6364 * @brief Read the contents of a data block (particle or non-particle data).
6365 * @param tng_data is a trajectory data container.
6366 * @param block is the block to store the data (should already contain
6367 * the block headers).
6368 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6369 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6370 * compared to the md5 hash of the read contents to ensure valid data.
6371 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6372 * error has occured.
6374 static tng_function_status tng_data_block_contents_read
6375 (const tng_trajectory_t tng_data
,
6376 const tng_gen_block_t block
,
6377 const char hash_mode
)
6379 int64_t start_pos
, n_values
, codec_id
, n_frames
, first_frame_with_data
;
6380 int64_t remaining_len
, stride_length
, block_n_particles
, num_first_particle
;
6382 char datatype
, dependency
, sparse_data
;
6383 tng_function_status stat
= TNG_SUCCESS
;
6384 char hash
[TNG_MD5_HASH_LEN
];
6385 md5_state_t md5_state
;
6387 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
6389 return(TNG_CRITICAL
);
6392 start_pos
= ftello(tng_data
->input_file
);
6394 if(hash_mode
== TNG_USE_HASH
)
6396 md5_init(&md5_state
);
6399 /* FIXME: Does not check if the size of the contents matches the expected
6400 * size or if the contents can be read. */
6402 if(tng_data_block_meta_information_read(tng_data
,
6404 &dependency
, &sparse_data
,
6405 &n_values
, &codec_id
,
6406 &first_frame_with_data
,
6407 &stride_length
, &n_frames
,
6408 &num_first_particle
,
6412 &md5_state
) == TNG_CRITICAL
)
6414 fprintf(stderr
, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6415 block
->name
, __FILE__
, __LINE__
);
6416 return(TNG_CRITICAL
);
6419 remaining_len
= block
->block_contents_size
- (ftello(tng_data
->input_file
) - start_pos
);
6421 stat
= tng_data_read(tng_data
, block
,
6426 first_frame_with_data
,
6429 codec_id
, multiplier
,
6433 if(hash_mode
== TNG_USE_HASH
)
6435 /* If there is data left in the block that the current version of the library
6436 * cannot interpret still read that to generate the MD5 hash. */
6437 tng_md5_remaining_append(tng_data
, block
, start_pos
, &md5_state
);
6439 md5_finish(&md5_state
, (md5_byte_t
*)hash
);
6440 if(strncmp(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN
) != 0)
6442 if(strncmp(block
->md5_hash
, hash
, TNG_MD5_HASH_LEN
) != 0)
6444 fprintf(stderr
, "TNG library: Data block contents corrupt (%s). Hashes do not match. "
6445 "%s: %d\n", block
->name
, __FILE__
, __LINE__
);
6451 /* Seek to the end of the block */
6452 fseeko(tng_data
->input_file
, start_pos
+ block
->block_contents_size
, SEEK_SET
);
6459 // ** Move the blocks in a frame set so that there is no unused space between
6460 // * them. This can only be done on the last frame set in the file and should
6461 // * be done e.g. if the last frame set in the file has fewer frames than
6462 // * default or after compressing data blocks in a frame set.
6463 // * @param tng_data is a trajectory data container.
6464 // * @details the current_trajectory_frame_set is the one that will be modified.
6465 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6466 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6467 // * FIXME: This function is not finished!!!
6469 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6471 // tng_gen_block_t block;
6472 // tng_trajectory_frame_set_t frame_set;
6473 // FILE *temp = tng_data->input_file;
6474 // int64_t pos, contents_start_pos, output_file_len;
6476 // frame_set = &tng_data->current_trajectory_frame_set;
6478 // if(frame_set->n_written_frames == frame_set->n_frames)
6480 // return(TNG_SUCCESS);
6483 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6484 // tng_data->last_trajectory_frame_set_output_file_pos)
6488 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6490 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6491 // __FILE__, __LINE__);
6492 // return(TNG_CRITICAL);
6495 // tng_block_init(&block);
6496 // // output_file_pos = ftello(tng_data->output_file);
6498 // tng_data->input_file = tng_data->output_file;
6500 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6502 // fseeko(tng_data->output_file, pos, SEEK_SET);
6503 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6505 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6506 // __FILE__, __LINE__);
6507 // tng_data->input_file = temp;
6508 // tng_block_destroy(&block);
6509 // return(TNG_CRITICAL);
6512 // contents_start_pos = ftello(tng_data->output_file);
6514 // fseeko(tng_data->output_file, 0, SEEK_END);
6515 // output_file_len = ftello(tng_data->output_file);
6516 // pos = contents_start_pos + block->block_contents_size;
6517 // fseeko(tng_data->output_file, pos,
6520 // while(pos < output_file_len)
6522 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6524 // fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", pos,
6525 // __FILE__, __LINE__);
6526 // tng_data->input_file = temp;
6527 // tng_block_destroy(&block);
6528 // return(TNG_CRITICAL);
6530 // pos += block->header_contents_size + block->block_contents_size;
6531 // fseeko(tng_data->output_file, pos, SEEK_SET);
6534 // return(TNG_SUCCESS);
6538 * @brief Finish writing the current frame set. Update the number of frames
6539 * and the hashes of the frame set and all its data blocks (if hash_mode
6541 * @param tng_data is a trajectory data container.
6542 * @param hash_mode specifies whether to update the block md5 hash when
6543 * updating the pointers.
6544 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6545 * error has occured.
6547 static tng_function_status tng_frame_set_finalize
6548 (const tng_trajectory_t tng_data
,
6549 const char hash_mode
)
6551 tng_gen_block_t block
;
6552 tng_trajectory_frame_set_t frame_set
;
6553 FILE *temp
= tng_data
->input_file
;
6554 int64_t pos
, curr_file_pos
;
6556 frame_set
= &tng_data
->current_trajectory_frame_set
;
6558 if(frame_set
->n_written_frames
== frame_set
->n_frames
)
6560 return(TNG_SUCCESS
);
6563 frame_set
->n_written_frames
= frame_set
->n_frames
;
6565 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
6567 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
6568 __FILE__
, __LINE__
);
6569 return(TNG_CRITICAL
);
6572 tng_block_init(&block
);
6573 /* output_file_pos = ftello(tng_data->output_file); */
6575 tng_data
->input_file
= tng_data
->output_file
;
6577 curr_file_pos
= ftello(tng_data
->output_file
);
6579 pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
6581 fseeko(tng_data
->output_file
, pos
, SEEK_SET
);
6583 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
6585 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
6586 __FILE__
, __LINE__
);
6587 tng_data
->input_file
= temp
;
6588 tng_block_destroy(&block
);
6589 return(TNG_CRITICAL
);
6592 // contents_start_pos = ftello(tng_data->output_file);
6594 fseeko(tng_data
->output_file
, sizeof(frame_set
->first_frame
), SEEK_CUR
);
6595 if(fwrite(&frame_set
->n_frames
, sizeof(frame_set
->n_frames
),
6596 1, tng_data
->output_file
) != 1)
6598 tng_data
->input_file
= temp
;
6599 tng_block_destroy(&block
);
6600 return(TNG_CRITICAL
);
6603 if(hash_mode
== TNG_USE_HASH
)
6605 tng_md5_hash_update(tng_data
, block
, pos
,
6606 pos
+ block
->header_contents_size
);
6609 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
6611 tng_data
->input_file
= temp
;
6612 tng_block_destroy(&block
);
6613 return(TNG_SUCCESS
);
6617 // ** Sets the name of a file contents block
6618 // * @param tng_data is a trajectory data container.
6619 // * @param block is the block, of which to change names.
6620 // * @param new_name is the new name of the block.
6621 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6622 // * error has occured.
6624 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
6625 // tng_gen_block_t block,
6626 // const char *new_name)
6630 // len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6632 // * If the currently stored string length is not enough to store the new
6633 // * string it is freed and reallocated. *
6634 // if(block->name && strlen(block->name) < len)
6636 // free(block->name);
6641 // block->name = (char *)malloc(len);
6644 // fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6645 // __FILE__, __LINE__);
6646 // return(TNG_CRITICAL);
6650 // strncpy(block->name, new_name, len);
6652 // return(TNG_SUCCESS);
6656 tng_function_status DECLSPECDLLEXPORT tng_atom_residue_get
6657 (const tng_trajectory_t tng_data
,
6658 const tng_atom_t atom
,
6659 tng_residue_t
*residue
)
6663 TNG_ASSERT(atom
, "TNG library: atom must not be NULL");
6665 *residue
= atom
->residue
;
6667 return(TNG_SUCCESS
);
6670 tng_function_status DECLSPECDLLEXPORT tng_atom_name_get
6671 (const tng_trajectory_t tng_data
,
6672 const tng_atom_t atom
,
6677 TNG_ASSERT(atom
, "TNG library: atom must not be NULL");
6678 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
6680 strncpy(name
, atom
->name
, max_len
- 1);
6681 name
[max_len
- 1] = 0;
6683 if(strlen(atom
->name
) > (unsigned int)max_len
- 1)
6685 return(TNG_FAILURE
);
6687 return(TNG_SUCCESS
);
6690 tng_function_status DECLSPECDLLEXPORT tng_atom_name_set
6691 (const tng_trajectory_t tng_data
,
6692 const tng_atom_t atom
,
6693 const char *new_name
)
6698 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
6699 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer.");
6701 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
6703 /* If the currently stored string length is not enough to store the new
6704 * string it is freed and reallocated. */
6705 if(atom
->name
&& strlen(atom
->name
) < len
)
6712 atom
->name
= (char *)malloc(len
);
6715 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
6716 __FILE__
, __LINE__
);
6717 return(TNG_CRITICAL
);
6721 strncpy(atom
->name
, new_name
, len
);
6723 return(TNG_SUCCESS
);
6726 tng_function_status DECLSPECDLLEXPORT tng_atom_type_get
6727 (const tng_trajectory_t tng_data
,
6728 const tng_atom_t atom
,
6733 TNG_ASSERT(atom
, "TNG library: atom must not be NULL");
6734 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer");
6736 strncpy(type
, atom
->atom_type
, max_len
- 1);
6737 type
[max_len
- 1] = 0;
6739 if(strlen(atom
->atom_type
) > (unsigned int)max_len
- 1)
6741 return(TNG_FAILURE
);
6743 return(TNG_SUCCESS
);
6746 tng_function_status DECLSPECDLLEXPORT tng_atom_type_set
6747 (const tng_trajectory_t tng_data
,
6748 const tng_atom_t atom
,
6749 const char *new_type
)
6754 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
6755 TNG_ASSERT(new_type
, "TNG library: new_type must not be a NULL pointer.");
6757 len
= tng_min_size(strlen(new_type
) + 1, TNG_MAX_STR_LEN
);
6759 /* If the currently stored string length is not enough to store the new
6760 * string it is freed and reallocated. */
6761 if(atom
->atom_type
&& strlen(atom
->atom_type
) < len
)
6763 free(atom
->atom_type
);
6764 atom
->atom_type
= 0;
6766 if(!atom
->atom_type
)
6768 atom
->atom_type
= (char *)malloc(len
);
6769 if(!atom
->atom_type
)
6771 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
6772 __FILE__
, __LINE__
);
6773 return(TNG_CRITICAL
);
6777 strncpy(atom
->atom_type
, new_type
, len
);
6779 return(TNG_SUCCESS
);
6783 * @brief Initialise an atom struct
6784 * @param atom is the atom to initialise.
6785 * @return TNG_SUCCESS (0) if successful.
6787 static tng_function_status
tng_atom_init(const tng_atom_t atom
)
6790 atom
->atom_type
= 0;
6792 return(TNG_SUCCESS
);
6796 * @brief Free the memory in an atom struct
6797 * @param atom is the atom to destroy.
6798 * @return TNG_SUCCESS (0) if successful.
6800 static tng_function_status
tng_atom_destroy(const tng_atom_t atom
)
6809 free(atom
->atom_type
);
6810 atom
->atom_type
= 0;
6813 return(TNG_SUCCESS
);
6817 * @brief Update chain->residue pointers (after new memory for
6818 * molecule->residues has been allocated).
6819 * @param tng_data The trajectory container containing the molecule.
6820 * @param mol The molecule that contains the chains that need to be
6822 * @returns TNG_SUCCESS (0) if successful.
6824 static tng_function_status tng_molecule_chains_residue_pointers_update
6825 (const tng_trajectory_t tng_data
,
6826 const tng_molecule_t mol
)
6829 int64_t i
, res_cnt
= 0;
6832 for(i
= 0; i
< mol
->n_chains
; i
++)
6834 chain
= &mol
->chains
[i
];
6835 chain
->residues
= mol
->residues
+ res_cnt
;
6836 res_cnt
+= chain
->n_residues
;
6838 return(TNG_SUCCESS
);
6841 tng_function_status DECLSPECDLLEXPORT tng_version_major
6842 (const tng_trajectory_t tng_data
,
6847 *version
= TNG_VERSION_MAJOR
;
6849 return(TNG_SUCCESS
);
6852 tng_function_status DECLSPECDLLEXPORT tng_version_minor
6853 (const tng_trajectory_t tng_data
,
6858 *version
= TNG_VERSION_MINOR
;
6860 return(TNG_SUCCESS
);
6863 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
6864 (const tng_trajectory_t tng_data
,
6869 *patch_level
= TNG_VERSION_PATCHLEVEL
;
6871 return(TNG_SUCCESS
);
6874 tng_function_status DECLSPECDLLEXPORT tng_version
6875 (const tng_trajectory_t tng_data
,
6880 TNG_ASSERT(version
, "TNG library: version must not be a NULL pointer");
6882 TNG_SNPRINTF(version
, max_len
, "%s", TNG_VERSION
);
6884 return(TNG_SUCCESS
);
6887 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
6888 (const tng_trajectory_t tng_data
,
6890 tng_molecule_t
*molecule
)
6894 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
6895 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
6897 /* Set ID to the ID of the last molecule + 1 */
6898 if(tng_data
->n_molecules
)
6900 id
= tng_data
->molecules
[tng_data
->n_molecules
-1].id
+ 1;
6907 return(tng_molecule_w_id_add(tng_data
, name
, id
, molecule
));
6910 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
6911 (const tng_trajectory_t tng_data
,
6914 tng_molecule_t
*molecule
)
6916 tng_molecule_t new_molecules
;
6917 int64_t *new_molecule_cnt_list
;
6918 tng_function_status stat
= TNG_SUCCESS
;
6920 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
6921 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
6923 new_molecules
= (tng_molecule_t
)realloc(tng_data
->molecules
,
6924 sizeof(struct tng_molecule
) *
6925 (tng_data
->n_molecules
+ 1));
6929 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
6930 __FILE__
, __LINE__
);
6931 free(tng_data
->molecules
);
6932 tng_data
->molecules
= 0;
6933 return(TNG_CRITICAL
);
6936 new_molecule_cnt_list
= (int64_t *)realloc(tng_data
->molecule_cnt_list
,
6938 (tng_data
->n_molecules
+ 1));
6940 if(!new_molecule_cnt_list
)
6942 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
6943 __FILE__
, __LINE__
);
6944 free(tng_data
->molecule_cnt_list
);
6945 tng_data
->molecule_cnt_list
= 0;
6946 free(new_molecules
);
6947 return(TNG_CRITICAL
);
6950 tng_data
->molecules
= new_molecules
;
6951 tng_data
->molecule_cnt_list
= new_molecule_cnt_list
;
6953 *molecule
= &new_molecules
[tng_data
->n_molecules
];
6955 tng_molecule_init(tng_data
, *molecule
);
6956 tng_molecule_name_set(tng_data
, *molecule
, name
);
6958 /* FIXME: Should this be a function argument instead? */
6959 tng_data
->molecule_cnt_list
[tng_data
->n_molecules
] = 0;
6961 (*molecule
)->id
= id
;
6963 tng_data
->n_molecules
++;
6968 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
6969 (const tng_trajectory_t tng_data
,
6970 tng_molecule_t
*molecule_p
)
6972 int64_t *new_molecule_cnt_list
, id
;
6973 tng_molecule_t new_molecules
, molecule
;
6975 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
6977 /* Set ID to the ID of the last molecule + 1 */
6978 if(tng_data
->n_molecules
)
6980 id
= tng_data
->molecules
[tng_data
->n_molecules
-1].id
+ 1;
6987 new_molecules
= (tng_molecule_t
)realloc(tng_data
->molecules
,
6988 sizeof(struct tng_molecule
) *
6989 (tng_data
->n_molecules
+ 1));
6993 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
6994 __FILE__
, __LINE__
);
6995 free(tng_data
->molecules
);
6996 tng_data
->molecules
= 0;
6997 return(TNG_CRITICAL
);
7000 new_molecule_cnt_list
= (int64_t *)realloc(tng_data
->molecule_cnt_list
,
7002 (tng_data
->n_molecules
+ 1));
7004 if(!new_molecule_cnt_list
)
7006 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7007 __FILE__
, __LINE__
);
7008 free(tng_data
->molecule_cnt_list
);
7009 tng_data
->molecule_cnt_list
= 0;
7010 free(new_molecules
);
7011 return(TNG_CRITICAL
);
7014 molecule
= *molecule_p
;
7016 tng_data
->molecules
= new_molecules
;
7017 tng_data
->molecule_cnt_list
= new_molecule_cnt_list
;
7019 new_molecules
[tng_data
->n_molecules
] = *molecule
;
7021 tng_data
->molecule_cnt_list
[tng_data
->n_molecules
] = 0;
7025 molecule
= &new_molecules
[tng_data
->n_molecules
];
7027 *molecule_p
= molecule
;
7031 tng_data
->n_molecules
++;
7033 return(TNG_SUCCESS
);
7036 tng_function_status
tng_molecule_name_get(const tng_trajectory_t tng_data
,
7037 const tng_molecule_t molecule
,
7042 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
7043 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
7045 strncpy(name
, molecule
->name
, max_len
- 1);
7046 name
[max_len
- 1] = 0;
7048 if(strlen(molecule
->name
) > (unsigned int)max_len
- 1)
7050 return(TNG_FAILURE
);
7052 return(TNG_SUCCESS
);
7055 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7056 (const tng_trajectory_t tng_data
,
7057 const tng_molecule_t molecule
,
7058 const char *new_name
)
7063 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7064 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer.");
7066 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
7068 /* If the currently stored string length is not enough to store the new
7069 * string it is freed and reallocated. */
7070 if(molecule
->name
&& strlen(molecule
->name
) < len
)
7072 free(molecule
->name
);
7077 molecule
->name
= (char *)malloc(len
);
7080 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7081 __FILE__
, __LINE__
);
7082 return(TNG_CRITICAL
);
7086 strncpy(molecule
->name
, new_name
, len
);
7088 return(TNG_SUCCESS
);
7091 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7092 (const tng_trajectory_t tng_data
,
7093 const tng_molecule_t molecule
,
7096 int64_t i
, index
= -1;
7098 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7099 TNG_ASSERT(cnt
, "TNG library: cnt must not be a NULL pointer.");
7101 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
7103 if(&tng_data
->molecules
[i
] == molecule
)
7111 return(TNG_FAILURE
);
7113 *cnt
= tng_data
->molecule_cnt_list
[index
];
7115 return(TNG_SUCCESS
);
7118 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7119 (const tng_trajectory_t tng_data
,
7120 const tng_molecule_t molecule
,
7123 int64_t i
, old_cnt
, index
= -1;
7125 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7127 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
7129 if(&tng_data
->molecules
[i
] == molecule
)
7137 fprintf(stderr
, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7138 __FILE__
, __LINE__
);
7139 return(TNG_FAILURE
);
7141 if(tng_data
->var_num_atoms_flag
== TNG_CONSTANT_N_ATOMS
)
7143 old_cnt
= tng_data
->molecule_cnt_list
[index
];
7144 tng_data
->molecule_cnt_list
[index
] = cnt
;
7146 tng_data
->n_particles
+= (cnt
-old_cnt
) *
7147 tng_data
->molecules
[index
].n_atoms
;
7151 old_cnt
= tng_data
->current_trajectory_frame_set
.molecule_cnt_list
[index
];
7152 tng_data
->current_trajectory_frame_set
.molecule_cnt_list
[index
] = cnt
;
7154 tng_data
->current_trajectory_frame_set
.n_particles
+= (cnt
-old_cnt
) *
7155 tng_data
->molecules
[index
].n_atoms
;
7158 return(TNG_SUCCESS
);
7161 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7162 (const tng_trajectory_t tng_data
,
7165 tng_molecule_t
*molecule
)
7167 int64_t i
, n_molecules
;
7169 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7170 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7171 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
7173 n_molecules
= tng_data
->n_molecules
;
7175 for(i
= n_molecules
- 1; i
>= 0; i
--)
7177 *molecule
= &tng_data
->molecules
[i
];
7178 if(name
[0] == 0 || strcmp(name
, (*molecule
)->name
) == 0)
7180 if(nr
== -1 || nr
== (*molecule
)->id
)
7182 return(TNG_SUCCESS
);
7189 return(TNG_FAILURE
);
7192 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7193 (const tng_trajectory_t tng_data
,
7194 const int64_t index
,
7195 tng_molecule_t
*molecule
)
7197 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7198 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
7200 if(index
>= tng_data
->n_molecules
)
7203 return(TNG_FAILURE
);
7205 *molecule
= &tng_data
->molecules
[index
];
7206 return(TNG_SUCCESS
);
7209 tng_function_status DECLSPECDLLEXPORT
tng_molecule_system_copy(const tng_trajectory_t tng_data_src
,
7210 const tng_trajectory_t tng_data_dest
)
7212 tng_molecule_t molecule
, molecule_temp
;
7213 tng_chain_t chain
, chain_temp
;
7214 tng_residue_t residue
, residue_temp
;
7215 tng_atom_t atom
, atom_temp
;
7216 tng_bond_t bond_temp
;
7217 tng_function_status stat
;
7218 int64_t i
, j
, k
, l
, *list_temp
;
7220 TNG_ASSERT(tng_data_src
, "TNG library: Trajectory container not properly setup.");
7221 TNG_ASSERT(tng_data_dest
, "TNG library: Trajectory container not properly setup.");
7223 for(i
= 0; i
< tng_data_dest
->n_molecules
; i
++)
7225 molecule
= &tng_data_dest
->molecules
[i
];
7226 tng_molecule_destroy(tng_data_dest
, molecule
);
7229 tng_data_dest
->n_molecules
= 0;
7230 tng_data_dest
->n_particles
= 0;
7232 molecule_temp
= (tng_molecule_t
)realloc(tng_data_dest
->molecules
,
7233 sizeof(struct tng_molecule
) * tng_data_src
->n_molecules
);
7236 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7237 __FILE__
, __LINE__
);
7238 free(tng_data_dest
->molecules
);
7239 tng_data_dest
->molecules
= 0;
7240 return(TNG_CRITICAL
);
7242 list_temp
= (int64_t *)realloc(tng_data_dest
->molecule_cnt_list
,
7243 sizeof(int64_t) * tng_data_src
->n_molecules
);
7246 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7247 __FILE__
, __LINE__
);
7248 free(tng_data_dest
->molecule_cnt_list
);
7249 tng_data_dest
->molecule_cnt_list
= 0;
7250 free(molecule_temp
);
7251 return(TNG_CRITICAL
);
7254 tng_data_dest
->molecules
= molecule_temp
;
7255 tng_data_dest
->molecule_cnt_list
= list_temp
;
7257 for(i
= 0; i
< tng_data_src
->n_molecules
; i
++)
7259 molecule
= &tng_data_src
->molecules
[i
];
7260 stat
= tng_molecule_w_id_add(tng_data_dest
, molecule
->name
, molecule
->id
,
7262 if(stat
!= TNG_SUCCESS
)
7264 fprintf(stderr
, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7265 __FILE__
, __LINE__
);
7268 molecule_temp
->quaternary_str
= molecule
->quaternary_str
;
7269 for(j
= 0; j
< molecule
->n_chains
; j
++)
7271 chain
= &molecule
->chains
[j
];
7272 stat
= tng_molecule_chain_w_id_add(tng_data_dest
, molecule_temp
,
7273 chain
->name
, chain
->id
,
7275 if(stat
!= TNG_SUCCESS
)
7277 fprintf(stderr
, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7278 __FILE__
, __LINE__
);
7281 for(k
= 0; k
< chain
->n_residues
; k
++)
7283 residue
= &chain
->residues
[k
];
7284 stat
= tng_chain_residue_w_id_add(tng_data_dest
, chain_temp
,
7285 residue
->name
, residue
->id
,
7287 if(stat
!= TNG_SUCCESS
)
7289 fprintf(stderr
, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7290 __FILE__
, __LINE__
);
7293 for(l
= 0; l
< residue
->n_atoms
; l
++)
7295 atom
= &molecule
->atoms
[residue
->atoms_offset
+ l
];
7296 stat
= tng_residue_atom_w_id_add(tng_data_dest
, residue_temp
,
7297 atom
->name
, atom
->atom_type
,
7298 atom
->id
, &atom_temp
);
7299 if(stat
!= TNG_SUCCESS
)
7301 fprintf(stderr
, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7302 __FILE__
, __LINE__
);
7308 molecule_temp
->n_bonds
= molecule
->n_bonds
;
7309 if(molecule
->n_bonds
> 0)
7311 bond_temp
= (tng_bond_t
)realloc(molecule_temp
->bonds
, sizeof(struct tng_bond
) *
7315 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7316 __FILE__
, __LINE__
);
7317 free(molecule_temp
->bonds
);
7318 molecule_temp
->n_bonds
= 0;
7319 return(TNG_CRITICAL
);
7321 molecule_temp
->bonds
= bond_temp
;
7322 for(j
= 0; j
< molecule
->n_bonds
; j
++)
7324 molecule_temp
->bonds
[j
] = molecule
->bonds
[j
];
7327 stat
= tng_molecule_cnt_set(tng_data_dest
, molecule_temp
,
7328 tng_data_src
->molecule_cnt_list
[i
]);
7329 if(stat
!= TNG_SUCCESS
)
7331 fprintf(stderr
, "TNG library: Cannot set molecule count. %s: %d.\n",
7332 __FILE__
, __LINE__
);
7336 return(TNG_SUCCESS
);
7339 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7340 (const tng_trajectory_t tng_data
,
7341 const tng_molecule_t molecule
,
7345 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
7346 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
7348 *n
= molecule
->n_chains
;
7350 return(TNG_SUCCESS
);
7353 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7354 (const tng_trajectory_t tng_data
,
7355 const tng_molecule_t molecule
,
7356 const int64_t index
,
7360 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
7361 TNG_ASSERT(chain
, "TNG library: chain must not be a NULL pointer.");
7363 if(index
>= molecule
->n_chains
)
7366 return(TNG_FAILURE
);
7368 *chain
= &molecule
->chains
[index
];
7369 return(TNG_SUCCESS
);
7372 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7373 (const tng_trajectory_t tng_data
,
7374 const tng_molecule_t molecule
,
7378 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
7379 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
7381 *n
= molecule
->n_residues
;
7383 return(TNG_SUCCESS
);
7386 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7387 (const tng_trajectory_t tng_data
,
7388 const tng_molecule_t molecule
,
7389 const int64_t index
,
7390 tng_residue_t
*residue
)
7393 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
7394 TNG_ASSERT(residue
, "TNG library: residue must not be a NULL pointer.");
7396 if(index
>= molecule
->n_residues
)
7399 return(TNG_FAILURE
);
7401 *residue
= &molecule
->residues
[index
];
7402 return(TNG_SUCCESS
);
7405 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7406 (const tng_trajectory_t tng_data
,
7407 const tng_molecule_t molecule
,
7411 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
7412 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
7414 *n
= molecule
->n_atoms
;
7416 return(TNG_SUCCESS
);
7419 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7420 (const tng_trajectory_t tng_data
,
7421 const tng_molecule_t molecule
,
7422 const int64_t index
,
7426 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
7427 TNG_ASSERT(atom
, "TNG library: atom must not be a NULL pointer.");
7429 if(index
>= molecule
->n_atoms
)
7432 return(TNG_FAILURE
);
7434 *atom
= &molecule
->atoms
[index
];
7435 return(TNG_SUCCESS
);
7438 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7439 (const tng_trajectory_t tng_data
,
7440 const tng_molecule_t molecule
,
7445 int64_t i
, n_chains
;
7448 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7449 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7451 n_chains
= molecule
->n_chains
;
7453 for(i
= n_chains
- 1; i
>= 0; i
--)
7455 *chain
= &molecule
->chains
[i
];
7456 if(name
[0] == 0 || strcmp(name
, (*chain
)->name
) == 0)
7458 if(nr
== -1 || nr
== (*chain
)->id
)
7460 return(TNG_SUCCESS
);
7467 return(TNG_FAILURE
);
7470 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7471 (const tng_trajectory_t tng_data
,
7472 const tng_molecule_t molecule
,
7478 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7479 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7481 /* Set ID to the ID of the last chain + 1 */
7482 if(molecule
->n_chains
)
7484 id
= molecule
->chains
[molecule
->n_chains
-1].id
+ 1;
7491 return(tng_molecule_chain_w_id_add(tng_data
, molecule
, name
,
7495 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7496 (const tng_trajectory_t tng_data
,
7497 const tng_molecule_t molecule
,
7502 tng_chain_t new_chains
;
7503 tng_function_status stat
= TNG_SUCCESS
;
7505 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7506 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7508 new_chains
= (tng_chain_t
)realloc(molecule
->chains
,
7509 sizeof(struct tng_chain
) *
7510 (molecule
->n_chains
+ 1));
7514 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7515 __FILE__
, __LINE__
);
7516 free(molecule
->chains
);
7517 molecule
->chains
= 0;
7518 return(TNG_CRITICAL
);
7521 molecule
->chains
= new_chains
;
7523 *chain
= &new_chains
[molecule
->n_chains
];
7526 tng_chain_name_set(tng_data
, *chain
, name
);
7528 (*chain
)->molecule
= molecule
;
7529 (*chain
)->n_residues
= 0;
7531 molecule
->n_chains
++;
7538 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7539 (const tng_trajectory_t tng_data
,
7540 const tng_molecule_t molecule
,
7541 const int64_t from_atom_id
,
7542 const int64_t to_atom_id
,
7545 tng_bond_t new_bonds
;
7548 new_bonds
= (tng_bond_t
)realloc(molecule
->bonds
,
7549 sizeof(struct tng_bond
) *
7550 (molecule
->n_bonds
+ 1));
7554 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7555 __FILE__
, __LINE__
);
7557 free(molecule
->bonds
);
7558 molecule
->bonds
= 0;
7559 return(TNG_CRITICAL
);
7562 molecule
->bonds
= new_bonds
;
7564 *bond
= &new_bonds
[molecule
->n_bonds
];
7566 (*bond
)->from_atom_id
= from_atom_id
;
7567 (*bond
)->to_atom_id
= to_atom_id
;
7569 molecule
->n_bonds
++;
7571 return(TNG_SUCCESS
);
7574 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7575 (const tng_trajectory_t tng_data
,
7576 const tng_molecule_t molecule
,
7584 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7586 n_atoms
= molecule
->n_atoms
;
7588 for(i
= n_atoms
- 1; i
>= 0; i
--)
7590 *atom
= &molecule
->atoms
[i
];
7591 if(name
[0] == 0 || strcmp(name
, (*atom
)->name
) == 0)
7593 if(id
== -1 || id
== (*atom
)->id
)
7595 return(TNG_SUCCESS
);
7602 return(TNG_FAILURE
);
7605 tng_function_status
tng_chain_name_get(const tng_trajectory_t tng_data
,
7606 const tng_chain_t chain
,
7611 TNG_ASSERT(chain
, "TNG library: chain must not be NULL");
7612 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
7614 strncpy(name
, chain
->name
, max_len
- 1);
7615 name
[max_len
- 1] = 0;
7617 if(strlen(chain
->name
) > (unsigned int)max_len
- 1)
7619 return(TNG_FAILURE
);
7621 return(TNG_SUCCESS
);
7624 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7625 (const tng_trajectory_t tng_data
,
7626 const tng_chain_t chain
,
7627 const char *new_name
)
7632 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer.");
7634 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
7636 /* If the currently stored string length is not enough to store the new
7637 * string it is freed and reallocated. */
7638 if(chain
->name
&& strlen(chain
->name
) < len
)
7645 chain
->name
= (char *)malloc(len
);
7648 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7649 __FILE__
, __LINE__
);
7650 return(TNG_CRITICAL
);
7654 strncpy(chain
->name
, new_name
, len
);
7656 return(TNG_SUCCESS
);
7659 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
7660 (const tng_trajectory_t tng_data
,
7661 const tng_chain_t chain
,
7665 TNG_ASSERT(chain
, "TNG library: chain must not be NULL");
7666 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
7668 *n
= chain
->n_residues
;
7670 return(TNG_SUCCESS
);
7673 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
7674 (const tng_trajectory_t tng_data
,
7675 const tng_chain_t chain
,
7676 const int64_t index
,
7677 tng_residue_t
*residue
)
7680 TNG_ASSERT(chain
, "TNG library: chain must not be a NULL pointer.");
7681 TNG_ASSERT(residue
, "TNG library: residue must not be a NULL pointer.");
7683 if(index
>= chain
->n_residues
)
7686 return(TNG_FAILURE
);
7688 *residue
= &chain
->residues
[index
];
7689 return(TNG_SUCCESS
);
7692 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
7693 (const tng_trajectory_t tng_data
,
7694 const tng_chain_t chain
,
7697 tng_residue_t
*residue
)
7699 int64_t i
, n_residues
;
7702 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7704 n_residues
= chain
->n_residues
;
7706 for(i
= n_residues
- 1; i
>= 0; i
--)
7708 *residue
= &chain
->residues
[i
];
7709 if(name
[0] == 0 || strcmp(name
, (*residue
)->name
) == 0)
7711 if(id
== -1 || id
== (*residue
)->id
)
7713 return(TNG_SUCCESS
);
7720 return(TNG_FAILURE
);
7723 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
7724 (const tng_trajectory_t tng_data
,
7725 const tng_chain_t chain
,
7727 tng_residue_t
*residue
)
7731 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7732 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7734 /* Set ID to the ID of the last residue + 1 */
7735 if(chain
->n_residues
)
7737 id
= chain
->residues
[chain
->n_residues
-1].id
+ 1;
7744 return(tng_chain_residue_w_id_add(tng_data
, chain
, name
,
7748 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
7749 (const tng_trajectory_t tng_data
,
7750 const tng_chain_t chain
,
7753 tng_residue_t
*residue
)
7756 tng_residue_t new_residues
, temp_residue
, last_residue
;
7757 tng_molecule_t molecule
= chain
->molecule
;
7758 tng_function_status stat
= TNG_SUCCESS
;
7760 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7761 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7763 if(chain
->n_residues
)
7765 curr_index
= chain
->residues
- molecule
->residues
;
7772 new_residues
= (tng_residue_t
)realloc(molecule
->residues
,
7773 sizeof(struct tng_residue
) *
7774 (molecule
->n_residues
+ 1));
7778 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7779 __FILE__
, __LINE__
);
7780 free(molecule
->residues
);
7781 molecule
->residues
= 0;
7782 return(TNG_CRITICAL
);
7785 molecule
->residues
= new_residues
;
7787 if(curr_index
!= -1)
7789 chain
->residues
= new_residues
+ curr_index
;
7790 if(molecule
->n_residues
)
7792 last_residue
= &new_residues
[molecule
->n_residues
- 1];
7794 temp_residue
= chain
->residues
+ (chain
->n_residues
- 1);
7795 /* Make space in list of residues to add the new residues together with the other
7796 * residues of this chain */
7797 if(temp_residue
!= last_residue
)
7800 memmove(temp_residue
+ 1, temp_residue
,
7801 last_residue
- temp_residue
);
7807 curr_index
= molecule
->n_residues
;
7810 *residue
= &molecule
->residues
[curr_index
+ chain
->n_residues
];
7812 tng_molecule_chains_residue_pointers_update(tng_data
, molecule
);
7814 (*residue
)->name
= 0;
7815 tng_residue_name_set(tng_data
, *residue
, name
);
7817 (*residue
)->chain
= chain
;
7818 (*residue
)->n_atoms
= 0;
7819 (*residue
)->atoms_offset
= 0;
7821 chain
->n_residues
++;
7822 molecule
->n_residues
++;
7824 (*residue
)->id
= id
;
7829 tng_function_status
tng_residue_name_get(const tng_trajectory_t tng_data
,
7830 const tng_residue_t residue
,
7835 TNG_ASSERT(residue
, "TNG library: residue must not be NULL");
7836 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
7838 strncpy(name
, residue
->name
, max_len
- 1);
7839 name
[max_len
- 1] = 0;
7841 if(strlen(residue
->name
) > (unsigned int)max_len
- 1)
7843 return(TNG_FAILURE
);
7845 return(TNG_SUCCESS
);
7848 tng_function_status DECLSPECDLLEXPORT
tng_residue_name_set(const tng_trajectory_t tng_data
,
7849 const tng_residue_t residue
,
7850 const char *new_name
)
7855 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7856 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
7858 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
7860 /* If the currently stored string length is not enough to store the new
7861 * string it is freed and reallocated. */
7862 if(residue
->name
&& strlen(residue
->name
) < len
)
7864 free(residue
->name
);
7869 residue
->name
= (char *)malloc(len
);
7872 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7873 __FILE__
, __LINE__
);
7874 return(TNG_CRITICAL
);
7878 strncpy(residue
->name
, new_name
, len
);
7880 return(TNG_SUCCESS
);
7883 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
7884 (const tng_trajectory_t tng_data
,
7885 const tng_residue_t residue
,
7889 TNG_ASSERT(residue
, "TNG library: residue must not be NULL");
7890 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
7892 *n
= residue
->n_atoms
;
7894 return(TNG_SUCCESS
);
7897 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
7898 (const tng_trajectory_t tng_data
,
7899 const tng_residue_t residue
,
7900 const int64_t index
,
7904 tng_molecule_t molecule
;
7907 TNG_ASSERT(residue
, "TNG library: residue must not be a NULL pointer.");
7908 TNG_ASSERT(atom
, "TNG library: atom must not be a NULL pointer.");
7910 if(index
>= residue
->n_atoms
)
7913 return(TNG_FAILURE
);
7915 chain
= residue
->chain
;
7916 molecule
= chain
->molecule
;
7918 if(index
+ residue
->atoms_offset
>= molecule
->n_atoms
)
7921 return(TNG_FAILURE
);
7924 *atom
= &molecule
->atoms
[residue
->atoms_offset
+ index
];
7925 return(TNG_SUCCESS
);
7928 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
7929 (const tng_trajectory_t tng_data
,
7930 const tng_residue_t residue
,
7931 const char *atom_name
,
7932 const char *atom_type
,
7937 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7938 TNG_ASSERT(atom_name
, "TNG library: atom_name must not be a NULL pointer.");
7939 TNG_ASSERT(atom_type
, "TNG library: atom_type must not be a NULL pointer.");
7941 /* Set ID to the ID of the last atom + 1 */
7942 if(residue
->chain
->molecule
->n_atoms
)
7944 id
= residue
->chain
->molecule
->atoms
[residue
->chain
->molecule
->n_atoms
-1].id
+ 1;
7951 return(tng_residue_atom_w_id_add(tng_data
, residue
, atom_name
, atom_type
,
7955 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
7956 (const tng_trajectory_t tng_data
,
7957 const tng_residue_t residue
,
7958 const char *atom_name
,
7959 const char *atom_type
,
7963 tng_atom_t new_atoms
;
7964 tng_molecule_t molecule
= residue
->chain
->molecule
;
7965 tng_function_status stat
= TNG_SUCCESS
;
7967 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7968 TNG_ASSERT(atom_name
, "TNG library: atom_name must not be a NULL pointer.");
7969 TNG_ASSERT(atom_type
, "TNG library: atom_type must not be a NULL pointer.");
7971 if(!residue
->n_atoms
)
7973 residue
->atoms_offset
= molecule
->n_atoms
;
7976 new_atoms
= (tng_atom_t
)realloc(molecule
->atoms
,
7977 sizeof(struct tng_atom
) *
7978 (molecule
->n_atoms
+ 1));
7982 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
7983 __FILE__
, __LINE__
);
7984 free(molecule
->atoms
);
7985 molecule
->atoms
= 0;
7986 return(TNG_CRITICAL
);
7989 molecule
->atoms
= new_atoms
;
7991 *atom
= &new_atoms
[molecule
->n_atoms
];
7993 tng_atom_init(*atom
);
7994 tng_atom_name_set(tng_data
, *atom
, atom_name
);
7995 tng_atom_type_set(tng_data
, *atom
, atom_type
);
7997 (*atom
)->residue
= residue
;
8000 molecule
->n_atoms
++;
8007 tng_function_status DECLSPECDLLEXPORT
tng_molecule_alloc(const tng_trajectory_t tng_data
,
8008 tng_molecule_t
*molecule_p
)
8010 *molecule_p
= (tng_molecule_t
)malloc(sizeof(struct tng_molecule
));
8013 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
8014 __FILE__
, __LINE__
);
8015 return(TNG_CRITICAL
);
8018 tng_molecule_init(tng_data
, *molecule_p
);
8020 return(TNG_SUCCESS
);
8023 tng_function_status DECLSPECDLLEXPORT
tng_molecule_free(const tng_trajectory_t tng_data
,
8024 tng_molecule_t
*molecule_p
)
8028 return(TNG_SUCCESS
);
8031 tng_molecule_destroy(tng_data
, *molecule_p
);
8036 return(TNG_SUCCESS
);
8039 tng_function_status DECLSPECDLLEXPORT
tng_molecule_init(const tng_trajectory_t tng_data
,
8040 const tng_molecule_t molecule
)
8043 molecule
->quaternary_str
= 1;
8045 molecule
->n_chains
= 0;
8046 molecule
->chains
= 0;
8047 molecule
->n_residues
= 0;
8048 molecule
->residues
= 0;
8049 molecule
->n_atoms
= 0;
8050 molecule
->atoms
= 0;
8051 molecule
->n_bonds
= 0;
8052 molecule
->bonds
= 0;
8054 return(TNG_SUCCESS
);
8057 tng_function_status DECLSPECDLLEXPORT
tng_molecule_destroy(const tng_trajectory_t tng_data
,
8058 const tng_molecule_t molecule
)
8065 free(molecule
->name
);
8069 if(molecule
->chains
)
8071 for(i
= 0; i
< molecule
->n_chains
; i
++)
8073 if(molecule
->chains
[i
].name
)
8075 free(molecule
->chains
[i
].name
);
8076 molecule
->chains
[i
].name
= 0;
8079 free(molecule
->chains
);
8080 molecule
->chains
= 0;
8082 molecule
->n_chains
= 0;
8084 if(molecule
->residues
)
8086 for(i
= 0; i
< molecule
->n_residues
; i
++)
8088 if(molecule
->residues
[i
].name
)
8090 free(molecule
->residues
[i
].name
);
8091 molecule
->residues
[i
].name
= 0;
8094 free(molecule
->residues
);
8095 molecule
->residues
= 0;
8097 molecule
->n_residues
= 0;
8101 for(i
= 0; i
< molecule
->n_atoms
; i
++)
8103 tng_atom_destroy(&molecule
->atoms
[i
]);
8105 free(molecule
->atoms
);
8106 molecule
->atoms
= 0;
8108 molecule
->n_atoms
= 0;
8112 free(molecule
->bonds
);
8113 molecule
->bonds
= 0;
8115 molecule
->n_bonds
= 0;
8117 return(TNG_SUCCESS
);
8120 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8121 (const tng_trajectory_t tng_data
,
8126 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8128 tng_bool found
= TNG_FALSE
;
8130 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8131 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8133 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8135 if(!molecule_cnt_list
)
8137 return(TNG_FAILURE
);
8140 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8142 mol
= &tng_data
->molecules
[i
];
8143 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8145 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8153 return(TNG_FAILURE
);
8156 strncpy(name
, mol
->name
, max_len
- 1);
8157 name
[max_len
- 1] = 0;
8159 if(strlen(mol
->name
) > (unsigned int)max_len
- 1)
8161 return(TNG_FAILURE
);
8163 return(TNG_SUCCESS
);
8166 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8167 (const tng_trajectory_t tng_data
,
8171 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8173 tng_bool found
= TNG_FALSE
;
8175 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8176 TNG_ASSERT(id
, "TNG library: id must not be a NULL pointer.");
8178 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8180 if(!molecule_cnt_list
)
8182 return(TNG_FAILURE
);
8185 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8187 mol
= &tng_data
->molecules
[i
];
8188 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8190 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8198 return(TNG_FAILURE
);
8203 return(TNG_SUCCESS
);
8206 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8207 (const tng_trajectory_t tng_data
,
8209 int64_t **from_atoms
,
8212 int64_t atom_cnt
= 0, cnt
, mol_cnt
, i
, j
, k
;
8213 int64_t from_atom
, to_atom
, *molecule_cnt_list
= 0;
8217 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8218 TNG_ASSERT(n_bonds
, "TNG library: n_bonds must not be a NULL pointer.");
8219 TNG_ASSERT(from_atoms
, "TNG library: from_atoms must not be a NULL pointer.");
8220 TNG_ASSERT(to_atoms
, "TNG library: to_atoms must not be a NULL pointer.");
8222 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8224 if(!molecule_cnt_list
)
8226 return(TNG_FAILURE
);
8230 /* First count the total number of bonds to allocate memory */
8231 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8233 mol
= &tng_data
->molecules
[i
];
8234 mol_cnt
= molecule_cnt_list
[i
];
8235 *n_bonds
+= mol_cnt
* mol
->n_bonds
;
8239 return(TNG_SUCCESS
);
8242 *from_atoms
= (int64_t *)malloc(sizeof(int64_t) * (*n_bonds
));
8245 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
8246 __FILE__
, __LINE__
);
8247 return(TNG_CRITICAL
);
8249 *to_atoms
= (int64_t *)malloc(sizeof(int64_t) * (*n_bonds
));
8252 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
8253 __FILE__
, __LINE__
);
8256 return(TNG_CRITICAL
);
8260 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8262 mol
= &tng_data
->molecules
[i
];
8263 mol_cnt
= molecule_cnt_list
[i
];
8264 for(j
= 0; j
< mol_cnt
; j
++)
8266 for(k
= 0; k
< mol
->n_bonds
; k
++)
8268 bond
= &mol
->bonds
[k
];
8269 from_atom
= atom_cnt
+ bond
->from_atom_id
;
8270 to_atom
= atom_cnt
+ bond
->to_atom_id
;
8271 (*from_atoms
)[cnt
] = from_atom
;
8272 (*to_atoms
)[cnt
++] = to_atom
;
8274 atom_cnt
+= mol
->n_atoms
;
8278 return(TNG_SUCCESS
);
8281 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8282 (const tng_trajectory_t tng_data
,
8287 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8290 tng_bool found
= TNG_FALSE
;
8292 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8293 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8295 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8297 if(!molecule_cnt_list
)
8299 return(TNG_FAILURE
);
8302 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8304 mol
= &tng_data
->molecules
[i
];
8305 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8307 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8310 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
8316 return(TNG_FAILURE
);
8318 if(!atom
->residue
|| !atom
->residue
->chain
)
8320 return(TNG_FAILURE
);
8323 strncpy(name
, atom
->residue
->chain
->name
, max_len
- 1);
8324 name
[max_len
- 1] = 0;
8326 if(strlen(atom
->residue
->chain
->name
) > (unsigned int)max_len
- 1)
8328 return(TNG_FAILURE
);
8330 return(TNG_SUCCESS
);
8333 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8334 (const tng_trajectory_t tng_data
,
8339 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8342 tng_bool found
= TNG_FALSE
;
8344 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8345 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8347 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8349 if(!molecule_cnt_list
)
8351 return(TNG_FAILURE
);
8354 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8356 mol
= &tng_data
->molecules
[i
];
8357 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8359 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8362 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
8368 return(TNG_FAILURE
);
8372 return(TNG_FAILURE
);
8375 strncpy(name
, atom
->residue
->name
, max_len
- 1);
8376 name
[max_len
- 1] = 0;
8378 if(strlen(atom
->residue
->name
) > (unsigned int)max_len
- 1)
8380 return(TNG_FAILURE
);
8382 return(TNG_SUCCESS
);
8385 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8386 (const tng_trajectory_t tng_data
,
8390 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8393 tng_bool found
= TNG_FALSE
;
8395 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8396 TNG_ASSERT(id
, "TNG library: id must not be a NULL pointer.");
8398 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8400 if(!molecule_cnt_list
)
8402 return(TNG_FAILURE
);
8405 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8407 mol
= &tng_data
->molecules
[i
];
8408 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8410 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8413 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
8419 return(TNG_FAILURE
);
8423 return(TNG_FAILURE
);
8426 *id
= atom
->residue
->id
;
8428 return(TNG_SUCCESS
);
8431 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8432 (const tng_trajectory_t tng_data
,
8436 int64_t cnt
= 0, i
, offset
= 0, *molecule_cnt_list
= 0;
8439 tng_bool found
= TNG_FALSE
;
8441 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8442 TNG_ASSERT(id
, "TNG library: id must not be a NULL pointer.");
8444 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8446 if(!molecule_cnt_list
)
8448 return(TNG_FAILURE
);
8451 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8453 mol
= &tng_data
->molecules
[i
];
8454 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8456 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8457 offset
+= mol
->n_residues
* molecule_cnt_list
[i
];
8460 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
8466 return(TNG_FAILURE
);
8470 return(TNG_FAILURE
);
8473 offset
+= mol
->n_residues
* ((nr
- cnt
) / mol
->n_atoms
);
8475 *id
= atom
->residue
->id
+ offset
;
8477 return(TNG_SUCCESS
);
8480 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8481 (const tng_trajectory_t tng_data
,
8486 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8489 tng_bool found
= TNG_FALSE
;
8491 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8492 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8494 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8496 if(!molecule_cnt_list
)
8498 return(TNG_FAILURE
);
8501 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8503 mol
= &tng_data
->molecules
[i
];
8504 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8506 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8509 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
8515 return(TNG_FAILURE
);
8518 strncpy(name
, atom
->name
, max_len
- 1);
8519 name
[max_len
- 1] = 0;
8521 if(strlen(atom
->name
) > (unsigned int)max_len
- 1)
8523 return(TNG_FAILURE
);
8525 return(TNG_SUCCESS
);
8528 tng_function_status tng_atom_type_of_particle_nr_get
8529 (const tng_trajectory_t tng_data
,
8534 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
8537 tng_bool found
= TNG_FALSE
;
8539 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8540 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
8542 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
8544 if(!molecule_cnt_list
)
8546 return(TNG_FAILURE
);
8549 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8551 mol
= &tng_data
->molecules
[i
];
8552 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
8554 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
8557 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
8563 return(TNG_FAILURE
);
8566 strncpy(type
, atom
->atom_type
, max_len
- 1);
8567 type
[max_len
- 1] = 0;
8569 if(strlen(atom
->atom_type
) > (unsigned int)max_len
- 1)
8571 return(TNG_FAILURE
);
8573 return(TNG_SUCCESS
);
8576 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8577 (const tng_trajectory_t tng_data
,
8578 const int64_t num_first_particle
,
8579 const int64_t n_particles
,
8580 const int64_t *mapping_table
)
8583 tng_particle_mapping_t mapping
;
8584 tng_trajectory_frame_set_t frame_set
;
8586 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8588 frame_set
= &tng_data
->current_trajectory_frame_set
;
8590 /* Sanity check of the particle ranges. Split into multiple if
8591 * statements for improved readability */
8592 for(i
= 0; i
< frame_set
->n_mapping_blocks
; i
++)
8594 mapping
= &frame_set
->mappings
[i
];
8595 if(num_first_particle
>= mapping
->num_first_particle
&&
8596 num_first_particle
< mapping
->num_first_particle
+
8597 mapping
->n_particles
)
8599 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
8600 return(TNG_FAILURE
);
8602 if(num_first_particle
+ n_particles
>=
8603 mapping
->num_first_particle
&&
8604 num_first_particle
+ n_particles
<
8605 mapping
->num_first_particle
+ mapping
->n_particles
)
8607 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
8608 return(TNG_FAILURE
);
8610 if(mapping
->num_first_particle
>= num_first_particle
&&
8611 mapping
->num_first_particle
< num_first_particle
+
8614 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
8615 return(TNG_FAILURE
);
8617 if(mapping
->num_first_particle
+ mapping
->n_particles
>
8618 num_first_particle
&&
8619 mapping
->num_first_particle
+ mapping
->n_particles
<
8620 num_first_particle
+ n_particles
)
8622 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
8623 return(TNG_FAILURE
);
8627 frame_set
->n_mapping_blocks
++;
8629 mapping
= (tng_particle_mapping_t
)realloc(frame_set
->mappings
, sizeof(struct tng_particle_mapping
) *
8630 frame_set
->n_mapping_blocks
);
8634 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
8635 __FILE__
, __LINE__
);
8636 free(frame_set
->mappings
);
8637 frame_set
->mappings
= 0;
8638 return(TNG_CRITICAL
);
8640 frame_set
->mappings
= mapping
;
8642 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].num_first_particle
= num_first_particle
;
8643 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].n_particles
= n_particles
;
8645 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].real_particle_numbers
= (int64_t *)malloc(sizeof(int64_t) * n_particles
);
8646 if(!frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].real_particle_numbers
)
8648 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
8649 __FILE__
, __LINE__
);
8650 return(TNG_CRITICAL
);
8653 for(i
=0; i
<n_particles
; i
++)
8655 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].real_particle_numbers
[i
] = mapping_table
[i
];
8658 return(TNG_SUCCESS
);
8661 tng_function_status DECLSPECDLLEXPORT
tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data
)
8663 tng_trajectory_frame_set_t frame_set
;
8664 tng_particle_mapping_t mapping
;
8667 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8669 frame_set
= &tng_data
->current_trajectory_frame_set
;
8671 if(frame_set
->n_mapping_blocks
&& frame_set
->mappings
)
8673 for(i
= 0; i
< frame_set
->n_mapping_blocks
; i
++)
8675 mapping
= &frame_set
->mappings
[i
];
8676 if(mapping
->real_particle_numbers
)
8678 free(mapping
->real_particle_numbers
);
8679 mapping
->real_particle_numbers
= 0;
8682 free(frame_set
->mappings
);
8683 frame_set
->mappings
= 0;
8684 frame_set
->n_mapping_blocks
= 0;
8687 return(TNG_SUCCESS
);
8690 tng_function_status DECLSPECDLLEXPORT
tng_trajectory_init(tng_trajectory_t
*tng_data_p
)
8693 tng_trajectory_frame_set_t frame_set
;
8694 tng_trajectory_t tng_data
;
8696 *tng_data_p
= (tng_trajectory_t
)malloc(sizeof(struct tng_trajectory
));
8699 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
8700 __FILE__
, __LINE__
);
8701 return(TNG_CRITICAL
);
8704 tng_data
= *tng_data_p
;
8706 frame_set
= &tng_data
->current_trajectory_frame_set
;
8708 tng_data
->input_file_path
= 0;
8709 tng_data
->input_file
= 0;
8710 tng_data
->input_file_len
= 0;
8711 tng_data
->output_file_path
= 0;
8712 tng_data
->output_file
= 0;
8714 tng_data
->first_program_name
= 0;
8715 tng_data
->first_user_name
= 0;
8716 tng_data
->first_computer_name
= 0;
8717 tng_data
->first_pgp_signature
= 0;
8718 tng_data
->last_program_name
= 0;
8719 tng_data
->last_user_name
= 0;
8720 tng_data
->last_computer_name
= 0;
8721 tng_data
->last_pgp_signature
= 0;
8722 tng_data
->forcefield_name
= 0;
8727 fprintf(stderr
, "TNG library: Cannot get time. %s: %d\n", __FILE__
, __LINE__
);
8731 tng_data
->time
= seconds
;
8734 tng_data
->var_num_atoms_flag
= TNG_CONSTANT_N_ATOMS
;
8735 tng_data
->first_trajectory_frame_set_input_file_pos
= -1;
8736 tng_data
->last_trajectory_frame_set_input_file_pos
= -1;
8737 tng_data
->current_trajectory_frame_set_input_file_pos
= -1;
8738 tng_data
->first_trajectory_frame_set_output_file_pos
= -1;
8739 tng_data
->last_trajectory_frame_set_output_file_pos
= -1;
8740 tng_data
->current_trajectory_frame_set_output_file_pos
= -1;
8741 tng_data
->frame_set_n_frames
= 100;
8742 tng_data
->n_trajectory_frame_sets
= 0;
8743 tng_data
->medium_stride_length
= 100;
8744 tng_data
->long_stride_length
= 10000;
8746 tng_data
->time_per_frame
= -1;
8748 tng_data
->n_particle_data_blocks
= 0;
8749 tng_data
->n_data_blocks
= 0;
8751 tng_data
->non_tr_particle_data
= 0;
8752 tng_data
->non_tr_data
= 0;
8754 tng_data
->compress_algo_pos
= 0;
8755 tng_data
->compress_algo_vel
= 0;
8756 tng_data
->compression_precision
= 1000;
8757 tng_data
->distance_unit_exponential
= -9;
8759 frame_set
->first_frame
= -1;
8760 frame_set
->n_mapping_blocks
= 0;
8761 frame_set
->mappings
= 0;
8762 frame_set
->molecule_cnt_list
= 0;
8764 frame_set
->n_particle_data_blocks
= 0;
8765 frame_set
->n_data_blocks
= 0;
8767 frame_set
->tr_particle_data
= 0;
8768 frame_set
->tr_data
= 0;
8770 frame_set
->n_written_frames
= 0;
8771 frame_set
->n_unwritten_frames
= 0;
8773 frame_set
->next_frame_set_file_pos
= -1;
8774 frame_set
->prev_frame_set_file_pos
= -1;
8775 frame_set
->medium_stride_next_frame_set_file_pos
= -1;
8776 frame_set
->medium_stride_prev_frame_set_file_pos
= -1;
8777 frame_set
->long_stride_next_frame_set_file_pos
= -1;
8778 frame_set
->long_stride_prev_frame_set_file_pos
= -1;
8780 frame_set
->first_frame_time
= -1;
8782 tng_data
->n_molecules
= 0;
8783 tng_data
->molecules
= 0;
8784 tng_data
->molecule_cnt_list
= 0;
8785 tng_data
->n_particles
= 0;
8788 /* Check the endianness of the computer */
8789 static int32_t endianness_32
= 0x01234567;
8791 if ( *(const unsigned char*)&endianness_32
== 0x01 )
8793 tng_data
->endianness_32
= TNG_BIG_ENDIAN_32
;
8797 else if( *(const unsigned char*)&endianness_32
== 0x67 )
8799 tng_data
->endianness_32
= TNG_LITTLE_ENDIAN_32
;
8804 else if ( *(const unsigned char*)&endianness_32
== 0x45 )
8806 tng_data
->endianness_32
= TNG_BYTE_PAIR_SWAP_32
;
8810 static int64_t endianness_64
= 0x0123456789ABCDEFLL
;
8811 /* 0x0123456789ABCDEF */
8812 if ( *(const unsigned char*)&endianness_64
== 0x01 )
8814 tng_data
->endianness_64
= TNG_BIG_ENDIAN_64
;
8817 /* 0xEFCDAB8967452301 */
8818 else if ( *(const unsigned char*)&endianness_64
== 0xEF )
8820 tng_data
->endianness_64
= TNG_LITTLE_ENDIAN_64
;
8823 /* 0x89ABCDEF01234567 */
8824 else if ( *(const unsigned char*)&endianness_64
== 0x89 )
8826 tng_data
->endianness_64
= TNG_QUAD_SWAP_64
;
8829 /* 0x45670123CDEF89AB */
8830 else if ( *(const unsigned char*)&endianness_64
== 0x45 )
8832 tng_data
->endianness_64
= TNG_BYTE_PAIR_SWAP_64
;
8835 /* 0x23016745AB89EFCD */
8836 else if ( *(const unsigned char*)&endianness_64
== 0x23 )
8838 tng_data
->endianness_64
= TNG_BYTE_SWAP_64
;
8842 /* By default do not swap the byte order, i.e. keep the byte order of the
8843 * architecture. The input file endianness will be set when reading the
8844 * header. The output endianness can be changed - before the file is
8846 tng_data
->input_endianness_swap_func_32
= 0;
8847 tng_data
->input_endianness_swap_func_64
= 0;
8848 tng_data
->output_endianness_swap_func_32
= 0;
8849 tng_data
->output_endianness_swap_func_64
= 0;
8851 tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
= -1;
8852 tng_data
->current_trajectory_frame_set
.prev_frame_set_file_pos
= -1;
8853 tng_data
->current_trajectory_frame_set
.n_frames
= 0;
8855 return(TNG_SUCCESS
);
8858 tng_function_status DECLSPECDLLEXPORT
tng_trajectory_destroy(tng_trajectory_t
*tng_data_p
)
8861 int64_t n_particles
, n_values_per_frame
;
8862 tng_trajectory_t tng_data
= *tng_data_p
;
8863 tng_trajectory_frame_set_t frame_set
;
8867 return(TNG_SUCCESS
);
8870 frame_set
= &tng_data
->current_trajectory_frame_set
;
8872 if(tng_data
->input_file
)
8874 if(tng_data
->output_file
== tng_data
->input_file
)
8876 tng_frame_set_finalize(tng_data
, TNG_USE_HASH
);
8877 tng_data
->output_file
= 0;
8879 fclose(tng_data
->input_file
);
8880 tng_data
->input_file
= 0;
8883 if(tng_data
->input_file_path
)
8885 free(tng_data
->input_file_path
);
8886 tng_data
->input_file_path
= 0;
8889 if(tng_data
->output_file
)
8891 /* FIXME: Do not always write the hash */
8892 tng_frame_set_finalize(tng_data
, TNG_USE_HASH
);
8893 fclose(tng_data
->output_file
);
8894 tng_data
->output_file
= 0;
8897 if(tng_data
->output_file_path
)
8899 free(tng_data
->output_file_path
);
8900 tng_data
->output_file_path
= 0;
8903 if(tng_data
->first_program_name
)
8905 free(tng_data
->first_program_name
);
8906 tng_data
->first_program_name
= 0;
8909 if(tng_data
->last_program_name
)
8911 free(tng_data
->last_program_name
);
8912 tng_data
->last_program_name
= 0;
8915 if(tng_data
->first_user_name
)
8917 free(tng_data
->first_user_name
);
8918 tng_data
->first_user_name
= 0;
8921 if(tng_data
->last_user_name
)
8923 free(tng_data
->last_user_name
);
8924 tng_data
->last_user_name
= 0;
8927 if(tng_data
->first_computer_name
)
8929 free(tng_data
->first_computer_name
);
8930 tng_data
->first_computer_name
= 0;
8933 if(tng_data
->last_computer_name
)
8935 free(tng_data
->last_computer_name
);
8936 tng_data
->last_computer_name
= 0;
8939 if(tng_data
->first_pgp_signature
)
8941 free(tng_data
->first_pgp_signature
);
8942 tng_data
->first_pgp_signature
= 0;
8945 if(tng_data
->last_pgp_signature
)
8947 free(tng_data
->last_pgp_signature
);
8948 tng_data
->last_pgp_signature
= 0;
8951 if(tng_data
->forcefield_name
)
8953 free(tng_data
->forcefield_name
);
8954 tng_data
->forcefield_name
= 0;
8957 tng_frame_set_particle_mapping_free(tng_data
);
8959 if(frame_set
->molecule_cnt_list
)
8961 free(frame_set
->molecule_cnt_list
);
8962 frame_set
->molecule_cnt_list
= 0;
8965 if(tng_data
->var_num_atoms_flag
)
8967 n_particles
= frame_set
->n_particles
;
8971 n_particles
= tng_data
->n_particles
;
8974 if(tng_data
->non_tr_particle_data
)
8976 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
8978 if(tng_data
->non_tr_particle_data
[i
].values
)
8980 free(tng_data
->non_tr_particle_data
[i
].values
);
8981 tng_data
->non_tr_particle_data
[i
].values
= 0;
8984 if(tng_data
->non_tr_particle_data
[i
].strings
)
8986 n_values_per_frame
= tng_data
->non_tr_particle_data
[i
].
8988 if(tng_data
->non_tr_particle_data
[i
].strings
[0])
8990 for(j
= 0; j
< n_particles
; j
++)
8992 if(tng_data
->non_tr_particle_data
[i
].strings
[0][j
])
8994 for(k
= 0; k
< n_values_per_frame
; k
++)
8996 if(tng_data
->non_tr_particle_data
[i
].
8999 free(tng_data
->non_tr_particle_data
[i
].
9001 tng_data
->non_tr_particle_data
[i
].
9002 strings
[0][j
][k
] = 0;
9005 free(tng_data
->non_tr_particle_data
[i
].
9007 tng_data
->non_tr_particle_data
[i
].strings
[0][j
] = 0;
9010 free(tng_data
->non_tr_particle_data
[i
].strings
[0]);
9011 tng_data
->non_tr_particle_data
[i
].strings
[0] = 0;
9013 free(tng_data
->non_tr_particle_data
[i
].strings
);
9014 tng_data
->non_tr_particle_data
[i
].strings
= 0;
9017 if(tng_data
->non_tr_particle_data
[i
].block_name
)
9019 free(tng_data
->non_tr_particle_data
[i
].block_name
);
9020 tng_data
->non_tr_particle_data
[i
].block_name
= 0;
9023 free(tng_data
->non_tr_particle_data
);
9024 tng_data
->non_tr_particle_data
= 0;
9027 if(tng_data
->non_tr_data
)
9029 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
9031 if(tng_data
->non_tr_data
[i
].values
)
9033 free(tng_data
->non_tr_data
[i
].values
);
9034 tng_data
->non_tr_data
[i
].values
= 0;
9037 if(tng_data
->non_tr_data
[i
].strings
)
9039 n_values_per_frame
= tng_data
->non_tr_data
[i
].
9041 if(tng_data
->non_tr_data
[i
].strings
[0][0])
9043 for(j
= 0; j
< n_values_per_frame
; j
++)
9045 if(tng_data
->non_tr_data
[i
].strings
[0][0][j
])
9047 free(tng_data
->non_tr_data
[i
].strings
[0][0][j
]);
9048 tng_data
->non_tr_data
[i
].strings
[0][0][j
] = 0;
9051 free(tng_data
->non_tr_data
[i
].strings
[0][0]);
9052 tng_data
->non_tr_data
[i
].strings
[0][0] = 0;
9054 free(tng_data
->non_tr_data
[i
].strings
[0]);
9055 tng_data
->non_tr_data
[i
].strings
[0] = 0;
9056 free(tng_data
->non_tr_data
[i
].strings
);
9057 tng_data
->non_tr_data
[i
].strings
= 0;
9060 if(tng_data
->non_tr_data
[i
].block_name
)
9062 free(tng_data
->non_tr_data
[i
].block_name
);
9063 tng_data
->non_tr_data
[i
].block_name
= 0;
9066 free(tng_data
->non_tr_data
);
9067 tng_data
->non_tr_data
= 0;
9070 tng_data
->n_particle_data_blocks
= 0;
9071 tng_data
->n_data_blocks
= 0;
9073 if(tng_data
->compress_algo_pos
)
9075 free(tng_data
->compress_algo_pos
);
9076 tng_data
->compress_algo_pos
= 0;
9078 if(tng_data
->compress_algo_vel
)
9080 free(tng_data
->compress_algo_vel
);
9081 tng_data
->compress_algo_vel
= 0;
9084 if(frame_set
->tr_particle_data
)
9086 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
9088 if(frame_set
->tr_particle_data
[i
].values
)
9090 free(frame_set
->tr_particle_data
[i
].values
);
9091 frame_set
->tr_particle_data
[i
].values
= 0;
9094 if(frame_set
->tr_particle_data
[i
].strings
)
9096 n_values_per_frame
= frame_set
->tr_particle_data
[i
].
9098 for(j
= 0; j
< frame_set
->tr_particle_data
[i
].n_frames
; j
++)
9100 if(frame_set
->tr_particle_data
[i
].strings
[j
])
9102 for(k
= 0; k
< n_particles
; k
++)
9104 if(frame_set
->tr_particle_data
[i
].
9107 for(l
= 0; l
< n_values_per_frame
; l
++)
9109 if(frame_set
->tr_particle_data
[i
].
9112 free(frame_set
->tr_particle_data
[i
].
9114 frame_set
->tr_particle_data
[i
].
9115 strings
[j
][k
][l
] = 0;
9118 free(frame_set
->tr_particle_data
[i
].
9120 frame_set
->tr_particle_data
[i
].
9124 free(frame_set
->tr_particle_data
[i
].strings
[j
]);
9125 frame_set
->tr_particle_data
[i
].strings
[j
] = 0;
9128 free(frame_set
->tr_particle_data
[i
].strings
);
9129 frame_set
->tr_particle_data
[i
].strings
= 0;
9132 if(frame_set
->tr_particle_data
[i
].block_name
)
9134 free(frame_set
->tr_particle_data
[i
].block_name
);
9135 frame_set
->tr_particle_data
[i
].block_name
= 0;
9138 free(frame_set
->tr_particle_data
);
9139 frame_set
->tr_particle_data
= 0;
9142 if(frame_set
->tr_data
)
9144 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
9146 if(frame_set
->tr_data
[i
].values
)
9148 free(frame_set
->tr_data
[i
].values
);
9149 frame_set
->tr_data
[i
].values
= 0;
9152 if(frame_set
->tr_data
[i
].strings
)
9154 n_values_per_frame
= frame_set
->tr_data
[i
].
9156 for(j
= 0; j
< frame_set
->tr_data
[i
].n_frames
; j
++)
9158 if(frame_set
->tr_data
[i
].strings
[j
])
9160 for(k
= 0; k
< n_values_per_frame
; k
++)
9162 if(frame_set
->tr_data
[i
].strings
[j
][k
])
9164 free(frame_set
->tr_data
[i
].strings
[j
][k
]);
9165 frame_set
->tr_data
[i
].strings
[j
][k
] = 0;
9168 free(frame_set
->tr_data
[i
].strings
[j
]);
9169 frame_set
->tr_data
[i
].strings
[j
] = 0;
9172 free(frame_set
->tr_data
[i
].strings
);
9173 frame_set
->tr_data
[i
].strings
= 0;
9176 if(frame_set
->tr_data
[i
].block_name
)
9178 free(frame_set
->tr_data
[i
].block_name
);
9179 frame_set
->tr_data
[i
].block_name
= 0;
9182 free(frame_set
->tr_data
);
9183 frame_set
->tr_data
= 0;
9186 frame_set
->n_particle_data_blocks
= 0;
9187 frame_set
->n_data_blocks
= 0;
9189 if(tng_data
->molecules
)
9191 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9193 tng_molecule_destroy(tng_data
, &tng_data
->molecules
[i
]);
9195 free(tng_data
->molecules
);
9196 tng_data
->molecules
= 0;
9197 tng_data
->n_molecules
= 0;
9199 if(tng_data
->molecule_cnt_list
)
9201 free(tng_data
->molecule_cnt_list
);
9202 tng_data
->molecule_cnt_list
= 0;
9208 return(TNG_SUCCESS
);
9211 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
9212 (const tng_trajectory_t src
,
9213 tng_trajectory_t
*dest_p
)
9215 tng_trajectory_frame_set_t frame_set
;
9216 tng_trajectory_t dest
;
9218 TNG_ASSERT(src
!= 0, "TNG library: Source trajectory must not be NULL.");
9220 *dest_p
= (tng_trajectory_t
)malloc(sizeof(struct tng_trajectory
));
9223 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9224 __FILE__
, __LINE__
);
9225 return(TNG_CRITICAL
);
9230 frame_set
= &dest
->current_trajectory_frame_set
;
9232 if(src
->input_file_path
)
9234 dest
->input_file_path
= (char *)malloc(strlen(src
->input_file_path
) + 1);
9235 if(!dest
->input_file_path
)
9237 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9238 __FILE__
, __LINE__
);
9239 return(TNG_CRITICAL
);
9241 strcpy(dest
->input_file_path
, src
->input_file_path
);
9242 dest
->input_file_len
= src
->input_file_len
;
9246 dest
->input_file_path
= 0;
9248 dest
->input_file
= 0;
9249 if(src
->output_file_path
)
9251 dest
->output_file_path
= (char *)malloc(strlen(src
->output_file_path
) + 1);
9252 if(!dest
->output_file_path
)
9254 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9255 __FILE__
, __LINE__
);
9256 return(TNG_CRITICAL
);
9258 strcpy(dest
->output_file_path
, src
->output_file_path
);
9262 dest
->output_file_path
= 0;
9264 dest
->output_file
= 0;
9266 dest
->first_program_name
= 0;
9267 dest
->first_user_name
= 0;
9268 dest
->first_computer_name
= 0;
9269 dest
->first_pgp_signature
= 0;
9270 dest
->last_program_name
= 0;
9271 dest
->last_user_name
= 0;
9272 dest
->last_computer_name
= 0;
9273 dest
->last_pgp_signature
= 0;
9274 dest
->forcefield_name
= 0;
9276 dest
->var_num_atoms_flag
= src
->var_num_atoms_flag
;
9277 dest
->first_trajectory_frame_set_input_file_pos
=
9278 src
->first_trajectory_frame_set_input_file_pos
;
9279 dest
->last_trajectory_frame_set_input_file_pos
=
9280 src
->last_trajectory_frame_set_input_file_pos
;
9281 dest
->current_trajectory_frame_set_input_file_pos
=
9282 src
->current_trajectory_frame_set_input_file_pos
;
9283 dest
->first_trajectory_frame_set_output_file_pos
=
9284 src
->first_trajectory_frame_set_output_file_pos
;
9285 dest
->last_trajectory_frame_set_output_file_pos
=
9286 src
->last_trajectory_frame_set_output_file_pos
;
9287 dest
->current_trajectory_frame_set_output_file_pos
=
9288 src
->current_trajectory_frame_set_output_file_pos
;
9289 dest
->frame_set_n_frames
= src
->frame_set_n_frames
;
9290 dest
->n_trajectory_frame_sets
= src
->n_trajectory_frame_sets
;
9291 dest
->medium_stride_length
= src
->medium_stride_length
;
9292 dest
->long_stride_length
= src
->long_stride_length
;
9294 dest
->time_per_frame
= src
->time_per_frame
;
9296 /* Currently the non trajectory data blocks are not copied since it
9297 * can lead to problems when freeing memory in a parallel block. */
9298 dest
->n_particle_data_blocks
= 0;
9299 dest
->n_data_blocks
= 0;
9300 dest
->non_tr_particle_data
= 0;
9301 dest
->non_tr_data
= 0;
9303 dest
->compress_algo_pos
= 0;
9304 dest
->compress_algo_vel
= 0;
9305 dest
->distance_unit_exponential
= -9;
9306 dest
->compression_precision
= 1000;
9308 frame_set
->n_mapping_blocks
= 0;
9309 frame_set
->mappings
= 0;
9310 frame_set
->molecule_cnt_list
= 0;
9312 frame_set
->n_particle_data_blocks
= 0;
9313 frame_set
->n_data_blocks
= 0;
9315 frame_set
->tr_particle_data
= 0;
9316 frame_set
->tr_data
= 0;
9318 frame_set
->n_written_frames
= 0;
9319 frame_set
->n_unwritten_frames
= 0;
9321 frame_set
->next_frame_set_file_pos
= -1;
9322 frame_set
->prev_frame_set_file_pos
= -1;
9323 frame_set
->medium_stride_next_frame_set_file_pos
= -1;
9324 frame_set
->medium_stride_prev_frame_set_file_pos
= -1;
9325 frame_set
->long_stride_next_frame_set_file_pos
= -1;
9326 frame_set
->long_stride_prev_frame_set_file_pos
= -1;
9327 frame_set
->first_frame
= -1;
9329 dest
->n_molecules
= 0;
9330 dest
->molecules
= 0;
9331 dest
->molecule_cnt_list
= 0;
9332 dest
->n_particles
= src
->n_particles
;
9334 dest
->endianness_32
= src
->endianness_32
;
9335 dest
->endianness_64
= src
->endianness_64
;
9336 dest
->input_endianness_swap_func_32
= src
->input_endianness_swap_func_32
;
9337 dest
->input_endianness_swap_func_64
= src
->input_endianness_swap_func_64
;
9338 dest
->output_endianness_swap_func_32
= src
->output_endianness_swap_func_32
;
9339 dest
->output_endianness_swap_func_64
= src
->output_endianness_swap_func_64
;
9341 dest
->current_trajectory_frame_set
.next_frame_set_file_pos
= -1;
9342 dest
->current_trajectory_frame_set
.prev_frame_set_file_pos
= -1;
9343 dest
->current_trajectory_frame_set
.n_frames
= 0;
9345 return(TNG_SUCCESS
);
9348 tng_function_status DECLSPECDLLEXPORT tng_input_file_get
9349 (const tng_trajectory_t tng_data
,
9353 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9354 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
9356 strncpy(file_name
, tng_data
->input_file_path
, max_len
- 1);
9357 file_name
[max_len
- 1] = 0;
9359 if(strlen(tng_data
->input_file_path
) > (unsigned int)max_len
- 1)
9361 return(TNG_FAILURE
);
9363 return(TNG_SUCCESS
);
9366 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
9367 (const tng_trajectory_t tng_data
,
9368 const char *file_name
)
9373 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9374 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
9377 if(tng_data
->input_file_path
&& strcmp(tng_data
->input_file_path
,
9380 return(TNG_SUCCESS
);
9383 if(tng_data
->input_file
)
9385 fclose(tng_data
->input_file
);
9388 len
= tng_min_size(strlen(file_name
) + 1, TNG_MAX_STR_LEN
);
9389 temp
= (char *)realloc(tng_data
->input_file_path
, len
);
9392 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9393 __FILE__
, __LINE__
);
9394 free(tng_data
->input_file_path
);
9395 tng_data
->input_file_path
= 0;
9396 return(TNG_CRITICAL
);
9398 tng_data
->input_file_path
= temp
;
9400 strncpy(tng_data
->input_file_path
, file_name
, len
);
9402 return(tng_input_file_init(tng_data
));
9405 tng_function_status tng_output_file_get
9406 (const tng_trajectory_t tng_data
,
9410 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9411 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
9413 strncpy(file_name
, tng_data
->output_file_path
, max_len
- 1);
9414 file_name
[max_len
- 1] = 0;
9416 if(strlen(tng_data
->output_file_path
) > (unsigned int)max_len
- 1)
9418 return(TNG_FAILURE
);
9420 return(TNG_SUCCESS
);
9423 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
9424 (const tng_trajectory_t tng_data
,
9425 const char *file_name
)
9430 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9431 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
9433 if(tng_data
->output_file_path
&&
9434 strcmp(tng_data
->output_file_path
, file_name
) == 0)
9436 return(TNG_SUCCESS
);
9439 if(tng_data
->output_file
)
9441 fclose(tng_data
->output_file
);
9444 len
= tng_min_size(strlen(file_name
) + 1, TNG_MAX_STR_LEN
);
9445 temp
= (char *)realloc(tng_data
->output_file_path
, len
);
9448 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9449 __FILE__
, __LINE__
);
9450 free(tng_data
->output_file_path
);
9451 tng_data
->output_file_path
= 0;
9452 return(TNG_CRITICAL
);
9454 tng_data
->output_file_path
= temp
;
9456 strncpy(tng_data
->output_file_path
, file_name
, len
);
9458 return(tng_output_file_init(tng_data
));
9461 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9462 (const tng_trajectory_t tng_data
,
9463 const char *file_name
)
9468 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9469 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
9471 if(tng_data
->output_file_path
&&
9472 strcmp(tng_data
->output_file_path
, file_name
) == 0)
9474 return(TNG_SUCCESS
);
9477 if(tng_data
->output_file
)
9479 fclose(tng_data
->output_file
);
9482 len
= tng_min_size(strlen(file_name
) + 1, TNG_MAX_STR_LEN
);
9483 temp
= (char *)realloc(tng_data
->output_file_path
, len
);
9486 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9487 __FILE__
, __LINE__
);
9488 free(tng_data
->output_file_path
);
9489 tng_data
->output_file_path
= 0;
9490 return(TNG_CRITICAL
);
9492 tng_data
->output_file_path
= temp
;
9494 strncpy(tng_data
->output_file_path
, file_name
, len
);
9496 tng_data
->output_file
= fopen(tng_data
->output_file_path
, "rb+");
9497 if(!tng_data
->output_file
)
9499 fprintf(stderr
, "TNG library: Cannot open file %s. %s: %d\n",
9500 tng_data
->output_file_path
, __FILE__
, __LINE__
);
9501 return(TNG_CRITICAL
);
9503 tng_data
->input_file
= tng_data
->output_file
;
9505 return(TNG_SUCCESS
);
9508 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9509 (const tng_trajectory_t tng_data
, tng_file_endianness
*endianness
)
9511 tng_endianness_32 end_32
;
9512 tng_endianness_64 end_64
;
9514 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9515 TNG_ASSERT(endianness
, "TNG library: endianness must not be a NULL pointer");
9517 if(tng_data
->output_endianness_swap_func_32
)
9519 /* If other endianness variants are added they must be added here as well */
9520 if(tng_data
->output_endianness_swap_func_32
==
9521 &tng_swap_byte_order_big_endian_32
)
9523 end_32
= TNG_BIG_ENDIAN_32
;
9525 else if(tng_data
->output_endianness_swap_func_32
==
9526 &tng_swap_byte_order_little_endian_32
)
9528 end_32
= TNG_LITTLE_ENDIAN_32
;
9532 return(TNG_FAILURE
);
9537 end_32
= (tng_endianness_32
)tng_data
->endianness_32
;
9540 if(tng_data
->output_endianness_swap_func_64
)
9542 /* If other endianness variants are added they must be added here as well */
9543 if(tng_data
->output_endianness_swap_func_64
==
9544 &tng_swap_byte_order_big_endian_64
)
9546 end_64
= TNG_BIG_ENDIAN_64
;
9548 else if(tng_data
->output_endianness_swap_func_64
==
9549 &tng_swap_byte_order_little_endian_64
)
9551 end_64
= TNG_LITTLE_ENDIAN_64
;
9555 return(TNG_FAILURE
);
9560 end_64
= (tng_endianness_64
)tng_data
->endianness_64
;
9563 if((int)end_32
!= (int)end_64
)
9565 return(TNG_FAILURE
);
9568 if(end_32
== TNG_LITTLE_ENDIAN_32
)
9570 *endianness
= TNG_LITTLE_ENDIAN
;
9573 else if(end_32
== TNG_BIG_ENDIAN_32
)
9575 *endianness
= TNG_BIG_ENDIAN
;
9579 return(TNG_FAILURE
);
9582 return(TNG_SUCCESS
);
9585 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9586 (const tng_trajectory_t tng_data
,
9587 const tng_file_endianness endianness
)
9589 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9591 /* Tne endianness cannot be changed if the data has already been written
9592 * to the output file. */
9593 if(ftello(tng_data
->output_file
) > 0)
9595 return(TNG_FAILURE
);
9598 if(endianness
== TNG_BIG_ENDIAN
)
9600 if(tng_data
->endianness_32
== TNG_BIG_ENDIAN_32
)
9602 tng_data
->output_endianness_swap_func_32
= 0;
9606 tng_data
->output_endianness_swap_func_32
=
9607 &tng_swap_byte_order_big_endian_32
;
9609 if(tng_data
->endianness_64
== TNG_BIG_ENDIAN_64
)
9611 tng_data
->output_endianness_swap_func_64
= 0;
9615 tng_data
->output_endianness_swap_func_64
=
9616 &tng_swap_byte_order_big_endian_64
;
9618 return(TNG_SUCCESS
);
9620 else if(endianness
== TNG_LITTLE_ENDIAN
)
9622 if(tng_data
->endianness_32
== TNG_LITTLE_ENDIAN_32
)
9624 tng_data
->output_endianness_swap_func_32
= 0;
9628 tng_data
->output_endianness_swap_func_32
=
9629 &tng_swap_byte_order_little_endian_32
;
9631 if(tng_data
->endianness_64
== TNG_LITTLE_ENDIAN_64
)
9633 tng_data
->output_endianness_swap_func_64
= 0;
9637 tng_data
->output_endianness_swap_func_64
=
9638 &tng_swap_byte_order_little_endian_64
;
9640 return(TNG_SUCCESS
);
9643 /* If the specified endianness is neither big nor little endian return a
9645 return(TNG_FAILURE
);
9648 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9649 (const tng_trajectory_t tng_data
,
9653 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9654 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
9656 strncpy(name
, tng_data
->first_program_name
, max_len
- 1);
9657 name
[max_len
- 1] = 0;
9659 if(strlen(tng_data
->first_program_name
) > (unsigned int)max_len
- 1)
9661 return(TNG_FAILURE
);
9663 return(TNG_SUCCESS
);
9666 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
9667 (const tng_trajectory_t tng_data
,
9668 const char *new_name
)
9672 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9673 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
9675 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
9677 if(tng_data
->first_program_name
&& strlen(tng_data
->first_program_name
) < len
)
9679 free(tng_data
->first_program_name
);
9680 tng_data
->first_program_name
= 0;
9682 if(!tng_data
->first_program_name
)
9684 tng_data
->first_program_name
= (char *)malloc(len
);
9685 if(!tng_data
->first_program_name
)
9687 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9688 __FILE__
, __LINE__
);
9689 return(TNG_CRITICAL
);
9693 strncpy(tng_data
->first_program_name
, new_name
, len
);
9695 return(TNG_SUCCESS
);
9698 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
9699 (const tng_trajectory_t tng_data
,
9700 char *name
, const int max_len
)
9702 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9703 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
9705 strncpy(name
, tng_data
->last_program_name
, max_len
- 1);
9706 name
[max_len
- 1] = 0;
9708 if(strlen(tng_data
->last_program_name
) > (unsigned int)max_len
- 1)
9710 return(TNG_FAILURE
);
9712 return(TNG_SUCCESS
);
9715 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
9716 (const tng_trajectory_t tng_data
,
9717 const char *new_name
)
9721 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9722 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
9724 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
9726 if(tng_data
->last_program_name
&& strlen(tng_data
->last_program_name
) < len
)
9728 free(tng_data
->last_program_name
);
9729 tng_data
->last_program_name
= 0;
9731 if(!tng_data
->last_program_name
)
9733 tng_data
->last_program_name
= (char *)malloc(len
);
9734 if(!tng_data
->last_program_name
)
9736 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9737 __FILE__
, __LINE__
);
9738 return(TNG_CRITICAL
);
9742 strncpy(tng_data
->last_program_name
, new_name
, len
);
9744 return(TNG_SUCCESS
);
9747 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
9748 (const tng_trajectory_t tng_data
,
9749 char *name
, const int max_len
)
9751 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9752 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
9754 strncpy(name
, tng_data
->first_user_name
, max_len
- 1);
9755 name
[max_len
- 1] = 0;
9757 if(strlen(tng_data
->first_user_name
) > (unsigned int)max_len
- 1)
9759 return(TNG_FAILURE
);
9761 return(TNG_SUCCESS
);
9764 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
9765 (const tng_trajectory_t tng_data
,
9766 const char *new_name
)
9770 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9771 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
9773 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
9775 /* If the currently stored string length is not enough to store the new
9776 * string it is freed and reallocated. */
9777 if(tng_data
->first_user_name
&& strlen(tng_data
->first_user_name
) < len
)
9779 free(tng_data
->first_user_name
);
9780 tng_data
->first_user_name
= 0;
9782 if(!tng_data
->first_user_name
)
9784 tng_data
->first_user_name
= (char *)malloc(len
);
9785 if(!tng_data
->first_user_name
)
9787 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9788 __FILE__
, __LINE__
);
9789 return(TNG_CRITICAL
);
9793 strncpy(tng_data
->first_user_name
, new_name
, len
);
9795 return(TNG_SUCCESS
);
9798 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
9799 (const tng_trajectory_t tng_data
,
9800 char *name
, const int max_len
)
9802 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9803 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
9805 strncpy(name
, tng_data
->last_user_name
, max_len
- 1);
9806 name
[max_len
- 1] = 0;
9808 if(strlen(tng_data
->last_user_name
) > (unsigned int)max_len
- 1)
9810 return(TNG_FAILURE
);
9812 return(TNG_SUCCESS
);
9815 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
9816 (const tng_trajectory_t tng_data
,
9817 const char *new_name
)
9821 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9822 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
9824 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
9826 /* If the currently stored string length is not enough to store the new
9827 * string it is freed and reallocated. */
9828 if(tng_data
->last_user_name
&& strlen(tng_data
->last_user_name
) < len
)
9830 free(tng_data
->last_user_name
);
9831 tng_data
->last_user_name
= 0;
9833 if(!tng_data
->last_user_name
)
9835 tng_data
->last_user_name
= (char *)malloc(len
);
9836 if(!tng_data
->last_user_name
)
9838 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9839 __FILE__
, __LINE__
);
9840 return(TNG_CRITICAL
);
9844 strncpy(tng_data
->last_user_name
, new_name
, len
);
9846 return(TNG_SUCCESS
);
9849 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
9850 (const tng_trajectory_t tng_data
,
9851 char *name
, const int max_len
)
9853 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9854 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
9856 strncpy(name
, tng_data
->first_computer_name
, max_len
- 1);
9857 name
[max_len
- 1] = 0;
9859 if(strlen(tng_data
->first_computer_name
) > (unsigned int)max_len
- 1)
9861 return(TNG_FAILURE
);
9863 return(TNG_SUCCESS
);
9866 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
9867 (const tng_trajectory_t tng_data
,
9868 const char *new_name
)
9872 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9873 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
9875 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
9877 /* If the currently stored string length is not enough to store the new
9878 * string it is freed and reallocated. */
9879 if(tng_data
->first_computer_name
&& strlen(tng_data
->first_computer_name
) < len
)
9881 free(tng_data
->first_computer_name
);
9882 tng_data
->first_computer_name
= 0;
9884 if(!tng_data
->first_computer_name
)
9886 tng_data
->first_computer_name
= (char *)malloc(len
);
9887 if(!tng_data
->first_computer_name
)
9889 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9890 __FILE__
, __LINE__
);
9891 return(TNG_CRITICAL
);
9895 strncpy(tng_data
->first_computer_name
, new_name
, len
);
9897 return(TNG_SUCCESS
);
9900 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
9901 (const tng_trajectory_t tng_data
,
9902 char *name
, const int max_len
)
9904 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9905 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
9907 strncpy(name
, tng_data
->last_computer_name
, max_len
- 1);
9908 name
[max_len
- 1] = 0;
9910 if(strlen(tng_data
->last_computer_name
) > (unsigned int)max_len
- 1)
9912 return(TNG_FAILURE
);
9914 return(TNG_SUCCESS
);
9917 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
9918 (const tng_trajectory_t tng_data
,
9919 const char *new_name
)
9923 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9924 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
9926 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
9928 /* If the currently stored string length is not enough to store the new
9929 * string it is freed and reallocated. */
9930 if(tng_data
->last_computer_name
&& strlen(tng_data
->last_computer_name
) <
9933 free(tng_data
->last_computer_name
);
9934 tng_data
->last_computer_name
= 0;
9936 if(!tng_data
->last_computer_name
)
9938 tng_data
->last_computer_name
= (char *)malloc(len
);
9939 if(!tng_data
->last_computer_name
)
9941 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9942 __FILE__
, __LINE__
);
9943 return(TNG_CRITICAL
);
9947 strncpy(tng_data
->last_computer_name
, new_name
, len
);
9949 return(TNG_SUCCESS
);
9952 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
9953 (const tng_trajectory_t tng_data
,
9954 char *signature
, const int max_len
)
9956 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9957 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
9959 strncpy(signature
, tng_data
->first_pgp_signature
, max_len
- 1);
9960 signature
[max_len
- 1] = 0;
9962 if(strlen(tng_data
->first_pgp_signature
) > (unsigned int)max_len
- 1)
9964 return(TNG_FAILURE
);
9966 return(TNG_SUCCESS
);
9969 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
9970 (const tng_trajectory_t tng_data
,
9971 const char *signature
)
9975 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9976 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
9978 len
= tng_min_size(strlen(signature
) + 1, TNG_MAX_STR_LEN
);
9980 /* If the currently stored string length is not enough to store the new
9981 * string it is freed and reallocated. */
9982 if(tng_data
->first_pgp_signature
&& strlen(tng_data
->first_pgp_signature
) <
9985 free(tng_data
->first_pgp_signature
);
9986 tng_data
->first_pgp_signature
= 0;
9988 if(!tng_data
->first_pgp_signature
)
9990 tng_data
->first_pgp_signature
= (char *)malloc(len
);
9991 if(!tng_data
->first_pgp_signature
)
9993 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
9994 __FILE__
, __LINE__
);
9995 return(TNG_CRITICAL
);
9999 strncpy(tng_data
->first_pgp_signature
, signature
, len
);
10001 return(TNG_SUCCESS
);
10004 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10005 (const tng_trajectory_t tng_data
,
10006 char *signature
, const int max_len
)
10008 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10009 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
10011 strncpy(signature
, tng_data
->last_pgp_signature
, max_len
- 1);
10012 signature
[max_len
- 1] = 0;
10014 if(strlen(tng_data
->last_pgp_signature
) > (unsigned int)max_len
- 1)
10016 return(TNG_FAILURE
);
10018 return(TNG_SUCCESS
);
10021 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10022 (const tng_trajectory_t tng_data
,
10023 const char *signature
)
10027 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10028 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
10030 len
= tng_min_size(strlen(signature
) + 1, TNG_MAX_STR_LEN
);
10032 /* If the currently stored string length is not enough to store the new
10033 * string it is freed and reallocated. */
10034 if(tng_data
->last_pgp_signature
&& strlen(tng_data
->last_pgp_signature
) <
10037 free(tng_data
->last_pgp_signature
);
10038 tng_data
->last_pgp_signature
= 0;
10040 if(!tng_data
->last_pgp_signature
)
10042 tng_data
->last_pgp_signature
= (char *)malloc(len
);
10043 if(!tng_data
->last_pgp_signature
)
10045 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
10046 __FILE__
, __LINE__
);
10047 return(TNG_CRITICAL
);
10051 strncpy(tng_data
->last_pgp_signature
, signature
, len
);
10053 return(TNG_SUCCESS
);
10056 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10057 (const tng_trajectory_t tng_data
,
10058 char *name
, const int max_len
)
10060 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10061 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10063 strncpy(name
, tng_data
->forcefield_name
, max_len
- 1);
10064 name
[max_len
- 1] = 0;
10066 if(strlen(tng_data
->forcefield_name
) > (unsigned int)max_len
- 1)
10068 return(TNG_FAILURE
);
10070 return(TNG_SUCCESS
);
10073 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10074 (const tng_trajectory_t tng_data
,
10075 const char *new_name
)
10079 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10080 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10082 len
= tng_min_size(strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10084 /* If the currently stored string length is not enough to store the new
10085 * string it is freed and reallocated. */
10086 if(tng_data
->forcefield_name
&& strlen(tng_data
->forcefield_name
) < len
)
10088 free(tng_data
->forcefield_name
);
10089 tng_data
->forcefield_name
= 0;
10091 if(!tng_data
->forcefield_name
)
10093 tng_data
->forcefield_name
= (char *)malloc(len
);
10094 if(!tng_data
->forcefield_name
)
10096 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
10097 __FILE__
, __LINE__
);
10098 return(TNG_CRITICAL
);
10102 strncpy(tng_data
->forcefield_name
, new_name
, len
);
10104 return(TNG_SUCCESS
);
10107 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10108 (const tng_trajectory_t tng_data
,
10111 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10112 TNG_ASSERT(len
, "TNG library: len must not be a NULL pointer");
10114 *len
= tng_data
->medium_stride_length
;
10116 return(TNG_SUCCESS
);
10119 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10120 (const tng_trajectory_t tng_data
,
10123 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10125 if(len
>= tng_data
->long_stride_length
)
10127 return(TNG_FAILURE
);
10129 tng_data
->medium_stride_length
= len
;
10131 return(TNG_SUCCESS
);
10134 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10135 (const tng_trajectory_t tng_data
,
10138 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10139 TNG_ASSERT(len
, "TNG library: len must not be a NULL pointer");
10141 *len
= tng_data
->long_stride_length
;
10143 return(TNG_SUCCESS
);
10146 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10147 (const tng_trajectory_t tng_data
,
10150 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10152 if(len
<= tng_data
->medium_stride_length
)
10154 return(TNG_FAILURE
);
10156 tng_data
->long_stride_length
= len
;
10158 return(TNG_SUCCESS
);
10161 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10162 (const tng_trajectory_t tng_data
,
10165 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10166 TNG_ASSERT(time
, "TNG library: time must not be a NULL pointer");
10168 *time
= tng_data
->time_per_frame
;
10170 return(TNG_SUCCESS
);
10173 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10174 (const tng_trajectory_t tng_data
,
10177 tng_trajectory_frame_set_t frame_set
;
10179 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10180 TNG_ASSERT(time
>= 0, "TNG library: The time per frame must be >= 0.");
10182 if(fabs(time
- tng_data
->time_per_frame
) < 0.00001)
10184 return(TNG_SUCCESS
);
10187 frame_set
= &tng_data
->current_trajectory_frame_set
;
10189 /* If the current frame set is not finished write it to disk before
10190 changing time per frame. */
10191 if(tng_data
->time_per_frame
> 0 && frame_set
->n_unwritten_frames
> 0)
10193 frame_set
->n_frames
= frame_set
->n_unwritten_frames
;
10194 tng_frame_set_write(tng_data
, TNG_USE_HASH
);
10196 tng_data
->time_per_frame
= time
;
10198 return(TNG_SUCCESS
);
10201 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10202 (const tng_trajectory_t tng_data
,
10205 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10206 TNG_ASSERT(len
, "TNG library: len must not be a NULL pointer");
10208 *len
= tng_data
->input_file_len
;
10210 return(TNG_SUCCESS
);
10213 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10214 (const tng_trajectory_t tng_data
,
10217 tng_gen_block_t block
;
10218 tng_function_status stat
;
10219 int64_t file_pos
, last_file_pos
, first_frame
, n_frames
;
10221 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10222 TNG_ASSERT(tng_data
->input_file
, "TNG library: An input file must be open to find the next frame set");
10223 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
10225 file_pos
= ftello(tng_data
->input_file
);
10226 last_file_pos
= tng_data
->last_trajectory_frame_set_input_file_pos
;
10228 if(last_file_pos
<= 0)
10230 return(TNG_FAILURE
);
10233 tng_block_init(&block
);
10234 fseeko(tng_data
->input_file
,
10237 /* Read block headers first to see that a frame set block is found. */
10238 stat
= tng_block_header_read(tng_data
, block
);
10239 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10241 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n", last_file_pos
,
10242 __FILE__
, __LINE__
);
10243 tng_block_destroy(&block
);
10244 return(TNG_FAILURE
);
10246 tng_block_destroy(&block
);
10248 if(tng_file_input_numerical(tng_data
, &first_frame
,
10249 sizeof(first_frame
),
10250 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
10252 return(TNG_CRITICAL
);
10255 if(tng_file_input_numerical(tng_data
, &n_frames
,
10257 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
10259 return(TNG_CRITICAL
);
10262 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
10264 *n
= first_frame
+ n_frames
;
10266 return(TNG_SUCCESS
);
10269 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10270 (const tng_trajectory_t tng_data
,
10273 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10275 *precision
= tng_data
->compression_precision
;
10277 return(TNG_SUCCESS
);
10280 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10281 (const tng_trajectory_t tng_data
,
10282 const double precision
)
10284 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10286 tng_data
->compression_precision
= precision
;
10288 return(TNG_SUCCESS
);
10291 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10292 (const tng_trajectory_t tng_data
,
10295 tng_molecule_t mol
;
10299 tng_function_status stat
;
10300 int64_t diff
, n_mod
, n_impl
;
10302 TNG_ASSERT(n
>= 0, "TNG library: The requested number of particles must be >= 0");
10304 diff
= n
- tng_data
->n_particles
;
10306 stat
= tng_molecule_find(tng_data
, "TNG_IMPLICIT_MOL", -1, &mol
);
10307 if(stat
== TNG_SUCCESS
)
10309 if(tng_molecule_cnt_get(tng_data
, mol
, &n_impl
) != TNG_SUCCESS
)
10311 fprintf(stderr
, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10312 __FILE__
, __LINE__
);
10313 return(TNG_FAILURE
);
10315 diff
-= n_impl
* mol
->n_atoms
;
10320 if(stat
== TNG_SUCCESS
)
10322 stat
= tng_molecule_cnt_set(tng_data
, mol
, 0);
10325 return(TNG_SUCCESS
);
10329 fprintf(stderr
, "TNG library: Already more actual particles than requested implicit ");
10330 fprintf(stderr
, "particle count.\n");
10331 fprintf(stderr
, "TNG library: Cannot set implicit particle count. %s: %d\n",
10332 __FILE__
, __LINE__
);
10333 /* FIXME: Should we set the count of all other molecules to 0 and add
10334 * implicit molecules? */
10335 return(TNG_FAILURE
);
10337 if(stat
!= TNG_SUCCESS
)
10339 stat
= tng_molecule_add(tng_data
,
10340 "TNG_IMPLICIT_MOL",
10342 if(stat
!= TNG_SUCCESS
)
10346 stat
= tng_molecule_chain_add(tng_data
, mol
, "", &chain
);
10347 if(stat
!= TNG_SUCCESS
)
10351 stat
= tng_chain_residue_add(tng_data
, chain
, "", &res
);
10352 if(stat
!= TNG_SUCCESS
)
10356 stat
= tng_residue_atom_add(tng_data
, res
, "", "", &atom
);
10357 if(stat
!= TNG_SUCCESS
)
10364 if(mol
->n_atoms
> 1)
10366 n_mod
= diff
% mol
->n_atoms
;
10369 fprintf(stderr
, "TNG library: Number of atoms in implicit molecule ");
10370 fprintf(stderr
, "not compatible with requested implicit particle cnt.\n");
10371 fprintf(stderr
, "TNG library: Cannot set implicit particle count. %s: %d\n",
10372 __FILE__
, __LINE__
);
10373 return(TNG_FAILURE
);
10375 diff
/= mol
->n_atoms
;
10378 stat
= tng_molecule_cnt_set(tng_data
, mol
, diff
);
10383 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10384 (const tng_trajectory_t tng_data
,
10387 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10388 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
10390 if(tng_data
->var_num_atoms_flag
== TNG_CONSTANT_N_ATOMS
)
10392 *n
= tng_data
->n_particles
;
10396 *n
= tng_data
->current_trajectory_frame_set
.n_particles
;
10399 return(TNG_SUCCESS
);
10402 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10403 (const tng_trajectory_t tng_data
,
10406 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10407 TNG_ASSERT(variable
, "TNG library: variable must not be a NULL pointer");
10409 *variable
= tng_data
->var_num_atoms_flag
;
10411 return(TNG_SUCCESS
);
10414 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10415 (const tng_trajectory_t tng_data
,
10418 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10419 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
10421 *n
= tng_data
->n_molecules
;
10423 return(TNG_SUCCESS
);
10426 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10427 (const tng_trajectory_t tng_data
,
10430 int64_t *cnt_list
= 0, cnt
= 0, i
;
10432 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10433 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
10435 tng_molecule_cnt_list_get(tng_data
, &cnt_list
);
10439 return(TNG_FAILURE
);
10442 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
10444 cnt
+= cnt_list
[i
];
10449 return(TNG_SUCCESS
);
10452 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10453 (const tng_trajectory_t tng_data
,
10454 int64_t **mol_cnt_list
)
10456 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10458 if(tng_data
->var_num_atoms_flag
)
10460 *mol_cnt_list
= tng_data
->current_trajectory_frame_set
.
10465 *mol_cnt_list
= tng_data
->molecule_cnt_list
;
10467 if(*mol_cnt_list
== 0)
10469 return(TNG_FAILURE
);
10471 return(TNG_SUCCESS
);
10474 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10475 (const tng_trajectory_t tng_data
,
10478 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10479 TNG_ASSERT(exp
, "TNG library: exp must not be a NULL pointer");
10481 *exp
= tng_data
->distance_unit_exponential
;
10483 return(TNG_SUCCESS
);
10486 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10487 (const tng_trajectory_t tng_data
,
10490 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10492 tng_data
->distance_unit_exponential
= exp
;
10494 return(TNG_SUCCESS
);
10497 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10498 (const tng_trajectory_t tng_data
,
10501 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10502 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
10504 *n
= tng_data
->frame_set_n_frames
;
10506 return(TNG_SUCCESS
);
10509 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10510 (const tng_trajectory_t tng_data
,
10513 tng_trajectory_frame_set_t frame_set
;
10514 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10516 tng_data
->frame_set_n_frames
= n
;
10517 frame_set
= &tng_data
->current_trajectory_frame_set
;
10520 frame_set
->n_frames
= n
;
10523 return(TNG_SUCCESS
);
10526 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10527 (const tng_trajectory_t tng_data
,
10530 int64_t long_stride_length
, medium_stride_length
;
10531 int64_t file_pos
, orig_frame_set_file_pos
;
10532 tng_trajectory_frame_set_t frame_set
;
10533 struct tng_trajectory_frame_set orig_frame_set
;
10534 tng_gen_block_t block
;
10535 tng_function_status stat
;
10538 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10539 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
10541 orig_frame_set
= tng_data
->current_trajectory_frame_set
;
10543 frame_set
= &tng_data
->current_trajectory_frame_set
;
10545 orig_frame_set_file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
10546 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
10550 *n
= tng_data
->n_trajectory_frame_sets
= cnt
;
10551 return(TNG_SUCCESS
);
10554 tng_block_init(&block
);
10555 fseeko(tng_data
->input_file
,
10558 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
10559 /* Read block headers first to see what block is found. */
10560 stat
= tng_block_header_read(tng_data
, block
);
10561 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10563 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n", file_pos
,
10564 __FILE__
, __LINE__
);
10565 tng_block_destroy(&block
);
10566 return(TNG_CRITICAL
);
10569 if(tng_block_read_next(tng_data
, block
,
10570 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10572 tng_block_destroy(&block
);
10573 return(TNG_CRITICAL
);
10578 long_stride_length
= tng_data
->long_stride_length
;
10579 medium_stride_length
= tng_data
->medium_stride_length
;
10581 /* Take long steps forward until a long step forward would be too long or
10582 * the last frame set is found */
10583 file_pos
= frame_set
->long_stride_next_frame_set_file_pos
;
10584 while(file_pos
> 0)
10588 cnt
+= long_stride_length
;
10589 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
10590 /* Read block headers first to see what block is found. */
10591 stat
= tng_block_header_read(tng_data
, block
);
10592 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10594 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10595 file_pos
, __FILE__
, __LINE__
);
10596 tng_block_destroy(&block
);
10597 return(TNG_CRITICAL
);
10600 if(tng_block_read_next(tng_data
, block
,
10601 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10603 tng_block_destroy(&block
);
10604 return(TNG_CRITICAL
);
10607 file_pos
= frame_set
->long_stride_next_frame_set_file_pos
;
10610 /* Take medium steps forward until a medium step forward would be too long
10611 * or the last frame set is found */
10612 file_pos
= frame_set
->medium_stride_next_frame_set_file_pos
;
10613 while(file_pos
> 0)
10617 cnt
+= medium_stride_length
;
10618 fseeko(tng_data
->input_file
,
10621 /* Read block headers first to see what block is found. */
10622 stat
= tng_block_header_read(tng_data
, block
);
10623 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10625 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10626 file_pos
, __FILE__
, __LINE__
);
10627 tng_block_destroy(&block
);
10628 return(TNG_CRITICAL
);
10631 if(tng_block_read_next(tng_data
, block
,
10632 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10634 tng_block_destroy(&block
);
10635 return(TNG_CRITICAL
);
10638 file_pos
= frame_set
->medium_stride_next_frame_set_file_pos
;
10641 /* Take one step forward until the last frame set is found */
10642 file_pos
= frame_set
->next_frame_set_file_pos
;
10643 while(file_pos
> 0)
10648 fseeko(tng_data
->input_file
,
10651 /* Read block headers first to see what block is found. */
10652 stat
= tng_block_header_read(tng_data
, block
);
10653 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10655 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10656 file_pos
, __FILE__
, __LINE__
);
10657 tng_block_destroy(&block
);
10658 return(TNG_CRITICAL
);
10661 if(tng_block_read_next(tng_data
, block
,
10662 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10664 tng_block_destroy(&block
);
10665 return(TNG_CRITICAL
);
10668 file_pos
= frame_set
->next_frame_set_file_pos
;
10671 tng_block_destroy(&block
);
10673 *n
= tng_data
->n_trajectory_frame_sets
= cnt
;
10675 *frame_set
= orig_frame_set
;
10676 /* The mapping block in the original frame set has been freed when reading
10677 * other frame sets. */
10678 frame_set
->mappings
= 0;
10679 frame_set
->n_mapping_blocks
= 0;
10681 fseeko(tng_data
->input_file
,
10682 tng_data
->first_trajectory_frame_set_input_file_pos
,
10685 tng_data
->current_trajectory_frame_set_input_file_pos
= orig_frame_set_file_pos
;
10687 return(TNG_SUCCESS
);
10690 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10691 (const tng_trajectory_t tng_data
,
10692 tng_trajectory_frame_set_t
*frame_set_p
)
10694 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10696 *frame_set_p
= &tng_data
->current_trajectory_frame_set
;
10698 return(TNG_SUCCESS
);
10701 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
10702 (const tng_trajectory_t tng_data
,
10705 int64_t long_stride_length
, medium_stride_length
;
10706 int64_t file_pos
, curr_nr
= 0, n_frame_sets
;
10707 tng_trajectory_frame_set_t frame_set
;
10708 tng_gen_block_t block
;
10709 tng_function_status stat
;
10711 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10712 TNG_ASSERT(nr
>= 0, "The frame set number (nr) must be >= 0");
10714 frame_set
= &tng_data
->current_trajectory_frame_set
;
10716 stat
= tng_num_frame_sets_get(tng_data
, &n_frame_sets
);
10718 if(stat
!= TNG_SUCCESS
)
10723 if(nr
>= n_frame_sets
)
10725 return(TNG_FAILURE
);
10728 long_stride_length
= tng_data
->long_stride_length
;
10729 medium_stride_length
= tng_data
->medium_stride_length
;
10731 /* FIXME: The frame set number of the current frame set is not stored */
10733 if(nr
< n_frame_sets
- 1 - nr
)
10735 /* Start from the beginning */
10736 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
10740 /* Start from the end */
10741 file_pos
= tng_data
->last_trajectory_frame_set_input_file_pos
;
10742 curr_nr
= n_frame_sets
- 1;
10746 return(TNG_FAILURE
);
10749 tng_block_init(&block
);
10750 fseeko(tng_data
->input_file
,
10753 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
10754 /* Read block headers first to see what block is found. */
10755 stat
= tng_block_header_read(tng_data
, block
);
10756 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10758 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n", file_pos
,
10759 __FILE__
, __LINE__
);
10760 tng_block_destroy(&block
);
10761 return(TNG_CRITICAL
);
10764 if(tng_block_read_next(tng_data
, block
,
10765 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10767 tng_block_destroy(&block
);
10768 return(TNG_CRITICAL
);
10773 tng_block_destroy(&block
);
10774 return(TNG_SUCCESS
);
10777 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
10779 /* Take long steps forward until a long step forward would be too long or
10780 * the right frame set is found */
10781 while(file_pos
> 0 && curr_nr
+ long_stride_length
<= nr
)
10783 file_pos
= frame_set
->long_stride_next_frame_set_file_pos
;
10786 curr_nr
+= long_stride_length
;
10787 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
10788 /* Read block headers first to see what block is found. */
10789 stat
= tng_block_header_read(tng_data
, block
);
10790 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10792 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10793 file_pos
, __FILE__
, __LINE__
);
10794 tng_block_destroy(&block
);
10795 return(TNG_CRITICAL
);
10798 if(tng_block_read_next(tng_data
, block
,
10799 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10801 tng_block_destroy(&block
);
10802 return(TNG_CRITICAL
);
10806 tng_block_destroy(&block
);
10807 return(TNG_SUCCESS
);
10812 /* Take medium steps forward until a medium step forward would be too long
10813 * or the right frame set is found */
10814 while(file_pos
> 0 && curr_nr
+ medium_stride_length
<= nr
)
10816 file_pos
= frame_set
->medium_stride_next_frame_set_file_pos
;
10819 curr_nr
+= medium_stride_length
;
10820 fseeko(tng_data
->input_file
,
10823 /* Read block headers first to see what block is found. */
10824 stat
= tng_block_header_read(tng_data
, block
);
10825 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10827 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10828 file_pos
, __FILE__
, __LINE__
);
10829 tng_block_destroy(&block
);
10830 return(TNG_CRITICAL
);
10833 if(tng_block_read_next(tng_data
, block
,
10834 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10836 tng_block_destroy(&block
);
10837 return(TNG_CRITICAL
);
10841 tng_block_destroy(&block
);
10842 return(TNG_SUCCESS
);
10847 /* Take one step forward until the right frame set is found */
10848 while(file_pos
> 0 && curr_nr
< nr
)
10850 file_pos
= frame_set
->next_frame_set_file_pos
;
10855 fseeko(tng_data
->input_file
,
10858 /* Read block headers first to see what block is found. */
10859 stat
= tng_block_header_read(tng_data
, block
);
10860 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10862 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10863 file_pos
, __FILE__
, __LINE__
);
10864 tng_block_destroy(&block
);
10865 return(TNG_CRITICAL
);
10868 if(tng_block_read_next(tng_data
, block
,
10869 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10871 tng_block_destroy(&block
);
10872 return(TNG_CRITICAL
);
10876 tng_block_destroy(&block
);
10877 return(TNG_SUCCESS
);
10882 /* Take long steps backward until a long step backward would be too long
10883 * or the right frame set is found */
10884 while(file_pos
> 0 && curr_nr
- long_stride_length
>= nr
)
10886 file_pos
= frame_set
->long_stride_prev_frame_set_file_pos
;
10889 curr_nr
-= long_stride_length
;
10890 fseeko(tng_data
->input_file
,
10893 /* Read block headers first to see what block is found. */
10894 stat
= tng_block_header_read(tng_data
, block
);
10895 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10897 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10898 file_pos
, __FILE__
, __LINE__
);
10899 tng_block_destroy(&block
);
10900 return(TNG_CRITICAL
);
10903 if(tng_block_read_next(tng_data
, block
,
10904 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10906 tng_block_destroy(&block
);
10907 return(TNG_CRITICAL
);
10911 tng_block_destroy(&block
);
10912 return(TNG_SUCCESS
);
10917 /* Take medium steps backward until a medium step backward would be too long
10918 * or the right frame set is found */
10919 while(file_pos
> 0 && curr_nr
- medium_stride_length
>= nr
)
10921 file_pos
= frame_set
->medium_stride_prev_frame_set_file_pos
;
10924 curr_nr
-= medium_stride_length
;
10925 fseeko(tng_data
->input_file
,
10928 /* Read block headers first to see what block is found. */
10929 stat
= tng_block_header_read(tng_data
, block
);
10930 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10932 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10933 file_pos
, __FILE__
, __LINE__
);
10934 tng_block_destroy(&block
);
10935 return(TNG_CRITICAL
);
10938 if(tng_block_read_next(tng_data
, block
,
10939 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10941 tng_block_destroy(&block
);
10942 return(TNG_CRITICAL
);
10946 tng_block_destroy(&block
);
10947 return(TNG_SUCCESS
);
10952 /* Take one step backward until the right frame set is found */
10953 while(file_pos
> 0 && curr_nr
> nr
)
10955 file_pos
= frame_set
->prev_frame_set_file_pos
;
10959 fseeko(tng_data
->input_file
,
10962 /* Read block headers first to see what block is found. */
10963 stat
= tng_block_header_read(tng_data
, block
);
10964 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
10966 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
10967 file_pos
, __FILE__
, __LINE__
);
10968 tng_block_destroy(&block
);
10969 return(TNG_CRITICAL
);
10972 if(tng_block_read_next(tng_data
, block
,
10973 TNG_SKIP_HASH
) != TNG_SUCCESS
)
10975 tng_block_destroy(&block
);
10976 return(TNG_CRITICAL
);
10980 tng_block_destroy(&block
);
10981 return(TNG_SUCCESS
);
10986 /* If for some reason the current frame set is not yet found,
10987 * take one step forward until the right frame set is found */
10988 while(file_pos
> 0 && curr_nr
< nr
)
10990 file_pos
= frame_set
->next_frame_set_file_pos
;
10994 fseeko(tng_data
->input_file
,
10997 /* Read block headers first to see what block is found. */
10998 stat
= tng_block_header_read(tng_data
, block
);
10999 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11001 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11002 file_pos
, __FILE__
, __LINE__
);
11003 tng_block_destroy(&block
);
11004 return(TNG_CRITICAL
);
11007 if(tng_block_read_next(tng_data
, block
,
11008 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11010 tng_block_destroy(&block
);
11011 return(TNG_CRITICAL
);
11015 tng_block_destroy(&block
);
11016 return(TNG_SUCCESS
);
11021 tng_block_destroy(&block
);
11022 return(TNG_FAILURE
);
11025 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11026 (const tng_trajectory_t tng_data
,
11027 const int64_t frame
)
11029 int64_t first_frame
, last_frame
, n_frames_per_frame_set
;
11030 int64_t long_stride_length
, medium_stride_length
;
11031 int64_t file_pos
, temp_frame
, n_frames
;
11032 tng_trajectory_frame_set_t frame_set
;
11033 tng_gen_block_t block
;
11034 tng_function_status stat
;
11036 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11037 TNG_ASSERT(frame
>= 0, "TNG library: frame must be >= 0.");
11039 frame_set
= &tng_data
->current_trajectory_frame_set
;
11041 tng_block_init(&block
);
11043 if(tng_data
->current_trajectory_frame_set_input_file_pos
< 0)
11045 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
11046 fseeko(tng_data
->input_file
,
11049 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
11050 /* Read block headers first to see what block is found. */
11051 stat
= tng_block_header_read(tng_data
, block
);
11052 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11054 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11055 file_pos
, __FILE__
, __LINE__
);
11056 tng_block_destroy(&block
);
11057 return(TNG_CRITICAL
);
11060 if(tng_block_read_next(tng_data
, block
,
11061 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11063 tng_block_destroy(&block
);
11064 return(TNG_CRITICAL
);
11068 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11069 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11070 /* Is this the right frame set? */
11071 if(first_frame
<= frame
&& frame
<= last_frame
)
11073 tng_block_destroy(&block
);
11074 return(TNG_SUCCESS
);
11077 n_frames_per_frame_set
= tng_data
->frame_set_n_frames
;
11078 long_stride_length
= tng_data
->long_stride_length
;
11079 medium_stride_length
= tng_data
->medium_stride_length
;
11081 if(tng_first_frame_nr_of_next_frame_set_get(tng_data
, &temp_frame
) ==
11084 if(temp_frame
- first_frame
> n_frames_per_frame_set
)
11086 n_frames_per_frame_set
= temp_frame
- first_frame
;
11090 tng_num_frames_get(tng_data
, &n_frames
);
11092 if(frame
>= n_frames
)
11094 tng_block_destroy(&block
);
11095 return(TNG_FAILURE
);
11098 if(first_frame
- frame
>= frame
||
11099 frame
- last_frame
>
11100 tng_data
->n_trajectory_frame_sets
* n_frames_per_frame_set
- frame
)
11102 /* Start from the beginning */
11103 if(first_frame
- frame
>= frame
)
11105 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
11109 tng_block_destroy(&block
);
11110 return(TNG_FAILURE
);
11113 /* Start from the end */
11114 else if(frame
- first_frame
> (n_frames
- 1) - frame
)
11116 file_pos
= tng_data
->last_trajectory_frame_set_input_file_pos
;
11118 /* If the last frame set position is not set start from the current
11119 * frame set, since it will be closer than the first frame set. */
11121 /* Start from current */
11124 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
11129 fseeko(tng_data
->input_file
,
11132 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
11133 /* Read block headers first to see what block is found. */
11134 stat
= tng_block_header_read(tng_data
, block
);
11135 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11137 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11138 file_pos
, __FILE__
, __LINE__
);
11139 tng_block_destroy(&block
);
11140 return(TNG_CRITICAL
);
11143 if(tng_block_read_next(tng_data
, block
,
11144 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11146 tng_block_destroy(&block
);
11147 return(TNG_CRITICAL
);
11152 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11153 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11155 if(frame
>= first_frame
&& frame
<= last_frame
)
11157 tng_block_destroy(&block
);
11158 return(TNG_SUCCESS
);
11161 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
11163 /* Take long steps forward until a long step forward would be too long or
11164 * the right frame set is found */
11165 while(file_pos
> 0 && first_frame
+ long_stride_length
*
11166 n_frames_per_frame_set
<= frame
)
11168 file_pos
= frame_set
->long_stride_next_frame_set_file_pos
;
11171 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
11172 /* Read block headers first to see what block is found. */
11173 stat
= tng_block_header_read(tng_data
, block
);
11174 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11176 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11177 file_pos
, __FILE__
, __LINE__
);
11178 tng_block_destroy(&block
);
11179 return(TNG_CRITICAL
);
11182 if(tng_block_read_next(tng_data
, block
,
11183 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11185 tng_block_destroy(&block
);
11186 return(TNG_CRITICAL
);
11189 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11190 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11191 if(frame
>= first_frame
&& frame
<= last_frame
)
11193 tng_block_destroy(&block
);
11194 return(TNG_SUCCESS
);
11198 /* Take medium steps forward until a medium step forward would be too long
11199 * or the right frame set is found */
11200 while(file_pos
> 0 && first_frame
+ medium_stride_length
*
11201 n_frames_per_frame_set
<= frame
)
11203 file_pos
= frame_set
->medium_stride_next_frame_set_file_pos
;
11206 fseeko(tng_data
->input_file
,
11209 /* Read block headers first to see what block is found. */
11210 stat
= tng_block_header_read(tng_data
, block
);
11211 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11213 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11214 file_pos
, __FILE__
, __LINE__
);
11215 tng_block_destroy(&block
);
11216 return(TNG_CRITICAL
);
11219 if(tng_block_read_next(tng_data
, block
,
11220 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11222 tng_block_destroy(&block
);
11223 return(TNG_CRITICAL
);
11226 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11227 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11228 if(frame
>= first_frame
&& frame
<= last_frame
)
11230 tng_block_destroy(&block
);
11231 return(TNG_SUCCESS
);
11235 /* Take one step forward until the right frame set is found */
11236 while(file_pos
> 0 && first_frame
< frame
&& last_frame
< frame
)
11238 file_pos
= frame_set
->next_frame_set_file_pos
;
11241 fseeko(tng_data
->input_file
,
11244 /* Read block headers first to see what block is found. */
11245 stat
= tng_block_header_read(tng_data
, block
);
11246 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11248 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11249 file_pos
, __FILE__
, __LINE__
);
11250 tng_block_destroy(&block
);
11251 return(TNG_CRITICAL
);
11254 if(tng_block_read_next(tng_data
, block
,
11255 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11257 tng_block_destroy(&block
);
11258 return(TNG_CRITICAL
);
11261 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11262 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11263 if(frame
>= first_frame
&& frame
<= last_frame
)
11265 tng_block_destroy(&block
);
11266 return(TNG_SUCCESS
);
11270 /* Take long steps backward until a long step backward would be too long
11271 * or the right frame set is found */
11272 while(file_pos
> 0 && first_frame
- long_stride_length
*
11273 n_frames_per_frame_set
>= frame
)
11275 file_pos
= frame_set
->long_stride_prev_frame_set_file_pos
;
11278 fseeko(tng_data
->input_file
,
11281 /* Read block headers first to see what block is found. */
11282 stat
= tng_block_header_read(tng_data
, block
);
11283 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11285 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11286 file_pos
, __FILE__
, __LINE__
);
11287 tng_block_destroy(&block
);
11288 return(TNG_CRITICAL
);
11291 if(tng_block_read_next(tng_data
, block
,
11292 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11294 tng_block_destroy(&block
);
11295 return(TNG_CRITICAL
);
11298 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11299 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11300 if(frame
>= first_frame
&& frame
<= last_frame
)
11302 tng_block_destroy(&block
);
11303 return(TNG_SUCCESS
);
11307 /* Take medium steps backward until a medium step backward would be too long
11308 * or the right frame set is found */
11309 while(file_pos
> 0 && first_frame
- medium_stride_length
*
11310 n_frames_per_frame_set
>= frame
)
11312 file_pos
= frame_set
->medium_stride_prev_frame_set_file_pos
;
11315 fseeko(tng_data
->input_file
,
11318 /* Read block headers first to see what block is found. */
11319 stat
= tng_block_header_read(tng_data
, block
);
11320 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11322 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11323 file_pos
, __FILE__
, __LINE__
);
11324 tng_block_destroy(&block
);
11325 return(TNG_CRITICAL
);
11328 if(tng_block_read_next(tng_data
, block
,
11329 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11331 tng_block_destroy(&block
);
11332 return(TNG_CRITICAL
);
11335 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11336 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11337 if(frame
>= first_frame
&& frame
<= last_frame
)
11339 tng_block_destroy(&block
);
11340 return(TNG_SUCCESS
);
11344 /* Take one step backward until the right frame set is found */
11345 while(file_pos
> 0 && first_frame
> frame
&& last_frame
> frame
)
11347 file_pos
= frame_set
->prev_frame_set_file_pos
;
11350 fseeko(tng_data
->input_file
,
11353 /* Read block headers first to see what block is found. */
11354 stat
= tng_block_header_read(tng_data
, block
);
11355 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11357 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11358 file_pos
, __FILE__
, __LINE__
);
11359 tng_block_destroy(&block
);
11360 return(TNG_CRITICAL
);
11363 if(tng_block_read_next(tng_data
, block
,
11364 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11366 tng_block_destroy(&block
);
11367 return(TNG_CRITICAL
);
11370 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11371 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11372 if(frame
>= first_frame
&& frame
<= last_frame
)
11374 tng_block_destroy(&block
);
11375 return(TNG_SUCCESS
);
11379 /* If for some reason the current frame set is not yet found,
11380 * take one step forward until the right frame set is found */
11381 while(file_pos
> 0 && first_frame
< frame
&& last_frame
< frame
)
11383 file_pos
= frame_set
->next_frame_set_file_pos
;
11386 fseeko(tng_data
->input_file
,
11389 /* Read block headers first to see what block is found. */
11390 stat
= tng_block_header_read(tng_data
, block
);
11391 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11393 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11394 file_pos
, __FILE__
, __LINE__
);
11395 tng_block_destroy(&block
);
11396 return(TNG_CRITICAL
);
11399 if(tng_block_read_next(tng_data
, block
,
11400 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11402 tng_block_destroy(&block
);
11403 return(TNG_CRITICAL
);
11406 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
11407 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
11408 if(frame
>= first_frame
&& frame
<= last_frame
)
11410 tng_block_destroy(&block
);
11411 return(TNG_SUCCESS
);
11415 tng_block_destroy(&block
);
11416 return(TNG_FAILURE
);
11419 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11420 (const tng_trajectory_t tng_data
,
11421 const tng_trajectory_frame_set_t frame_set
,
11426 TNG_ASSERT(frame_set
, "TNG library: frame_set not initialised before accessing data.");
11427 TNG_ASSERT(pos
, "TNG library: pos must not be a NULL pointer");
11429 *pos
= frame_set
->next_frame_set_file_pos
;
11431 return(TNG_SUCCESS
);
11434 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11435 (const tng_trajectory_t tng_data
,
11436 const tng_trajectory_frame_set_t frame_set
,
11441 TNG_ASSERT(frame_set
, "TNG library: frame_set not initialised before accessing data.");
11442 TNG_ASSERT(pos
, "TNG library: pos must not be a NULL pointer");
11444 *pos
= frame_set
->prev_frame_set_file_pos
;
11446 return(TNG_SUCCESS
);
11449 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11450 (const tng_trajectory_t tng_data
,
11451 const tng_trajectory_frame_set_t frame_set
,
11452 int64_t *first_frame
,
11453 int64_t *last_frame
)
11457 TNG_ASSERT(first_frame
, "TNG library: first_frame must not be a NULL pointer");
11458 TNG_ASSERT(last_frame
, "TNG library: last_frame must not be a NULL pointer");
11459 TNG_ASSERT(frame_set
, "TNG library: frame_set must not be a NULL pointer");
11461 *first_frame
= frame_set
->first_frame
;
11462 *last_frame
= *first_frame
+ frame_set
->n_frames
- 1;
11464 return(TNG_SUCCESS
);
11468 * @brief Translate from the particle numbering used in a frame set to the real
11469 * particle numbering - used in the molecule description.
11470 * @param frame_set is the frame_set containing the mappings to use.
11471 * @param local is the index number of the atom in this frame set
11472 * @param real is set to the index of the atom in the molecular system.
11473 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11476 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11477 (const tng_trajectory_frame_set_t frame_set
,
11478 const int64_t local
,
11481 int64_t i
, n_blocks
= frame_set
->n_mapping_blocks
, first
;
11482 tng_particle_mapping_t mapping
;
11486 return(TNG_SUCCESS
);
11488 for(i
= 0; i
< n_blocks
; i
++)
11490 mapping
= &frame_set
->mappings
[i
];
11491 first
= mapping
->num_first_particle
;
11492 if(local
< first
||
11493 local
>= first
+ mapping
->n_particles
)
11497 *real
= mapping
->real_particle_numbers
[local
-first
];
11498 return(TNG_SUCCESS
);
11501 return(TNG_FAILURE
);
11505 * @brief Translate from the real particle numbering to the particle numbering
11506 * used in a frame set.
11507 * @param frame_set is the frame_set containing the mappings to use.
11508 * @param real is the index number of the atom in the molecular system.
11509 * @param local is set to the index of the atom in this frame set.
11510 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11513 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11514 (const tng_trajectory_frame_set_t frame_set,
11515 const int64_t real,
11518 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11519 tng_particle_mapping_t mapping;
11523 return(TNG_SUCCESS);
11525 for(i = 0; i < n_blocks; i++)
11527 mapping = &frame_set->mappings[i];
11528 for(j = mapping->n_particles; j--;)
11530 if(mapping->real_particle_numbers[j] == real)
11533 return(TNG_SUCCESS);
11537 return(TNG_FAILURE);
11541 static tng_function_status tng_file_headers_len_get
11542 (const tng_trajectory_t tng_data
,
11546 tng_gen_block_t block
;
11548 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11550 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
11552 return(TNG_CRITICAL
);
11557 orig_pos
= ftello(tng_data
->input_file
);
11559 fseeko(tng_data
->input_file
, 0, SEEK_SET
);
11561 tng_block_init(&block
);
11562 /* Read through the headers of non-trajectory blocks (they come before the
11563 * trajectory blocks in the file) */
11564 while (*len
< tng_data
->input_file_len
&&
11565 tng_block_header_read(tng_data
, block
) != TNG_CRITICAL
&&
11567 block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11569 *len
+= block
->header_contents_size
+ block
->block_contents_size
;
11570 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
11573 fseeko(tng_data
->input_file
, orig_pos
, SEEK_SET
);
11575 tng_block_destroy(&block
);
11577 return(TNG_SUCCESS
);
11580 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11581 (const tng_trajectory_t tng_data
,
11582 const char hash_mode
)
11584 int64_t prev_pos
= 0;
11585 tng_gen_block_t block
;
11587 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11589 tng_data
->n_trajectory_frame_sets
= 0;
11591 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
11593 return(TNG_CRITICAL
);
11596 fseeko(tng_data
->input_file
, 0, SEEK_SET
);
11598 tng_block_init(&block
);
11599 /* Non trajectory blocks (they come before the trajectory
11600 * blocks in the file) */
11601 while (prev_pos
< tng_data
->input_file_len
&&
11602 tng_block_header_read(tng_data
, block
) != TNG_CRITICAL
&&
11604 block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11606 tng_block_read_next(tng_data
, block
, hash_mode
);
11607 prev_pos
= ftello(tng_data
->input_file
);
11610 /* Go back if a trajectory block was encountered */
11611 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
11613 fseeko(tng_data
->input_file
, prev_pos
, SEEK_SET
);
11616 tng_block_destroy(&block
);
11618 return(TNG_SUCCESS
);
11621 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11622 (const tng_trajectory_t tng_data
,
11623 const char hash_mode
)
11626 int64_t len
, orig_len
, tot_len
= 0, data_start_pos
, temp_pos
= -1;
11627 tng_function_status stat
;
11628 tng_gen_block_t block
;
11630 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11632 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
11634 return(TNG_CRITICAL
);
11637 if(tng_data
->n_trajectory_frame_sets
> 0)
11639 stat
= tng_file_headers_len_get(tng_data
, &orig_len
);
11640 if(stat
!= TNG_SUCCESS
)
11645 tng_block_init(&block
);
11646 block
->name
= (char *)malloc(TNG_MAX_STR_LEN
);
11649 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
11650 __FILE__
, __LINE__
);
11651 tng_block_destroy(&block
);
11652 return(TNG_CRITICAL
);
11654 strcpy(block
->name
, "GENERAL INFO");
11655 tng_block_header_len_calculate(tng_data
, block
, &len
);
11657 tng_general_info_block_len_calculate(tng_data
, &len
);
11659 strcpy(block
->name
, "MOLECULES");
11660 tng_block_header_len_calculate(tng_data
, block
, &len
);
11662 tng_molecules_block_len_calculate(tng_data
, &len
);
11665 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
11667 strcpy(block
->name
, tng_data
->non_tr_data
[i
].block_name
);
11668 tng_block_header_len_calculate(tng_data
, block
, &len
);
11670 tng_data_block_len_calculate(tng_data
,
11671 (tng_data_t
)&tng_data
->non_tr_data
[i
],
11672 TNG_FALSE
, 1, 1, 1, 0, 1,
11677 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
11679 strcpy(block
->name
, tng_data
->non_tr_particle_data
[i
].block_name
);
11680 tng_block_header_len_calculate(tng_data
, block
, &len
);
11682 tng_data_block_len_calculate(tng_data
,
11683 &tng_data
->non_tr_particle_data
[i
],
11684 TNG_TRUE
, 1, 1, 1, 0,
11685 tng_data
->n_particles
,
11690 tng_block_destroy(&block
);
11692 if(tot_len
> orig_len
)
11694 tng_migrate_data_in_file(tng_data
, orig_len
+1, tot_len
- orig_len
, hash_mode
);
11695 tng_data
->last_trajectory_frame_set_input_file_pos
= tng_data
->last_trajectory_frame_set_output_file_pos
;
11698 stat
= tng_reread_frame_set_at_file_pos(tng_data
, tng_data
->last_trajectory_frame_set_input_file_pos
);
11699 if(stat
== TNG_CRITICAL
)
11701 fprintf(stderr
, "TNG library: Cannot read frame set. %s: %d\n",
11702 __FILE__
, __LINE__
);
11703 return(TNG_CRITICAL
);
11706 /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
11707 * must temporarily be reset */
11708 temp_pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
11709 tng_data
->current_trajectory_frame_set_output_file_pos
= -1;
11712 if(tng_general_info_block_write(tng_data
, hash_mode
)
11715 fprintf(stderr
, "TNG library: Error writing general info block of file %s. %s: %d\n",
11716 tng_data
->input_file_path
, __FILE__
, __LINE__
);
11717 return(TNG_CRITICAL
);
11720 if(tng_molecules_block_write(tng_data
, hash_mode
)
11723 fprintf(stderr
, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11724 tng_data
->input_file_path
, __FILE__
, __LINE__
);
11725 return(TNG_CRITICAL
);
11728 /* FIXME: Currently writing non-trajectory data blocks here.
11729 * Should perhaps be moved. */
11730 tng_block_init(&block
);
11731 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
11733 block
->id
= tng_data
->non_tr_data
[i
].block_id
;
11734 tng_data_block_write(tng_data
, block
,
11735 i
, TNG_FALSE
, 0, hash_mode
);
11738 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
11740 block
->id
= tng_data
->non_tr_particle_data
[i
].block_id
;
11741 tng_data_block_write(tng_data
, block
,
11742 i
, TNG_TRUE
, 0, hash_mode
);
11745 tng_block_destroy(&block
);
11747 /* Continue writing at the end of the file. */
11748 fseeko(tng_data
->output_file
, 0, SEEK_END
);
11751 tng_data
->current_trajectory_frame_set_output_file_pos
= temp_pos
;
11754 return(TNG_SUCCESS
);
11757 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
11758 (const tng_trajectory_t tng_data
,
11759 const tng_gen_block_t block
,
11760 const char hash_mode
)
11762 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11763 TNG_ASSERT(block
, "TNG library: block must be initialised and must not be a NULL pointer.");
11767 case TNG_TRAJECTORY_FRAME_SET
:
11768 return(tng_frame_set_block_read(tng_data
, block
, hash_mode
));
11769 case TNG_PARTICLE_MAPPING
:
11770 return(tng_trajectory_mapping_block_read(tng_data
, block
, hash_mode
));
11771 case TNG_GENERAL_INFO
:
11772 return(tng_general_info_block_read(tng_data
, block
, hash_mode
));
11773 case TNG_MOLECULES
:
11774 return(tng_molecules_block_read(tng_data
, block
, hash_mode
));
11776 if(block
->id
>= TNG_TRAJ_BOX_SHAPE
)
11778 return(tng_data_block_contents_read(tng_data
, block
, hash_mode
));
11782 /* Skip to the next block */
11783 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
11784 return(TNG_FAILURE
);
11789 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11790 (const tng_trajectory_t tng_data
,
11791 const char hash_mode
)
11794 tng_gen_block_t block
;
11795 tng_function_status stat
;
11797 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11799 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
11801 return(TNG_CRITICAL
);
11804 file_pos
= ftello(tng_data
->input_file
);
11806 tng_block_init(&block
);
11808 /* Read block headers first to see what block is found. */
11809 stat
= tng_block_header_read(tng_data
, block
);
11810 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
||
11813 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11814 file_pos
, __FILE__
, __LINE__
);
11815 tng_block_destroy(&block
);
11816 return(TNG_CRITICAL
);
11819 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
11821 if(tng_block_read_next(tng_data
, block
,
11822 hash_mode
) == TNG_SUCCESS
)
11824 tng_data
->n_trajectory_frame_sets
++;
11825 file_pos
= ftello(tng_data
->input_file
);
11826 /* Read all blocks until next frame set block */
11827 stat
= tng_block_header_read(tng_data
, block
);
11828 while(file_pos
< tng_data
->input_file_len
&&
11829 stat
!= TNG_CRITICAL
&&
11830 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
11833 stat
= tng_block_read_next(tng_data
, block
,
11835 if(stat
!= TNG_CRITICAL
)
11837 file_pos
= ftello(tng_data
->input_file
);
11838 if(file_pos
< tng_data
->input_file_len
)
11840 stat
= tng_block_header_read(tng_data
, block
);
11844 if(stat
== TNG_CRITICAL
)
11846 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11847 file_pos
, __FILE__
, __LINE__
);
11848 tng_block_destroy(&block
);
11852 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
11854 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
11858 tng_block_destroy(&block
);
11860 return(TNG_SUCCESS
);
11864 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
11865 (const tng_trajectory_t tng_data
,
11866 const char hash_mode
,
11867 const int64_t block_id
)
11870 tng_gen_block_t block
;
11871 tng_function_status stat
;
11872 int found_flag
= 1;
11874 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11876 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
11878 return(TNG_CRITICAL
);
11881 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
11885 /* No current frame set. This means that the first frame set must be
11888 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
11893 fseeko(tng_data
->input_file
,
11899 return(TNG_FAILURE
);
11902 tng_block_init(&block
);
11904 /* Read block headers first to see what block is found. */
11905 stat
= tng_block_header_read(tng_data
, block
);
11906 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11908 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11909 file_pos
, __FILE__
, __LINE__
);
11910 tng_block_destroy(&block
);
11911 return(TNG_CRITICAL
);
11913 /* If the current frame set had already been read skip its block contents */
11916 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
11918 /* Otherwise read the frame set block */
11921 stat
= tng_block_read_next(tng_data
, block
,
11923 if(stat
!= TNG_SUCCESS
)
11925 fprintf(stderr
, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__
, __LINE__
);
11926 tng_block_destroy(&block
);
11930 file_pos
= ftello(tng_data
->input_file
);
11934 /* Read only blocks of the requested ID
11935 * until next frame set block */
11936 stat
= tng_block_header_read(tng_data
, block
);
11937 while(file_pos
< tng_data
->input_file_len
&&
11938 stat
!= TNG_CRITICAL
&&
11939 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
11942 if(block
->id
== block_id
)
11944 stat
= tng_block_read_next(tng_data
, block
,
11946 if(stat
!= TNG_CRITICAL
)
11948 file_pos
= ftello(tng_data
->input_file
);
11950 if(file_pos
< tng_data
->input_file_len
)
11952 stat
= tng_block_header_read(tng_data
, block
);
11958 file_pos
+= block
->block_contents_size
+ block
->header_contents_size
;
11959 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
11960 if(file_pos
< tng_data
->input_file_len
)
11962 stat
= tng_block_header_read(tng_data
, block
);
11966 if(stat
== TNG_CRITICAL
)
11968 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
11969 file_pos
, __FILE__
, __LINE__
);
11970 tng_block_destroy(&block
);
11974 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
11976 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
11979 tng_block_destroy(&block
);
11983 return(TNG_SUCCESS
);
11987 return(TNG_FAILURE
);
11991 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
11992 (const tng_trajectory_t tng_data
,
11993 const char hash_mode
)
11997 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11999 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12001 return(TNG_CRITICAL
);
12004 file_pos
= tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
;
12006 if(file_pos
< 0 && tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
12008 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
12013 fseeko(tng_data
->input_file
,
12019 return(TNG_FAILURE
);
12022 return(tng_frame_set_read(tng_data
, hash_mode
));
12025 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12026 (const tng_trajectory_t tng_data
,
12027 const char hash_mode
,
12028 const int64_t block_id
)
12031 tng_gen_block_t block
;
12032 tng_function_status stat
;
12034 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12036 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12038 return(TNG_CRITICAL
);
12041 file_pos
= tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
;
12043 if(file_pos
< 0 && tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
12045 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
12050 fseeko(tng_data
->input_file
,
12056 return(TNG_FAILURE
);
12059 tng_block_init(&block
);
12061 /* Read block headers first to see what block is found. */
12062 stat
= tng_block_header_read(tng_data
, block
);
12063 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12065 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
12066 file_pos
, __FILE__
, __LINE__
);
12067 tng_block_destroy(&block
);
12068 return(TNG_CRITICAL
);
12071 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
12073 if(tng_block_read_next(tng_data
, block
,
12074 hash_mode
) == TNG_SUCCESS
)
12076 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, hash_mode
, block_id
);
12079 tng_block_destroy(&block
);
12084 tng_function_status tng_frame_set_write
12085 (const tng_trajectory_t tng_data
,
12086 const char hash_mode
)
12089 tng_gen_block_t block
;
12090 tng_trajectory_frame_set_t frame_set
;
12091 tng_function_status stat
;
12093 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12095 frame_set
= &tng_data
->current_trajectory_frame_set
;
12097 if(frame_set
->n_written_frames
== frame_set
->n_frames
)
12099 return(TNG_SUCCESS
);
12102 tng_data
->current_trajectory_frame_set_output_file_pos
=
12103 ftello(tng_data
->output_file
);
12104 tng_data
->last_trajectory_frame_set_output_file_pos
=
12105 tng_data
->current_trajectory_frame_set_output_file_pos
;
12107 if(tng_data
->current_trajectory_frame_set_output_file_pos
<= 0)
12109 return(TNG_FAILURE
);
12112 if(tng_data
->first_trajectory_frame_set_output_file_pos
== -1)
12114 tng_data
->first_trajectory_frame_set_output_file_pos
=
12115 tng_data
->current_trajectory_frame_set_output_file_pos
;
12118 tng_block_init(&block
);
12120 if(tng_frame_set_block_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
12122 tng_block_destroy(&block
);
12123 return(TNG_FAILURE
);
12126 /* Write non-particle data blocks */
12127 for(i
= 0; i
<frame_set
->n_data_blocks
; i
++)
12129 block
->id
= frame_set
->tr_data
[i
].block_id
;
12130 tng_data_block_write(tng_data
, block
, i
, TNG_FALSE
, 0, hash_mode
);
12132 /* Write the mapping blocks and particle data blocks*/
12133 if(frame_set
->n_mapping_blocks
)
12135 for(i
= 0; i
< frame_set
->n_mapping_blocks
; i
++)
12137 block
->id
= TNG_PARTICLE_MAPPING
;
12138 if(frame_set
->mappings
[i
].n_particles
> 0)
12140 tng_trajectory_mapping_block_write(tng_data
, block
, i
, hash_mode
);
12141 for(j
= 0; j
<frame_set
->n_particle_data_blocks
; j
++)
12143 block
->id
= frame_set
->tr_particle_data
[j
].block_id
;
12144 tng_data_block_write(tng_data
, block
,
12145 j
, TNG_TRUE
, &frame_set
->mappings
[i
],
12153 for(i
= 0; i
<frame_set
->n_particle_data_blocks
; i
++)
12155 block
->id
= frame_set
->tr_particle_data
[i
].block_id
;
12156 tng_data_block_write(tng_data
, block
,
12157 i
, TNG_TRUE
, 0, hash_mode
);
12162 /* Update pointers in the general info block */
12163 stat
= tng_header_pointers_update(tng_data
, hash_mode
);
12165 if(stat
== TNG_SUCCESS
)
12167 stat
= tng_frame_set_pointers_update(tng_data
, hash_mode
);
12170 tng_block_destroy(&block
);
12172 frame_set
->n_unwritten_frames
= 0;
12174 fflush(tng_data
->output_file
);
12179 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12180 (const tng_trajectory_t tng_data
,
12181 const char hash_mode
)
12183 tng_trajectory_frame_set_t frame_set
;
12185 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12187 frame_set
= &tng_data
->current_trajectory_frame_set
;
12189 if(frame_set
->n_unwritten_frames
== 0)
12191 return(TNG_SUCCESS
);
12193 frame_set
->n_frames
= frame_set
->n_unwritten_frames
;
12195 return(tng_frame_set_write(tng_data
, hash_mode
));
12198 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12199 (const tng_trajectory_t tng_data
,
12200 const int64_t first_frame
,
12201 const int64_t n_frames
)
12203 tng_gen_block_t block
;
12204 tng_trajectory_frame_set_t frame_set
;
12205 FILE *temp
= tng_data
->input_file
;
12206 int64_t curr_file_pos
;
12208 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12209 TNG_ASSERT(first_frame
>= 0, "TNG library: first_frame must be >= 0.");
12210 TNG_ASSERT(n_frames
>= 0, "TNG library: n_frames must be >= 0.");
12212 frame_set
= &tng_data
->current_trajectory_frame_set
;
12214 curr_file_pos
= ftello(tng_data
->output_file
);
12216 if(curr_file_pos
<= 10)
12218 tng_file_headers_write(tng_data
, TNG_USE_HASH
);
12221 /* Set pointer to previous frame set to the one that was loaded
12223 * FIXME: This is a bit risky. If they are not added in order
12224 * it will be wrong. */
12225 if(tng_data
->n_trajectory_frame_sets
)
12227 frame_set
->prev_frame_set_file_pos
=
12228 tng_data
->last_trajectory_frame_set_output_file_pos
;
12231 frame_set
->next_frame_set_file_pos
= -1;
12233 tng_data
->current_trajectory_frame_set_output_file_pos
=
12234 ftello(tng_data
->output_file
);
12236 tng_data
->n_trajectory_frame_sets
++;
12238 /* Set the medium range pointers */
12239 if(tng_data
->n_trajectory_frame_sets
== tng_data
->medium_stride_length
+ 1)
12241 frame_set
->medium_stride_prev_frame_set_file_pos
=
12242 tng_data
->first_trajectory_frame_set_output_file_pos
;
12244 else if(tng_data
->n_trajectory_frame_sets
> tng_data
->medium_stride_length
+ 1)
12246 /* FIXME: Currently only working if the previous frame set has its
12247 * medium stride pointer already set. This might need some fixing. */
12248 if(frame_set
->medium_stride_prev_frame_set_file_pos
!= -1 &&
12249 frame_set
->medium_stride_prev_frame_set_file_pos
!= 0)
12251 tng_block_init(&block
);
12252 tng_data
->input_file
= tng_data
->output_file
;
12254 curr_file_pos
= ftello(tng_data
->output_file
);
12255 fseeko(tng_data
->output_file
,
12256 frame_set
->medium_stride_prev_frame_set_file_pos
,
12259 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
12261 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
12262 __FILE__
, __LINE__
);
12263 tng_data
->input_file
= temp
;
12264 tng_block_destroy(&block
);
12265 return(TNG_CRITICAL
);
12268 /* Read the next frame set from the previous frame set and one
12269 * medium stride step back */
12270 fseeko(tng_data
->output_file
, block
->block_contents_size
- (6 *
12271 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
12272 if(fread(&frame_set
->medium_stride_prev_frame_set_file_pos
,
12273 sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
),
12274 1, tng_data
->output_file
) == 0)
12276 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
12277 tng_data
->input_file
= temp
;
12278 tng_block_destroy(&block
);
12279 return(TNG_CRITICAL
);
12282 if(tng_data
->input_endianness_swap_func_64
)
12284 if(tng_data
->input_endianness_swap_func_64(tng_data
,
12285 (uint64_t *)&frame_set
->medium_stride_prev_frame_set_file_pos
)
12288 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
12289 __FILE__
, __LINE__
);
12293 tng_block_destroy(&block
);
12295 /* Set the long range pointers */
12296 if(tng_data
->n_trajectory_frame_sets
== tng_data
->long_stride_length
+ 1)
12298 frame_set
->long_stride_prev_frame_set_file_pos
=
12299 tng_data
->first_trajectory_frame_set_output_file_pos
;
12301 else if(tng_data
->n_trajectory_frame_sets
> tng_data
->medium_stride_length
+ 1)
12303 /* FIXME: Currently only working if the previous frame set has its
12304 * long stride pointer already set. This might need some fixing. */
12305 if(frame_set
->long_stride_prev_frame_set_file_pos
!= -1 &&
12306 frame_set
->long_stride_prev_frame_set_file_pos
!= 0)
12308 tng_block_init(&block
);
12309 tng_data
->input_file
= tng_data
->output_file
;
12311 fseeko(tng_data
->output_file
,
12312 frame_set
->long_stride_prev_frame_set_file_pos
,
12315 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
12317 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
12318 __FILE__
, __LINE__
);
12319 tng_data
->input_file
= temp
;
12320 tng_block_destroy(&block
);
12321 return(TNG_CRITICAL
);
12324 /* Read the next frame set from the previous frame set and one
12325 * long stride step back */
12326 fseeko(tng_data
->output_file
, block
->block_contents_size
- (6 *
12327 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
12329 tng_block_destroy(&block
);
12331 if(fread(&frame_set
->long_stride_prev_frame_set_file_pos
,
12332 sizeof(frame_set
->long_stride_prev_frame_set_file_pos
),
12333 1, tng_data
->output_file
) == 0)
12335 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
12336 tng_data
->input_file
= temp
;
12337 return(TNG_CRITICAL
);
12340 if(tng_data
->input_endianness_swap_func_64
)
12342 if(tng_data
->input_endianness_swap_func_64(tng_data
,
12343 (uint64_t *)&frame_set
->long_stride_prev_frame_set_file_pos
)
12346 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
12347 __FILE__
, __LINE__
);
12354 tng_data
->input_file
= temp
;
12355 fseeko(tng_data
->output_file
, curr_file_pos
, SEEK_SET
);
12359 frame_set
->first_frame
= first_frame
;
12360 frame_set
->n_frames
= n_frames
;
12361 frame_set
->n_written_frames
= 0;
12362 frame_set
->n_unwritten_frames
= 0;
12363 frame_set
->first_frame_time
= -1;
12365 if(tng_data
->first_trajectory_frame_set_output_file_pos
== -1 ||
12366 tng_data
->first_trajectory_frame_set_output_file_pos
== 0)
12368 tng_data
->first_trajectory_frame_set_output_file_pos
=
12369 tng_data
->current_trajectory_frame_set_output_file_pos
;
12371 /* FIXME: Should check the frame number instead of the file_pos,
12372 * in case frame sets are not in order */
12373 if(tng_data
->last_trajectory_frame_set_output_file_pos
== -1 ||
12374 tng_data
->last_trajectory_frame_set_output_file_pos
== 0 ||
12375 tng_data
->last_trajectory_frame_set_output_file_pos
<
12376 tng_data
->current_trajectory_frame_set_output_file_pos
)
12378 tng_data
->last_trajectory_frame_set_output_file_pos
=
12379 tng_data
->current_trajectory_frame_set_output_file_pos
;
12382 return(TNG_SUCCESS
);
12385 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12386 (const tng_trajectory_t tng_data
,
12387 const int64_t first_frame
,
12388 const int64_t n_frames
,
12389 const double first_frame_time
)
12391 tng_function_status stat
;
12393 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12394 TNG_ASSERT(first_frame
>= 0, "TNG library: first_frame must be >= 0.");
12395 TNG_ASSERT(n_frames
>= 0, "TNG library: n_frames must be >= 0.");
12396 TNG_ASSERT(first_frame_time
>= 0, "TNG library: first_frame_time must be >= 0.");
12399 stat
= tng_frame_set_new(tng_data
, first_frame
, n_frames
);
12400 if(stat
!= TNG_SUCCESS
)
12404 stat
= tng_frame_set_first_frame_time_set(tng_data
, first_frame_time
);
12409 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12410 (const tng_trajectory_t tng_data
,
12411 const double first_frame_time
)
12413 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12414 TNG_ASSERT(first_frame_time
>= 0, "TNG library: first_frame_time must be >= 0.");
12416 tng_data
->current_trajectory_frame_set
.first_frame_time
= first_frame_time
;
12418 return(TNG_SUCCESS
);
12421 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12422 (const tng_trajectory_t tng_data
,
12425 int64_t file_pos
, next_frame_set_file_pos
;
12426 tng_gen_block_t block
;
12427 tng_function_status stat
;
12429 tng_trajectory_frame_set_t frame_set
;
12431 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12432 TNG_ASSERT(tng_data
->input_file
, "TNG library: An input file must be open to find the next frame set");
12433 TNG_ASSERT(frame
, "TNG library: frame must not be a NULL pointer");
12435 file_pos
= ftello(tng_data
->input_file
);
12437 if(tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
12439 next_frame_set_file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
12443 frame_set
= &tng_data
->current_trajectory_frame_set
;
12444 next_frame_set_file_pos
= frame_set
->next_frame_set_file_pos
;
12447 if(next_frame_set_file_pos
<= 0)
12449 return(TNG_FAILURE
);
12452 fseeko(tng_data
->input_file
, next_frame_set_file_pos
, SEEK_SET
);
12453 /* Read block headers first to see that a frame set block is found. */
12454 tng_block_init(&block
);
12455 stat
= tng_block_header_read(tng_data
, block
);
12456 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12458 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
12459 file_pos
, __FILE__
, __LINE__
);
12460 return(TNG_CRITICAL
);
12462 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12464 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12466 tng_block_destroy(&block
);
12468 if(fread(frame
, sizeof(int64_t), 1, tng_data
->input_file
) == 0)
12470 fprintf(stderr
, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12471 __FILE__
, __LINE__
);
12472 return(TNG_CRITICAL
);
12474 fseeko(tng_data
->input_file
, file_pos
, SEEK_SET
);
12476 return(TNG_SUCCESS
);
12479 static tng_function_status tng_gen_data_block_add
12480 (const tng_trajectory_t tng_data
,
12482 const tng_bool is_particle_data
,
12483 const char *block_name
,
12484 const char datatype
,
12485 const char block_type_flag
,
12487 const int64_t n_values_per_frame
,
12488 int64_t stride_length
,
12489 const int64_t num_first_particle
,
12490 const int64_t n_particles
,
12491 const int64_t codec_id
,
12496 int64_t tot_n_particles
, n_frames_div
;
12497 char ***first_dim_values
, **second_dim_values
;
12498 tng_trajectory_frame_set_t frame_set
;
12500 char *new_data_c
= (char *)new_data
;
12501 tng_function_status stat
;
12503 frame_set
= &tng_data
->current_trajectory_frame_set
;
12505 if(stride_length
<= 0)
12510 if(is_particle_data
)
12512 stat
= tng_particle_data_find(tng_data
, id
, &data
);
12516 stat
= tng_data_find(tng_data
, id
, &data
);
12518 /* If the block does not exist, create it */
12519 if(stat
!= TNG_SUCCESS
)
12521 if(is_particle_data
)
12523 stat
= tng_particle_data_block_create(tng_data
, block_type_flag
);
12527 stat
= tng_data_block_create(tng_data
, block_type_flag
);
12530 if(stat
!= TNG_SUCCESS
)
12532 fprintf(stderr
, "TNG library: Cannot create particle data block. %s: %d\n",
12533 __FILE__
, __LINE__
);
12534 return(TNG_CRITICAL
);
12536 if(is_particle_data
)
12538 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
12540 data
= &frame_set
->tr_particle_data
[frame_set
->
12541 n_particle_data_blocks
- 1];
12545 data
= &tng_data
->non_tr_particle_data
[tng_data
->
12546 n_particle_data_blocks
- 1];
12551 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
12553 data
= &frame_set
->tr_data
[frame_set
->n_data_blocks
- 1];
12557 data
= &tng_data
->non_tr_data
[tng_data
->n_data_blocks
- 1];
12560 data
->block_id
= id
;
12562 data
->block_name
= (char *)malloc(strlen(block_name
) + 1);
12563 if(!data
->block_name
)
12565 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
12566 __FILE__
, __LINE__
);
12567 return(TNG_CRITICAL
);
12569 strncpy(data
->block_name
, block_name
, strlen(block_name
) + 1);
12572 /* FIXME: Memory leak from strings. */
12574 data
->last_retrieved_frame
= -1;
12577 data
->datatype
= datatype
;
12578 data
->stride_length
= tng_max_i64(stride_length
, 1);
12579 data
->n_values_per_frame
= n_values_per_frame
;
12580 data
->n_frames
= n_frames
;
12581 if(is_particle_data
)
12583 data
->dependency
= TNG_PARTICLE_DEPENDENT
;
12587 data
->dependency
= 0;
12589 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
12591 frame_set
->n_frames
== n_frames
||
12592 stride_length
> 1))
12594 data
->dependency
+= TNG_FRAME_DEPENDENT
;
12596 data
->codec_id
= codec_id
;
12597 data
->compression_multiplier
= 1.0;
12598 /* FIXME: This can cause problems. */
12599 data
->first_frame_with_data
= frame_set
->first_frame
;
12601 if(is_particle_data
)
12603 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&& tng_data
->var_num_atoms_flag
)
12605 tot_n_particles
= frame_set
->n_particles
;
12609 tot_n_particles
= tng_data
->n_particles
;
12612 /* This is just to keep the compiler happy - avoid it considering tot_n_particles
12613 * uninitialized. */
12616 tot_n_particles
= 0;
12619 /* If data values are supplied add that data to the data block. */
12622 /* Allocate memory */
12623 if(is_particle_data
)
12625 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
12626 stride_length
, tot_n_particles
,
12627 n_values_per_frame
);
12631 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
, stride_length
,
12632 n_values_per_frame
);
12634 if(stat
!= TNG_SUCCESS
)
12636 fprintf(stderr
, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12637 __FILE__
, __LINE__
);
12638 return(TNG_CRITICAL
);
12641 if(n_frames
> frame_set
->n_unwritten_frames
)
12643 frame_set
->n_unwritten_frames
= n_frames
;
12646 n_frames_div
= (n_frames
% stride_length
) ?
12647 n_frames
/ stride_length
+ 1:
12648 n_frames
/ stride_length
;
12650 if(datatype
== TNG_CHAR_DATA
)
12652 if(is_particle_data
)
12654 for(i
= 0; i
< n_frames_div
; i
++)
12656 first_dim_values
= data
->strings
[i
];
12657 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
12660 second_dim_values
= first_dim_values
[j
];
12661 for(k
= 0; k
< n_values_per_frame
; k
++)
12663 len
= tng_min_size(strlen(new_data_c
) + 1,
12665 if(second_dim_values
[k
])
12667 free(second_dim_values
[k
]);
12669 second_dim_values
[k
] = (char *)malloc(len
);
12670 if(!second_dim_values
[k
])
12672 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
12673 __FILE__
, __LINE__
);
12674 return(TNG_CRITICAL
);
12676 strncpy(second_dim_values
[k
],
12685 for(i
= 0; i
< n_frames_div
; i
++)
12687 second_dim_values
= data
->strings
[0][i
];
12688 for(j
= 0; j
< n_values_per_frame
; j
++)
12690 len
= tng_min_size(strlen(new_data_c
) + 1,
12692 if(second_dim_values
[j
])
12694 free(second_dim_values
[j
]);
12696 second_dim_values
[j
] = (char *)malloc(len
);
12697 if(!second_dim_values
[j
])
12699 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
12700 __FILE__
, __LINE__
);
12701 return(TNG_CRITICAL
);
12703 strncpy(second_dim_values
[j
],
12715 size
= sizeof(int64_t);
12717 case TNG_FLOAT_DATA
:
12718 size
= sizeof(float);
12720 case TNG_DOUBLE_DATA
:
12722 size
= sizeof(double);
12725 if(is_particle_data
)
12727 memcpy(data
->values
, new_data
, size
* n_frames_div
*
12728 n_particles
* n_values_per_frame
);
12732 memcpy(data
->values
, new_data
, size
* n_frames_div
*
12733 n_values_per_frame
);
12738 return(TNG_SUCCESS
);
12741 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12742 (const tng_trajectory_t tng_data
,
12744 const char *block_name
,
12745 const char datatype
,
12746 const char block_type_flag
,
12748 const int64_t n_values_per_frame
,
12749 int64_t stride_length
,
12750 const int64_t codec_id
,
12753 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12754 TNG_ASSERT(block_name
, "TNG library: block_name must not be a NULL pointer.");
12755 TNG_ASSERT(n_values_per_frame
> 0, "TNG library: n_values_per_frame must be a positive integer.");
12757 return(tng_gen_data_block_add(tng_data
, id
, TNG_FALSE
, block_name
, datatype
,
12758 block_type_flag
, n_frames
, n_values_per_frame
,
12759 stride_length
, 0, 0, codec_id
, new_data
));
12762 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12763 (const tng_trajectory_t tng_data
,
12765 const char *block_name
,
12766 const char datatype
,
12767 const char block_type_flag
,
12769 const int64_t n_values_per_frame
,
12770 int64_t stride_length
,
12771 const int64_t num_first_particle
,
12772 const int64_t n_particles
,
12773 const int64_t codec_id
,
12776 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12777 TNG_ASSERT(block_name
, "TNG library: block_name mustnot be a NULL pointer.");
12778 TNG_ASSERT(n_values_per_frame
> 0, "TNG library: n_values_per_frame must be a positive integer.");
12779 TNG_ASSERT(num_first_particle
>= 0, "TNG library: num_first_particle must be >= 0.");
12780 TNG_ASSERT(n_particles
>= 0, "TNG library: n_particles must be >= 0.");
12782 return(tng_gen_data_block_add(tng_data
, id
, TNG_TRUE
, block_name
, datatype
,
12783 block_type_flag
, n_frames
, n_values_per_frame
,
12784 stride_length
, num_first_particle
, n_particles
,
12785 codec_id
, new_data
));
12788 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12789 (const tng_trajectory_t tng_data
,
12790 const int64_t block_id
,
12795 tng_trajectory_frame_set_t frame_set
;
12796 tng_function_status stat
;
12798 int block_type
= -1;
12800 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12801 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
12803 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
12805 data
= &tng_data
->non_tr_particle_data
[i
];
12806 if(data
->block_id
== block_id
)
12808 strncpy(name
, data
->block_name
, max_len
);
12809 name
[max_len
- 1] = '\0';
12810 return(TNG_SUCCESS
);
12813 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
12815 data
= &tng_data
->non_tr_data
[i
];
12816 if(data
->block_id
== block_id
)
12818 strncpy(name
, data
->block_name
, max_len
);
12819 name
[max_len
- 1] = '\0';
12820 return(TNG_SUCCESS
);
12824 frame_set
= &tng_data
->current_trajectory_frame_set
;
12826 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
12827 if(stat
== TNG_SUCCESS
)
12829 block_type
= TNG_PARTICLE_BLOCK_DATA
;
12833 stat
= tng_data_find(tng_data
, block_id
, &data
);
12834 if(stat
== TNG_SUCCESS
)
12836 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
12840 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
12841 if(stat
!= TNG_SUCCESS
)
12845 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
12846 if(stat
== TNG_SUCCESS
)
12848 block_type
= TNG_PARTICLE_BLOCK_DATA
;
12852 stat
= tng_data_find(tng_data
, block_id
, &data
);
12853 if(stat
== TNG_SUCCESS
)
12855 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
12860 if(block_type
== TNG_PARTICLE_BLOCK_DATA
)
12862 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
12864 data
= &frame_set
->tr_particle_data
[i
];
12865 if(data
->block_id
== block_id
)
12867 strncpy(name
, data
->block_name
, max_len
);
12868 name
[max_len
- 1] = '\0';
12869 return(TNG_SUCCESS
);
12873 else if(block_type
== TNG_NON_PARTICLE_BLOCK_DATA
)
12875 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
12877 data
= &frame_set
->tr_data
[i
];
12878 if(data
->block_id
== block_id
)
12880 strncpy(name
, data
->block_name
, max_len
);
12881 name
[max_len
- 1] = '\0';
12882 return(TNG_SUCCESS
);
12887 return(TNG_FAILURE
);
12890 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
12891 (const tng_trajectory_t tng_data
,
12892 const int64_t block_id
,
12893 int *block_dependency
)
12896 tng_function_status stat
;
12899 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12900 TNG_ASSERT(block_dependency
, "TNG library: block_dependency must not be a NULL pointer.");
12902 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
12904 data
= &tng_data
->non_tr_particle_data
[i
];
12905 if(data
->block_id
== block_id
)
12907 *block_dependency
= TNG_PARTICLE_DEPENDENT
;
12908 return(TNG_SUCCESS
);
12911 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
12913 data
= &tng_data
->non_tr_data
[i
];
12914 if(data
->block_id
== block_id
)
12916 *block_dependency
= 0;
12917 return(TNG_SUCCESS
);
12921 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
12922 if(stat
== TNG_SUCCESS
)
12924 *block_dependency
= TNG_PARTICLE_DEPENDENT
+ TNG_FRAME_DEPENDENT
;
12925 return(TNG_SUCCESS
);
12929 stat
= tng_data_find(tng_data
, block_id
, &data
);
12930 if(stat
== TNG_SUCCESS
)
12932 *block_dependency
= TNG_FRAME_DEPENDENT
;
12933 return(TNG_SUCCESS
);
12937 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
12938 if(stat
!= TNG_SUCCESS
)
12942 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
12943 if(stat
== TNG_SUCCESS
)
12945 *block_dependency
= TNG_PARTICLE_DEPENDENT
+ TNG_FRAME_DEPENDENT
;
12946 return(TNG_SUCCESS
);
12950 stat
= tng_data_find(tng_data
, block_id
, &data
);
12951 if(stat
== TNG_SUCCESS
)
12953 *block_dependency
= TNG_FRAME_DEPENDENT
;
12954 return(TNG_SUCCESS
);
12960 return(TNG_FAILURE
);
12963 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
12964 (const tng_trajectory_t tng_data
,
12965 const int64_t block_id
,
12966 int64_t *n_values_per_frame
)
12969 tng_function_status stat
;
12972 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12973 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
12975 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
12977 data
= &tng_data
->non_tr_particle_data
[i
];
12978 if(data
->block_id
== block_id
)
12980 *n_values_per_frame
= data
->n_values_per_frame
;
12981 return(TNG_SUCCESS
);
12984 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
12986 data
= &tng_data
->non_tr_data
[i
];
12987 if(data
->block_id
== block_id
)
12989 *n_values_per_frame
= data
->n_values_per_frame
;
12990 return(TNG_SUCCESS
);
12994 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
12995 if(stat
== TNG_SUCCESS
)
12997 *n_values_per_frame
= data
->n_values_per_frame
;
12998 return(TNG_SUCCESS
);
13002 stat
= tng_data_find(tng_data
, block_id
, &data
);
13003 if(stat
== TNG_SUCCESS
)
13005 *n_values_per_frame
= data
->n_values_per_frame
;
13006 return(TNG_SUCCESS
);
13010 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
13011 if(stat
!= TNG_SUCCESS
)
13015 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
13016 if(stat
== TNG_SUCCESS
)
13018 *n_values_per_frame
= data
->n_values_per_frame
;
13019 return(TNG_SUCCESS
);
13023 stat
= tng_data_find(tng_data
, block_id
, &data
);
13024 if(stat
== TNG_SUCCESS
)
13026 *n_values_per_frame
= data
->n_values_per_frame
;
13027 return(TNG_SUCCESS
);
13033 return(TNG_FAILURE
);
13036 tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
13037 (const tng_trajectory_t tng_data
,
13038 const int64_t block_id
,
13041 tng_gen_block_t block
;
13042 tng_function_status stat
;
13043 char datatype
, dependency
, sparse_data
;
13044 int64_t n_values
, codec_id
, first_frame_with_data
, stride_length
, curr_n_frames
;
13045 int64_t num_first_particle
, block_n_particles
;
13047 md5_state_t md5_state
;
13048 int found
= TNG_FALSE
;
13050 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13052 tng_block_init(&block
);
13054 stat
= tng_block_header_read(tng_data
, block
);
13055 /* If the block header could not be read the reading position might not have been
13056 * at the start of a block. Try again from the file position of the current frame
13058 if(stat
!= TNG_SUCCESS
)
13060 fseeko(tng_data
->input_file
, tng_data
->current_trajectory_frame_set_input_file_pos
, SEEK_SET
);
13061 stat
= tng_block_header_read(tng_data
, block
);
13062 if(stat
!= TNG_SUCCESS
)
13064 tng_block_destroy(&block
);
13068 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
13070 stat
= tng_block_read_next(tng_data
, block
, TNG_SKIP_HASH
);
13071 if(stat
!= TNG_SUCCESS
)
13073 tng_block_destroy(&block
);
13076 stat
= tng_block_header_read(tng_data
, block
);
13078 while(stat
== TNG_SUCCESS
&& block
->id
!= TNG_TRAJECTORY_FRAME_SET
&& found
== TNG_FALSE
)
13080 if(block
->id
== block_id
)
13082 stat
= tng_data_block_meta_information_read(tng_data
, &datatype
,
13083 &dependency
, &sparse_data
,
13084 &n_values
, &codec_id
,
13085 &first_frame_with_data
,
13086 &stride_length
, &curr_n_frames
,
13087 &num_first_particle
,
13088 &block_n_particles
,
13089 &multiplier
, TNG_SKIP_HASH
,
13091 if(stat
== TNG_SUCCESS
)
13098 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
13099 stat
= tng_block_header_read(tng_data
, block
);
13102 if(found
== TNG_TRUE
)
13104 *n_frames
= (tng_data
->current_trajectory_frame_set
.n_frames
-
13105 (tng_data
->current_trajectory_frame_set
.first_frame
- first_frame_with_data
)) / stride_length
;
13107 else if(stat
== TNG_SUCCESS
)
13112 tng_block_destroy(&block
);
13117 static tng_function_status tng_frame_gen_data_write
13118 (const tng_trajectory_t tng_data
,
13119 const int64_t frame_nr
,
13120 const int64_t block_id
,
13121 const tng_bool is_particle_data
,
13122 const int64_t val_first_particle
,
13123 const int64_t val_n_particles
,
13124 const void *values
,
13125 const char hash_mode
)
13127 int64_t header_pos
, file_pos
, tot_n_particles
;
13128 int64_t output_file_len
, n_values_per_frame
, size
, contents_size
;
13129 int64_t header_size
, temp_first
, temp_last
;
13130 int64_t mapping_block_end_pos
, num_first_particle
, block_n_particles
;
13131 int64_t i
, last_frame
, temp_current
, write_n_particles
;
13132 tng_gen_block_t block
;
13133 tng_trajectory_frame_set_t frame_set
;
13134 FILE *temp
= tng_data
->input_file
;
13135 struct tng_data data
;
13136 tng_function_status stat
;
13137 tng_particle_mapping_t mapping
;
13138 char dependency
, sparse_data
, datatype
;
13141 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
13143 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
13144 __FILE__
, __LINE__
);
13145 return(TNG_CRITICAL
);
13148 temp_first
= tng_data
->first_trajectory_frame_set_input_file_pos
;
13149 temp_last
= tng_data
->last_trajectory_frame_set_input_file_pos
;
13150 temp_current
= tng_data
->current_trajectory_frame_set_input_file_pos
;
13151 tng_data
->first_trajectory_frame_set_input_file_pos
=
13152 tng_data
->first_trajectory_frame_set_output_file_pos
;
13153 tng_data
->last_trajectory_frame_set_input_file_pos
=
13154 tng_data
->last_trajectory_frame_set_output_file_pos
;
13155 tng_data
->current_trajectory_frame_set_input_file_pos
=
13156 tng_data
->current_trajectory_frame_set_output_file_pos
;
13158 tng_data
->input_file
= tng_data
->output_file
;
13160 stat
= tng_frame_set_of_frame_find(tng_data
, frame_nr
);
13162 frame_set
= &tng_data
->current_trajectory_frame_set
;
13164 if(stat
!= TNG_SUCCESS
)
13166 last_frame
= frame_set
->first_frame
+
13167 frame_set
->n_frames
- 1;
13168 /* If the wanted frame would be in the frame set after the last
13169 * frame set create a new frame set. */
13170 if(stat
== TNG_FAILURE
&&
13171 last_frame
< frame_nr
)
13172 /* (last_frame < frame_nr &&
13173 tng_data->current_trajectory_frame_set.first_frame +
13174 tng_data->frame_set_n_frames >= frame_nr))*/
13176 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
13178 last_frame
= frame_nr
- 1;
13180 tng_frame_set_new(tng_data
,
13182 tng_data
->frame_set_n_frames
);
13183 file_pos
= ftello(tng_data
->output_file
);
13184 fseeko(tng_data
->output_file
, 0, SEEK_END
);
13185 output_file_len
= ftello(tng_data
->output_file
);
13186 fseeko(tng_data
->output_file
, file_pos
, SEEK_SET
);
13188 /* Read mapping blocks from the last frame set */
13189 tng_block_init(&block
);
13191 stat
= tng_block_header_read(tng_data
, block
);
13192 while(file_pos
< output_file_len
&&
13193 stat
!= TNG_CRITICAL
&&
13194 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
13197 if(block
->id
== TNG_PARTICLE_MAPPING
)
13199 tng_trajectory_mapping_block_read(tng_data
, block
,
13204 fseeko(tng_data
->output_file
, block
->block_contents_size
,
13207 file_pos
= ftello(tng_data
->output_file
);
13208 if(file_pos
< output_file_len
)
13210 stat
= tng_block_header_read(tng_data
, block
);
13214 tng_block_destroy(&block
);
13215 /* Write the frame set to disk */
13216 if(tng_frame_set_write(tng_data
, hash_mode
) != TNG_SUCCESS
)
13218 fprintf(stderr
, "TNG library: Error writing frame set. %s: %d\n", __FILE__
, __LINE__
);
13219 return(TNG_CRITICAL
);
13224 tng_data
->input_file
= temp
;
13225 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13226 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13227 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13232 tng_block_init(&block
);
13234 file_pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
13236 fseeko(tng_data
->output_file
, 0, SEEK_END
);
13237 output_file_len
= ftello(tng_data
->output_file
);
13238 fseeko(tng_data
->output_file
, file_pos
, SEEK_SET
);
13240 /* Read past the frame set block first */
13241 stat
= tng_block_header_read(tng_data
, block
);
13242 if(stat
== TNG_CRITICAL
)
13244 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
13245 file_pos
, __FILE__
, __LINE__
);
13246 tng_block_destroy(&block
);
13247 tng_data
->input_file
= temp
;
13249 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13250 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13251 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13254 fseeko(tng_data
->output_file
, block
->block_contents_size
,
13257 if(is_particle_data
== TNG_TRUE
)
13259 if(tng_data
->var_num_atoms_flag
)
13261 tot_n_particles
= frame_set
->n_particles
;
13265 tot_n_particles
= tng_data
->n_particles
;
13268 if(val_n_particles
< tot_n_particles
)
13270 mapping_block_end_pos
= -1;
13271 /* Read all mapping blocks to find the right place to put the data */
13272 stat
= tng_block_header_read(tng_data
, block
);
13273 while(file_pos
< output_file_len
&&
13274 stat
!= TNG_CRITICAL
&&
13275 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
13278 if(block
->id
== TNG_PARTICLE_MAPPING
)
13280 tng_trajectory_mapping_block_read(tng_data
, block
, hash_mode
);
13284 fseeko(tng_data
->output_file
, block
->block_contents_size
,
13287 file_pos
= ftello(tng_data
->output_file
);
13288 if(block
->id
== TNG_PARTICLE_MAPPING
)
13290 mapping
= &frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1];
13291 if(val_first_particle
>= mapping
->num_first_particle
&&
13292 val_first_particle
< mapping
->num_first_particle
+
13293 mapping
->n_particles
&&
13294 val_first_particle
+ val_n_particles
<=
13295 mapping
->num_first_particle
+ mapping
->n_particles
)
13297 mapping_block_end_pos
= file_pos
;
13300 if(file_pos
< output_file_len
)
13302 stat
= tng_block_header_read(tng_data
, block
);
13305 if(stat
== TNG_CRITICAL
)
13307 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
13308 file_pos
, __FILE__
, __LINE__
);
13309 tng_block_destroy(&block
);
13310 tng_data
->input_file
= temp
;
13312 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13313 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13314 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13317 if(mapping_block_end_pos
< 0)
13319 tng_block_destroy(&block
);
13320 tng_data
->input_file
= temp
;
13322 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13323 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13324 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13325 return(TNG_FAILURE
);
13327 fseeko(tng_data
->output_file
, mapping_block_end_pos
, SEEK_SET
);
13331 /* Read all block headers until next frame set block or
13332 * until the wanted block id is found */
13333 stat
= tng_block_header_read(tng_data
, block
);
13334 while(file_pos
< output_file_len
&&
13335 stat
!= TNG_CRITICAL
&&
13336 block
->id
!= block_id
&&
13337 (is_particle_data
!= TNG_TRUE
|| block
->id
!= TNG_PARTICLE_MAPPING
) &&
13338 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
13341 fseeko(tng_data
->output_file
, block
->block_contents_size
, SEEK_CUR
);
13342 file_pos
= ftello(tng_data
->output_file
);
13343 if(file_pos
< output_file_len
)
13345 stat
= tng_block_header_read(tng_data
, block
);
13348 if(stat
== TNG_CRITICAL
)
13350 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
13351 file_pos
, __FILE__
, __LINE__
);
13352 tng_block_destroy(&block
);
13353 tng_data
->input_file
= temp
;
13354 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13355 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13356 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13360 contents_size
= block
->block_contents_size
;
13361 header_size
= block
->header_contents_size
;
13363 header_pos
= ftello(tng_data
->output_file
) - header_size
;
13364 frame_set
= &tng_data
->current_trajectory_frame_set
;
13366 if(tng_file_input_numerical(tng_data
, &datatype
,
13368 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13370 tng_block_destroy(&block
);
13371 return(TNG_CRITICAL
);
13373 if(tng_file_input_numerical(tng_data
, &dependency
,
13374 sizeof(dependency
),
13375 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13377 tng_block_destroy(&block
);
13378 return(TNG_CRITICAL
);
13380 data
.datatype
= datatype
;
13382 if(!(dependency
& TNG_FRAME_DEPENDENT
) ||
13383 (is_particle_data
== TNG_FALSE
&& dependency
& TNG_PARTICLE_DEPENDENT
) ||
13384 (is_particle_data
== TNG_TRUE
&& !(dependency
& TNG_PARTICLE_DEPENDENT
)))
13386 tng_block_destroy(&block
);
13387 tng_data
->input_file
= temp
;
13389 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13390 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13391 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13392 return(TNG_FAILURE
);
13395 if(tng_file_input_numerical(tng_data
, &sparse_data
,
13396 sizeof(sparse_data
),
13397 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13399 tng_block_destroy(&block
);
13400 return(TNG_CRITICAL
);
13403 if(tng_file_input_numerical(tng_data
, &data
.n_values_per_frame
,
13404 sizeof(data
.n_values_per_frame
),
13405 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13407 tng_block_destroy(&block
);
13408 return(TNG_CRITICAL
);
13411 if(tng_file_input_numerical(tng_data
, &data
.codec_id
,
13412 sizeof(data
.codec_id
),
13413 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13415 tng_block_destroy(&block
);
13416 return(TNG_CRITICAL
);
13419 if(data
.codec_id
!= TNG_UNCOMPRESSED
)
13421 if(tng_file_input_numerical(tng_data
, &data
.compression_multiplier
,
13422 sizeof(data
.compression_multiplier
),
13423 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13425 tng_block_destroy(&block
);
13426 return(TNG_CRITICAL
);
13431 data
.compression_multiplier
= 1;
13436 if(tng_file_input_numerical(tng_data
, &data
.first_frame_with_data
,
13437 sizeof(data
.first_frame_with_data
),
13438 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13440 tng_block_destroy(&block
);
13441 return(TNG_CRITICAL
);
13444 if(tng_file_input_numerical(tng_data
, &data
.stride_length
,
13445 sizeof(data
.stride_length
),
13446 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13448 tng_block_destroy(&block
);
13449 return(TNG_CRITICAL
);
13454 data
.first_frame_with_data
= 0;
13455 data
.stride_length
= 1;
13457 data
.n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
;
13459 if(is_particle_data
== TNG_TRUE
)
13461 if(tng_file_input_numerical(tng_data
, &num_first_particle
,
13462 sizeof(num_first_particle
),
13463 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13465 tng_block_destroy(&block
);
13466 return(TNG_CRITICAL
);
13469 if(tng_file_input_numerical(tng_data
, &block_n_particles
,
13470 sizeof(block_n_particles
),
13471 TNG_SKIP_HASH
, 0, __LINE__
) == TNG_CRITICAL
)
13473 tng_block_destroy(&block
);
13474 return(TNG_CRITICAL
);
13478 tng_data
->input_file
= temp
;
13480 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
13481 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
13482 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
13484 switch(data
.datatype
)
13486 case(TNG_INT_DATA
):
13487 size
= sizeof(int64_t);
13489 case(TNG_FLOAT_DATA
):
13490 size
= sizeof(float);
13492 case(TNG_DOUBLE_DATA
):
13493 size
= sizeof(double);
13496 fprintf(stderr
, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__
,
13498 tng_block_destroy(&block
);
13499 return(TNG_FAILURE
);
13502 n_values_per_frame
= data
.n_values_per_frame
;
13504 file_pos
= (frame_nr
- tng_max_i64(frame_set
->first_frame
,
13505 data
.first_frame_with_data
)) /
13506 data
.stride_length
;
13507 if(is_particle_data
== TNG_TRUE
)
13509 file_pos
*= block_n_particles
* size
* n_values_per_frame
;
13513 file_pos
*= size
* n_values_per_frame
;
13516 if(file_pos
> contents_size
)
13518 fprintf(stderr
, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__
,
13520 tng_block_destroy(&block
);
13521 return(TNG_FAILURE
);
13524 fseeko(tng_data
->output_file
, file_pos
, SEEK_CUR
);
13526 if(is_particle_data
== TNG_TRUE
)
13528 write_n_particles
= val_n_particles
;
13532 write_n_particles
= 1;
13535 /* If the endianness is not big endian the data needs to be swapped */
13536 if((data
.datatype
== TNG_INT_DATA
||
13537 data
.datatype
== TNG_DOUBLE_DATA
) &&
13538 tng_data
->output_endianness_swap_func_64
)
13540 copy
= (char *)malloc(write_n_particles
* n_values_per_frame
* size
);
13541 memcpy(copy
, values
, write_n_particles
* n_values_per_frame
* size
);
13542 for(i
= 0; i
< write_n_particles
* n_values_per_frame
; i
++)
13544 if(tng_data
->output_endianness_swap_func_64(tng_data
,
13545 (uint64_t *) copy
+i
)
13548 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
13549 __FILE__
, __LINE__
);
13552 fwrite(copy
, write_n_particles
* n_values_per_frame
, size
,
13553 tng_data
->output_file
);
13556 else if(data
.datatype
== TNG_FLOAT_DATA
&&
13557 tng_data
->output_endianness_swap_func_32
)
13559 copy
= (char *)malloc(write_n_particles
* n_values_per_frame
* size
);
13560 memcpy(copy
, values
, write_n_particles
* n_values_per_frame
* size
);
13561 for(i
= 0; i
< write_n_particles
* n_values_per_frame
; i
++)
13563 if(tng_data
->output_endianness_swap_func_32(tng_data
,
13564 (uint32_t *) copy
+i
)
13567 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
13568 __FILE__
, __LINE__
);
13571 fwrite(copy
, write_n_particles
* n_values_per_frame
, size
,
13572 tng_data
->output_file
);
13578 fwrite(values
, write_n_particles
* n_values_per_frame
, size
, tng_data
->output_file
);
13581 fflush(tng_data
->output_file
);
13583 /* Update the number of written frames in the frame set. */
13584 if(frame_nr
- frame_set
->first_frame
+ 1 > frame_set
->n_written_frames
)
13586 frame_set
->n_written_frames
= frame_nr
- frame_set
->first_frame
+ 1;
13589 /* If the last frame has been written update the hash */
13590 if(hash_mode
== TNG_USE_HASH
&& (frame_nr
+ data
.stride_length
-
13591 data
.first_frame_with_data
) >=
13592 frame_set
->n_frames
)
13594 tng_md5_hash_update(tng_data
, block
, header_pos
, header_pos
+
13598 tng_block_destroy(&block
);
13600 return(TNG_SUCCESS
);
13603 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13604 (const tng_trajectory_t tng_data
,
13605 const int64_t frame_nr
,
13606 const int64_t block_id
,
13607 const void *values
,
13608 const char hash_mode
)
13610 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13611 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
13612 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer.");
13614 /* This is now just calling the generic data writing function. This
13615 * function must keep its signature to let the API be backwards
13617 return(tng_frame_gen_data_write(tng_data
, frame_nr
, block_id
,
13618 TNG_FALSE
, 0, 0, values
, hash_mode
));
13621 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13622 (const tng_trajectory_t tng_data
,
13623 const int64_t frame_nr
,
13624 const int64_t block_id
,
13625 const int64_t val_first_particle
,
13626 const int64_t val_n_particles
,
13627 const void *values
,
13628 const char hash_mode
)
13630 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13631 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
13632 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer.");
13633 TNG_ASSERT(val_first_particle
>= 0, "TNG library: val_first_particle must be >= 0.");
13634 TNG_ASSERT(val_n_particles
>= 0, "TNG library: val_n_particles must be >= 0.");
13636 /* This is now just calling the generic data writing function. This
13637 * function must keep its signature to let the API be backwards
13639 return(tng_frame_gen_data_write(tng_data
, frame_nr
, block_id
,
13640 TNG_TRUE
, val_first_particle
, val_n_particles
,
13641 values
, hash_mode
));
13644 static tng_function_status tng_data_values_alloc
13645 (const tng_trajectory_t tng_data
,
13646 union data_values
***values
,
13647 const int64_t n_frames
,
13648 const int64_t n_values_per_frame
,
13652 tng_function_status stat
;
13654 if(n_frames
<= 0 || n_values_per_frame
<= 0)
13656 return(TNG_FAILURE
);
13661 stat
= tng_data_values_free(tng_data
, *values
, n_frames
,
13662 n_values_per_frame
,
13664 if(stat
!= TNG_SUCCESS
)
13666 fprintf(stderr
, "TNG library: Cannot free particle data values. %s: %d\n",
13667 __FILE__
, __LINE__
);
13671 *values
= (union data_values
**)malloc(sizeof(union data_values
*) * n_frames
);
13674 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
13675 __FILE__
, __LINE__
);
13676 return(TNG_CRITICAL
);
13680 for(i
= 0; i
< n_frames
; i
++)
13682 (*values
)[i
] = (union data_values
*)malloc(sizeof(union data_values
) *
13683 n_values_per_frame
);
13686 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
13687 __FILE__
, __LINE__
);
13690 return(TNG_CRITICAL
);
13693 return(TNG_SUCCESS
);
13696 /* FIXME: This needs ***values */
13697 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
13698 (const tng_trajectory_t tng_data
,
13699 union data_values
**values
,
13700 const int64_t n_frames
,
13701 const int64_t n_values_per_frame
,
13709 for(i
= 0; i
< n_frames
; i
++)
13713 if(type
== TNG_CHAR_DATA
)
13715 for(j
= 0; j
< n_values_per_frame
; j
++)
13719 free(values
[i
][j
].c
);
13720 values
[i
][j
].c
= 0;
13732 return(TNG_SUCCESS
);
13735 static tng_function_status tng_particle_data_values_alloc
13736 (const tng_trajectory_t tng_data
,
13737 union data_values
****values
,
13738 const int64_t n_frames
,
13739 const int64_t n_particles
,
13740 const int64_t n_values_per_frame
,
13744 tng_function_status stat
;
13746 if(n_particles
== 0 || n_values_per_frame
== 0)
13748 return(TNG_FAILURE
);
13753 stat
= tng_particle_data_values_free(tng_data
, *values
, n_frames
,
13754 n_particles
, n_values_per_frame
,
13756 if(stat
!= TNG_SUCCESS
)
13758 fprintf(stderr
, "TNG library: Cannot free particle data values. %s: %d\n",
13759 __FILE__
, __LINE__
);
13763 *values
= (union data_values
***)malloc(sizeof(union data_values
**) * n_frames
);
13766 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
13767 __FILE__
, __LINE__
);
13768 return(TNG_CRITICAL
);
13772 for(i
= 0; i
< n_frames
; i
++)
13774 (*values
)[i
] = (union data_values
**)malloc(sizeof(union data_values
*) *
13778 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
13779 __FILE__
, __LINE__
);
13782 return(TNG_CRITICAL
);
13784 for(j
= 0; j
< n_particles
; j
++)
13786 (*values
)[i
][j
] = (union data_values
*)malloc(sizeof(union data_values
) *
13787 n_values_per_frame
);
13788 if(!(*values
)[i
][j
])
13790 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
13791 __FILE__
, __LINE__
);
13792 tng_particle_data_values_free(tng_data
, *values
, n_frames
,
13793 n_particles
, n_values_per_frame
,
13796 return(TNG_CRITICAL
);
13800 return(TNG_SUCCESS
);
13803 /* FIXME: This needs ****values */
13804 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
13805 (const tng_trajectory_t tng_data
,
13806 union data_values
***values
,
13807 const int64_t n_frames
,
13808 const int64_t n_particles
,
13809 const int64_t n_values_per_frame
,
13817 for(i
= 0; i
< n_frames
; i
++)
13821 for(j
= 0; j
< n_particles
; j
++)
13823 if(type
== TNG_CHAR_DATA
)
13825 for(k
= 0; k
< n_values_per_frame
; k
++)
13827 if(values
[i
][j
][k
].c
)
13829 free(values
[i
][j
][k
].c
);
13830 values
[i
][j
][k
].c
= 0;
13834 free(values
[i
][j
]);
13845 return(TNG_SUCCESS
);
13848 static tng_function_status tng_gen_data_get
13849 (const tng_trajectory_t tng_data
,
13850 const int64_t block_id
,
13851 const tng_bool is_particle_data
,
13852 union data_values
****values
,
13854 int64_t *n_particles
,
13855 int64_t *n_values_per_frame
,
13858 int64_t i
, j
, k
, mapping
, file_pos
, i_step
, block_index
;
13862 tng_trajectory_frame_set_t frame_set
;
13863 tng_gen_block_t block
;
13864 char block_type_flag
;
13865 tng_function_status stat
;
13867 frame_set
= &tng_data
->current_trajectory_frame_set
;
13872 if(is_particle_data
== TNG_TRUE
)
13874 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
13878 stat
= tng_data_find(tng_data
, block_id
, &data
);
13881 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
13883 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
13887 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
13890 if(stat
!= TNG_SUCCESS
)
13892 tng_block_init(&block
);
13893 file_pos
= ftello(tng_data
->input_file
);
13894 /* Read all blocks until next frame set block */
13895 stat
= tng_block_header_read(tng_data
, block
);
13896 while(file_pos
< tng_data
->input_file_len
&&
13897 stat
!= TNG_CRITICAL
&&
13898 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
13901 /* Use hash by default */
13902 stat
= tng_block_read_next(tng_data
, block
,
13904 if(stat
!= TNG_CRITICAL
)
13906 file_pos
= ftello(tng_data
->input_file
);
13907 if(file_pos
< tng_data
->input_file_len
)
13909 stat
= tng_block_header_read(tng_data
, block
);
13913 tng_block_destroy(&block
);
13914 if(stat
== TNG_CRITICAL
)
13916 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
13917 file_pos
, __FILE__
, __LINE__
);
13921 if(is_particle_data
== TNG_TRUE
)
13923 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
13925 data
= &frame_set
->tr_particle_data
[i
];
13926 if(data
->block_id
== block_id
)
13929 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
13936 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
13938 data
= &frame_set
->tr_data
[i
];
13939 if(data
->block_id
== block_id
)
13946 if(block_index
< 0)
13948 return(TNG_FAILURE
);
13952 if(is_particle_data
== TNG_TRUE
)
13954 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
13955 tng_data
->var_num_atoms_flag
)
13957 *n_particles
= frame_set
->n_particles
;
13961 *n_particles
= tng_data
->n_particles
;
13965 *n_frames
= tng_max_i64(1, data
->n_frames
);
13966 *n_values_per_frame
= data
->n_values_per_frame
;
13967 *type
= data
->datatype
;
13969 if(is_particle_data
== TNG_TRUE
)
13973 if(tng_particle_data_values_alloc(tng_data
, values
, *n_frames
,
13974 *n_particles
, *n_values_per_frame
,
13975 *type
) != TNG_SUCCESS
)
13977 return(TNG_CRITICAL
);
13981 i_step
= (*n_particles
) * (*n_values_per_frame
);
13983 /* It's not very elegant to reuse so much of the code in the different case
13984 * statements, but it's unnecessarily slow to have the switch-case block
13985 * inside the for loops. */
13988 case TNG_CHAR_DATA
:
13989 for(i
= 0; i
< *n_frames
; i
++)
13991 for(j
= 0; j
< *n_particles
; j
++)
13993 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
13994 for(k
= 0; k
< *n_values_per_frame
; k
++)
13996 len
= strlen(data
->strings
[i
][j
][k
]) + 1;
13997 (*values
)[i
][mapping
][k
].c
= (char *)malloc(len
);
13998 strncpy((*values
)[i
][mapping
][k
].c
,
13999 data
->strings
[i
][j
][k
], len
);
14005 size
= sizeof(int);
14006 for(i
= 0; i
< *n_frames
; i
++)
14008 for(j
= 0; j
< *n_particles
; j
++)
14010 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14011 for(k
= 0; k
< *n_values_per_frame
; k
++)
14013 (*values
)[i
][mapping
][k
].i
= *(int *)
14014 ((char *)data
->values
+ size
*
14016 (*n_values_per_frame
) + k
));
14021 case TNG_FLOAT_DATA
:
14022 size
= sizeof(float);
14023 for(i
= 0; i
< *n_frames
; i
++)
14025 for(j
= 0; j
< *n_particles
; j
++)
14027 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14028 for(k
= 0; k
< *n_values_per_frame
; k
++)
14030 (*values
)[i
][mapping
][k
].f
= *(float *)
14031 ((char *)data
->values
+ size
*
14033 (*n_values_per_frame
) + k
));
14038 case TNG_DOUBLE_DATA
:
14040 size
= sizeof(double);
14041 for(i
= 0; i
< *n_frames
; i
++)
14043 for(j
= 0; j
< *n_particles
; j
++)
14045 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14046 for(k
= 0; k
< *n_values_per_frame
; k
++)
14048 (*values
)[i
][mapping
][k
].d
= *(double *)
14049 ((char *)data
->values
+ size
*
14051 (*n_values_per_frame
) + k
));
14059 if(*(values
[0]) == 0)
14061 if(tng_data_values_alloc(tng_data
, values
[0], *n_frames
,
14062 *n_values_per_frame
,
14063 *type
) != TNG_SUCCESS
)
14065 return(TNG_CRITICAL
);
14070 case TNG_CHAR_DATA
:
14071 for(i
= 0; i
< *n_frames
; i
++)
14073 for(j
= 0; j
< *n_values_per_frame
; j
++)
14075 len
= strlen(data
->strings
[0][i
][j
]) + 1;
14076 (*values
)[0][i
][j
].c
= (char *)malloc(len
);
14077 strncpy((*values
)[0][i
][j
].c
, data
->strings
[0][i
][j
], len
);
14082 size
= sizeof(int);
14083 for(i
= 0; i
< *n_frames
; i
++)
14085 for(j
= 0; j
< *n_values_per_frame
; j
++)
14087 (*values
)[0][i
][j
].i
= *(int *)((char *)data
->values
+ size
*
14088 (i
*(*n_values_per_frame
) + j
));
14092 case TNG_FLOAT_DATA
:
14093 size
= sizeof(float);
14094 for(i
= 0; i
< *n_frames
; i
++)
14096 for(j
= 0; j
< *n_values_per_frame
; j
++)
14098 (*values
)[0][i
][j
].f
= *(float *)((char *)data
->values
+ size
*
14099 (i
*(*n_values_per_frame
) + j
));
14103 case TNG_DOUBLE_DATA
:
14105 size
= sizeof(double);
14106 for(i
= 0; i
< *n_frames
; i
++)
14108 for(j
= 0; j
< *n_values_per_frame
; j
++)
14110 (*values
)[0][i
][j
].d
= *(double *)((char *)data
->values
+ size
*
14111 (i
*(*n_values_per_frame
) + j
));
14117 data
->last_retrieved_frame
= frame_set
->first_frame
+ data
->n_frames
- 1;
14119 return(TNG_SUCCESS
);
14122 tng_function_status DECLSPECDLLEXPORT tng_data_get
14123 (const tng_trajectory_t tng_data
,
14124 const int64_t block_id
,
14125 union data_values
***values
,
14127 int64_t *n_values_per_frame
,
14130 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14131 TNG_ASSERT(n_frames
, "TNG library: n_frames must not be a NULL pointer.");
14132 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
14133 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
14135 return(tng_gen_data_get(tng_data
, block_id
, TNG_FALSE
, &values
, n_frames
, 0,
14136 n_values_per_frame
, type
));
14139 static tng_function_status tng_gen_data_vector_get
14140 (const tng_trajectory_t tng_data
,
14141 const int64_t block_id
,
14142 const tng_bool is_particle_data
,
14145 int64_t *stride_length
,
14146 int64_t *n_particles
,
14147 int64_t *n_values_per_frame
,
14150 int64_t i
, j
, mapping
, file_pos
, i_step
, full_data_len
, n_frames_div
;
14151 int64_t block_index
;
14154 tng_trajectory_frame_set_t frame_set
;
14155 tng_gen_block_t block
;
14157 char block_type_flag
;
14158 tng_function_status stat
;
14160 frame_set
= &tng_data
->current_trajectory_frame_set
;
14165 if(is_particle_data
== TNG_TRUE
)
14167 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
14171 stat
= tng_data_find(tng_data
, block_id
, &data
);
14174 if(stat
!= TNG_SUCCESS
)
14176 tng_block_init(&block
);
14177 file_pos
= ftello(tng_data
->input_file
);
14178 /* Read all blocks until next frame set block */
14179 stat
= tng_block_header_read(tng_data
, block
);
14180 while(file_pos
< tng_data
->input_file_len
&&
14181 stat
!= TNG_CRITICAL
&&
14182 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14185 /* Use hash by default */
14186 stat
= tng_block_read_next(tng_data
, block
,
14188 if(stat
!= TNG_CRITICAL
)
14190 file_pos
= ftello(tng_data
->input_file
);
14191 if(file_pos
< tng_data
->input_file_len
)
14193 stat
= tng_block_header_read(tng_data
, block
);
14197 tng_block_destroy(&block
);
14198 if(stat
== TNG_CRITICAL
)
14200 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
14201 file_pos
, __FILE__
, __LINE__
);
14205 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
14207 data
= &frame_set
->tr_particle_data
[i
];
14208 if(data
->block_id
== block_id
)
14214 if(block_index
< 0)
14216 return(TNG_FAILURE
);
14220 if(is_particle_data
== TNG_TRUE
)
14222 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
14224 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
14228 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
14231 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
14232 tng_data
->var_num_atoms_flag
)
14234 *n_particles
= frame_set
->n_particles
;
14238 *n_particles
= tng_data
->n_particles
;
14242 *type
= data
->datatype
;
14246 case TNG_CHAR_DATA
:
14247 return(TNG_FAILURE
);
14249 size
= sizeof(int64_t);
14251 case TNG_FLOAT_DATA
:
14252 size
= sizeof(float);
14254 case TNG_DOUBLE_DATA
:
14256 size
= sizeof(double);
14259 *n_frames
= tng_max_i64(1, data
->n_frames
);
14260 *n_values_per_frame
= data
->n_values_per_frame
;
14261 *stride_length
= data
->stride_length
;
14263 n_frames_div
= (*n_frames
% *stride_length
) ?
14264 *n_frames
/ *stride_length
+ 1:
14265 *n_frames
/ *stride_length
;
14267 full_data_len
= n_frames_div
* size
*
14268 (*n_values_per_frame
);
14269 if(is_particle_data
== TNG_TRUE
)
14271 full_data_len
*= (*n_particles
);
14274 temp
= (char *)realloc(*values
, full_data_len
);
14277 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
14278 __FILE__
, __LINE__
);
14281 return(TNG_CRITICAL
);
14286 if(is_particle_data
!= TNG_TRUE
|| frame_set
->n_mapping_blocks
<= 0)
14288 memcpy(*values
, data
->values
, full_data_len
);
14292 i_step
= (*n_particles
) * (*n_values_per_frame
);
14293 for(i
= 0; i
< *n_frames
; i
++)
14295 for(j
= 0; j
< *n_particles
; j
++)
14297 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14298 memcpy(((char *)*values
) + size
* (i
* i_step
+ mapping
*
14299 (*n_values_per_frame
)),
14300 (char *)data
->values
+ size
*
14301 (i
* i_step
+ j
* (*n_values_per_frame
)),
14302 size
* (*n_values_per_frame
));
14307 data
->last_retrieved_frame
= frame_set
->first_frame
+ data
->n_frames
- 1;
14309 return(TNG_SUCCESS
);
14312 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
14313 (const tng_trajectory_t tng_data
,
14314 const int64_t block_id
,
14317 int64_t *stride_length
,
14318 int64_t *n_values_per_frame
,
14321 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14322 TNG_ASSERT(n_frames
, "TNG library: n_frames must not be a NULL pointer.");
14323 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
14324 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
14325 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
14327 return(tng_gen_data_vector_get(tng_data
, block_id
, TNG_FALSE
, values
,
14328 n_frames
, stride_length
, 0, n_values_per_frame
,
14332 static tng_function_status tng_gen_data_interval_get
14333 (const tng_trajectory_t tng_data
,
14334 const int64_t block_id
,
14335 const tng_bool is_particle_data
,
14336 const int64_t start_frame_nr
,
14337 const int64_t end_frame_nr
,
14338 const char hash_mode
,
14339 union data_values
****values
,
14340 int64_t *n_particles
,
14341 int64_t *n_values_per_frame
,
14344 int64_t i
, j
, k
, mapping
, n_frames
, file_pos
, current_frame_pos
, i_step
;
14345 int64_t first_frame
, block_index
;
14349 tng_trajectory_frame_set_t frame_set
;
14350 tng_gen_block_t block
;
14351 char block_type_flag
;
14352 tng_function_status stat
;
14356 frame_set
= &tng_data
->current_trajectory_frame_set
;
14357 first_frame
= frame_set
->first_frame
;
14359 stat
= tng_frame_set_of_frame_find(tng_data
, start_frame_nr
);
14360 if(stat
!= TNG_SUCCESS
)
14365 /* Do not re-read the frame set. */
14366 if((is_particle_data
== TNG_TRUE
&&
14367 (first_frame
!= frame_set
->first_frame
||
14368 frame_set
->n_particle_data_blocks
<= 0)) ||
14369 (is_particle_data
== TNG_FALSE
&&
14370 (first_frame
!= frame_set
->first_frame
||
14371 frame_set
->n_data_blocks
<= 0)))
14373 tng_block_init(&block
);
14374 file_pos
= ftello(tng_data
->input_file
);
14375 /* Read all blocks until next frame set block */
14376 stat
= tng_block_header_read(tng_data
, block
);
14377 while(file_pos
< tng_data
->input_file_len
&&
14378 stat
!= TNG_CRITICAL
&&
14379 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14382 stat
= tng_block_read_next(tng_data
, block
,
14384 if(stat
!= TNG_CRITICAL
)
14386 file_pos
= ftello(tng_data
->input_file
);
14387 if(file_pos
< tng_data
->input_file_len
)
14389 stat
= tng_block_header_read(tng_data
, block
);
14393 tng_block_destroy(&block
);
14394 if(stat
== TNG_CRITICAL
)
14396 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
14397 file_pos
, __FILE__
, __LINE__
);
14402 /* See if there is already a data block of this ID.
14403 * Start checking the last read frame set */
14404 if(is_particle_data
== TNG_TRUE
)
14406 for(i
= frame_set
->n_particle_data_blocks
; i
-- ;)
14408 data
= &frame_set
->tr_particle_data
[i
];
14409 if(data
->block_id
== block_id
)
14412 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
14419 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
14421 data
= &frame_set
->tr_data
[i
];
14422 if(data
->block_id
== block_id
)
14430 if(block_index
< 0)
14432 fprintf(stderr
, "TNG library: Could not find particle data block with id %" PRId64
". %s: %d\n",
14433 block_id
, __FILE__
, __LINE__
);
14434 return(TNG_FAILURE
);
14437 if(is_particle_data
== TNG_TRUE
)
14439 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
14440 tng_data
->var_num_atoms_flag
)
14442 *n_particles
= frame_set
->n_particles
;
14446 *n_particles
= tng_data
->n_particles
;
14450 n_frames
= end_frame_nr
- start_frame_nr
+ 1;
14451 *n_values_per_frame
= data
->n_values_per_frame
;
14452 *type
= data
->datatype
;
14456 if(is_particle_data
== TNG_TRUE
)
14458 if(tng_particle_data_values_alloc(tng_data
, values
, n_frames
,
14459 *n_particles
, *n_values_per_frame
,
14460 *type
) != TNG_SUCCESS
)
14462 return(TNG_CRITICAL
);
14467 if(tng_data_values_alloc(tng_data
, *values
, n_frames
,
14468 *n_values_per_frame
,
14469 *type
) != TNG_SUCCESS
)
14471 return(TNG_CRITICAL
);
14476 current_frame_pos
= start_frame_nr
- frame_set
->first_frame
;
14478 if(is_particle_data
== TNG_TRUE
)
14480 i_step
= (*n_particles
) * (*n_values_per_frame
);
14484 i_step
= (*n_values_per_frame
);
14486 /* It's not very elegant to reuse so much of the code in the different case
14487 * statements, but it's unnecessarily slow to have the switch-case block
14488 * inside the for loops. */
14491 case TNG_CHAR_DATA
:
14492 for(i
=0; i
<n_frames
; i
++)
14494 if(current_frame_pos
== frame_set
->n_frames
)
14496 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
14497 if(stat
!= TNG_SUCCESS
)
14501 current_frame_pos
= 0;
14503 if(is_particle_data
== TNG_TRUE
)
14505 for(j
= 0; j
< *n_particles
; j
++)
14507 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14508 for(k
= 0; k
< *n_values_per_frame
; k
++)
14510 len
= strlen(data
->strings
[current_frame_pos
][j
][k
]) + 1;
14511 (*values
)[i
][mapping
][k
].c
= (char *)malloc(len
);
14512 strncpy((*values
)[i
][mapping
][k
].c
, data
->strings
[current_frame_pos
][j
][k
], len
);
14518 for(j
= 0; j
< *n_values_per_frame
; j
++)
14520 len
= strlen(data
->strings
[0][current_frame_pos
][j
]) + 1;
14521 (*values
)[0][i
][j
].c
= (char *)malloc(len
);
14522 strncpy((*values
)[0][i
][j
].c
, data
->strings
[0][current_frame_pos
][j
], len
);
14525 current_frame_pos
++;
14529 size
= sizeof(int);
14530 for(i
=0; i
<n_frames
; i
++)
14532 if(current_frame_pos
== frame_set
->n_frames
)
14534 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
14535 if(stat
!= TNG_SUCCESS
)
14539 current_frame_pos
= 0;
14541 if(is_particle_data
== TNG_TRUE
)
14543 for(j
= 0; j
< *n_particles
; j
++)
14545 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14546 for(k
= 0; k
< *n_values_per_frame
; k
++)
14548 (*values
)[i
][mapping
][k
].i
= *(int *)
14549 ((char *)data
->values
+ size
*
14550 (current_frame_pos
*
14552 (*n_values_per_frame
) + k
));
14555 current_frame_pos
++;
14559 for(j
= 0; j
< *n_values_per_frame
; j
++)
14561 (*values
)[0][i
][j
].i
= *(int *)((char *)data
->values
+ size
*
14562 (current_frame_pos
*
14568 case TNG_FLOAT_DATA
:
14569 size
= sizeof(float);
14570 for(i
=0; i
<n_frames
; i
++)
14572 if(current_frame_pos
== frame_set
->n_frames
)
14574 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
14575 if(stat
!= TNG_SUCCESS
)
14579 current_frame_pos
= 0;
14581 if(is_particle_data
== TNG_TRUE
)
14583 for(j
=0; j
<*n_particles
; j
++)
14585 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14586 for(k
=0; k
<*n_values_per_frame
; k
++)
14588 (*values
)[i
][mapping
][k
].f
= *(float *)
14589 ((char *)data
->values
+ size
*
14590 (current_frame_pos
*
14592 (*n_values_per_frame
) + k
));
14598 for(j
= 0; j
< *n_values_per_frame
; j
++)
14600 (*values
)[0][i
][j
].f
= *(float *)((char *)data
->values
+ size
*
14601 (current_frame_pos
*
14605 current_frame_pos
++;
14608 case TNG_DOUBLE_DATA
:
14610 size
= sizeof(double);
14611 for(i
=0; i
<n_frames
; i
++)
14613 if(current_frame_pos
== frame_set
->n_frames
)
14615 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
14616 if(stat
!= TNG_SUCCESS
)
14620 current_frame_pos
= 0;
14622 if(is_particle_data
== TNG_TRUE
)
14624 for(j
=0; j
<*n_particles
; j
++)
14626 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
14627 for(k
=0; k
<*n_values_per_frame
; k
++)
14629 (*values
)[i
][mapping
][k
].d
= *(double *)
14630 ((char *)data
->values
+ size
*
14631 (current_frame_pos
*
14633 (*n_values_per_frame
) + k
));
14639 for(j
= 0; j
< *n_values_per_frame
; j
++)
14641 (*values
)[0][i
][j
].d
= *(double *)((char *)data
->values
+ size
*
14642 (current_frame_pos
*
14646 current_frame_pos
++;
14650 data
->last_retrieved_frame
= end_frame_nr
;
14652 return(TNG_SUCCESS
);
14655 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14656 (const tng_trajectory_t tng_data
,
14657 const int64_t block_id
,
14658 const int64_t start_frame_nr
,
14659 const int64_t end_frame_nr
,
14660 const char hash_mode
,
14661 union data_values
***values
,
14662 int64_t *n_values_per_frame
,
14665 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14666 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14667 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
14668 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
14670 return(tng_gen_data_interval_get(tng_data
, block_id
, TNG_FALSE
, start_frame_nr
,
14671 end_frame_nr
, hash_mode
, &values
, 0,
14672 n_values_per_frame
, type
));
14675 static tng_function_status tng_gen_data_vector_interval_get
14676 (const tng_trajectory_t tng_data
,
14677 const int64_t block_id
,
14678 const tng_bool is_particle_data
,
14679 const int64_t start_frame_nr
,
14680 const int64_t end_frame_nr
,
14681 const char hash_mode
,
14683 int64_t *n_particles
,
14684 int64_t *stride_length
,
14685 int64_t *n_values_per_frame
,
14688 int64_t n_frames
, tot_n_frames
, n_frames_div
, n_frames_div_2
, first_frame
;
14689 int64_t file_pos
, current_frame_pos
, last_frame_pos
, full_data_len
, frame_size
;
14691 tng_trajectory_frame_set_t frame_set
;
14693 tng_gen_block_t block
;
14694 void *current_values
= 0, *temp
;
14695 tng_function_status stat
;
14697 frame_set
= &tng_data
->current_trajectory_frame_set
;
14698 first_frame
= frame_set
->first_frame
;
14700 stat
= tng_frame_set_of_frame_find(tng_data
, start_frame_nr
);
14701 if(stat
!= TNG_SUCCESS
)
14706 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
14707 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
14708 if(is_particle_data
== TNG_TRUE
)
14710 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
14714 stat
= tng_data_find(tng_data
, block_id
, &data
);
14717 if(first_frame
!= frame_set
->first_frame
||
14718 stat
!= TNG_SUCCESS
)
14720 tng_block_init(&block
);
14721 if(stat
!= TNG_SUCCESS
)
14723 fseeko(tng_data
->input_file
,
14724 tng_data
->current_trajectory_frame_set_input_file_pos
,
14726 stat
= tng_block_header_read(tng_data
, block
);
14727 if(stat
!= TNG_SUCCESS
)
14729 fprintf(stderr
, "TNG library: Cannot read block header. %s: %d\n",
14730 __FILE__
, __LINE__
);
14734 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
14736 file_pos
= ftello(tng_data
->input_file
);
14737 /* Read until next frame set block */
14738 stat
= tng_block_header_read(tng_data
, block
);
14739 while(file_pos
< tng_data
->input_file_len
&&
14740 stat
!= TNG_CRITICAL
&&
14741 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14744 if(block
->id
== block_id
|| block
->id
== TNG_PARTICLE_MAPPING
)
14746 stat
= tng_block_read_next(tng_data
, block
,
14748 if(stat
!= TNG_CRITICAL
)
14750 file_pos
= ftello(tng_data
->input_file
);
14751 if(file_pos
< tng_data
->input_file_len
)
14753 stat
= tng_block_header_read(tng_data
, block
);
14759 file_pos
+= block
->block_contents_size
+ block
->header_contents_size
;
14760 fseeko(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
14761 if(file_pos
< tng_data
->input_file_len
)
14763 stat
= tng_block_header_read(tng_data
, block
);
14767 tng_block_destroy(&block
);
14768 if(stat
== TNG_CRITICAL
)
14770 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
14771 file_pos
, __FILE__
, __LINE__
);
14775 if(is_particle_data
== TNG_TRUE
)
14777 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
14781 stat
= tng_data_find(tng_data
, block_id
, &data
);
14783 if(stat
!= TNG_SUCCESS
)
14788 stat
= tng_gen_data_vector_get(tng_data
, block_id
, is_particle_data
,
14789 ¤t_values
, &n_frames
, stride_length
,
14790 n_particles
, n_values_per_frame
, type
);
14792 if(stat
!= TNG_SUCCESS
|| (is_particle_data
&& *n_particles
== 0))
14796 free(current_values
);
14801 if(n_frames
== 1 && n_frames
< frame_set
->n_frames
)
14807 tot_n_frames
= end_frame_nr
- start_frame_nr
+ 1;
14812 case TNG_CHAR_DATA
:
14813 return(TNG_FAILURE
);
14815 size
= sizeof(int64_t);
14817 case TNG_FLOAT_DATA
:
14818 size
= sizeof(float);
14820 case TNG_DOUBLE_DATA
:
14822 size
= sizeof(double);
14825 n_frames_div
= (tot_n_frames
% *stride_length
) ?
14826 tot_n_frames
/ *stride_length
+ 1:
14827 tot_n_frames
/ *stride_length
;
14829 full_data_len
= n_frames_div
* size
* (*n_values_per_frame
);
14830 if(is_particle_data
)
14832 full_data_len
*= (*n_particles
);
14835 temp
= (char *)realloc(*values
, full_data_len
);
14838 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
14839 __FILE__
, __LINE__
);
14842 return(TNG_CRITICAL
);
14847 if( n_frames
== 1 && n_frames
< frame_set
->n_frames
)
14849 if(is_particle_data
)
14851 memcpy(*values
, current_values
, size
* (*n_particles
) *
14852 (*n_values_per_frame
));
14856 memcpy(*values
, current_values
, size
* (*n_values_per_frame
));
14861 current_frame_pos
= start_frame_nr
- frame_set
->first_frame
;
14863 frame_size
= size
* (*n_values_per_frame
);
14864 if(is_particle_data
)
14866 frame_size
*= (*n_particles
);
14869 last_frame_pos
= tng_min_i64(n_frames
,
14870 end_frame_nr
- start_frame_nr
);
14872 n_frames_div
= current_frame_pos
/ *stride_length
;
14873 n_frames_div_2
= (last_frame_pos
% *stride_length
) ?
14874 last_frame_pos
/ *stride_length
+ 1:
14875 last_frame_pos
/ *stride_length
;
14876 n_frames_div_2
= tng_max_i64(1, n_frames_div_2
+ 1);
14878 memcpy(*values
, (char *)current_values
+ n_frames_div
* frame_size
,
14879 n_frames_div_2
* frame_size
);
14881 current_frame_pos
+= n_frames
- current_frame_pos
;
14883 while(current_frame_pos
<= end_frame_nr
- start_frame_nr
)
14885 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
14886 if(stat
!= TNG_SUCCESS
)
14890 free(current_values
);
14897 stat
= tng_gen_data_vector_get(tng_data
, block_id
, is_particle_data
,
14898 ¤t_values
, &n_frames
,
14899 stride_length
, n_particles
,
14900 n_values_per_frame
, type
);
14902 if(stat
!= TNG_SUCCESS
)
14906 free(current_values
);
14913 last_frame_pos
= tng_min_i64(n_frames
,
14914 end_frame_nr
- current_frame_pos
);
14916 n_frames_div
= current_frame_pos
/ *stride_length
;
14917 n_frames_div_2
= (last_frame_pos
% *stride_length
) ?
14918 last_frame_pos
/ *stride_length
+ 1:
14919 last_frame_pos
/ *stride_length
;
14920 n_frames_div_2
= tng_max_i64(1, n_frames_div_2
);
14922 memcpy(((char *)*values
) + n_frames_div
* frame_size
,
14924 n_frames_div_2
* frame_size
);
14926 current_frame_pos
+= n_frames
;
14932 free(current_values
);
14935 data
->last_retrieved_frame
= end_frame_nr
;
14937 return(TNG_SUCCESS
);
14941 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14942 (const tng_trajectory_t tng_data
,
14943 const int64_t block_id
,
14944 const int64_t start_frame_nr
,
14945 const int64_t end_frame_nr
,
14946 const char hash_mode
,
14948 int64_t *stride_length
,
14949 int64_t *n_values_per_frame
,
14952 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14953 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14954 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
14955 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
14956 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
14958 return(tng_gen_data_vector_interval_get(tng_data
, block_id
, TNG_FALSE
,
14959 start_frame_nr
, end_frame_nr
,
14960 hash_mode
, values
, 0, stride_length
,
14961 n_values_per_frame
, type
));
14964 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
14965 (const tng_trajectory_t tng_data
,
14966 const int64_t block_id
,
14967 union data_values
****values
,
14969 int64_t *n_particles
,
14970 int64_t *n_values_per_frame
,
14973 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14974 TNG_ASSERT(n_frames
, "TNG library: n_frames must not be a NULL pointer.");
14975 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
14976 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
14977 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
14979 return(tng_gen_data_get(tng_data
, block_id
, TNG_TRUE
, values
, n_frames
, n_particles
,
14980 n_values_per_frame
, type
));
14983 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
14984 (const tng_trajectory_t tng_data
,
14985 const int64_t block_id
,
14988 int64_t *stride_length
,
14989 int64_t *n_particles
,
14990 int64_t *n_values_per_frame
,
14993 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14994 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
14995 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
14996 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
14997 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
14999 return(tng_gen_data_vector_get(tng_data
, block_id
, TNG_TRUE
, values
,
15000 n_frames
, stride_length
, n_particles
,
15001 n_values_per_frame
, type
));
15004 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15005 (const tng_trajectory_t tng_data
,
15006 const int64_t block_id
,
15007 const int64_t start_frame_nr
,
15008 const int64_t end_frame_nr
,
15009 const char hash_mode
,
15010 union data_values
****values
,
15011 int64_t *n_particles
,
15012 int64_t *n_values_per_frame
,
15015 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15016 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15017 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
15018 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15019 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15021 return(tng_gen_data_interval_get(tng_data
, block_id
, TNG_TRUE
, start_frame_nr
,
15022 end_frame_nr
, hash_mode
, values
, n_particles
,
15023 n_values_per_frame
, type
));
15026 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15027 (const tng_trajectory_t tng_data
,
15028 const int64_t block_id
,
15029 const int64_t start_frame_nr
,
15030 const int64_t end_frame_nr
,
15031 const char hash_mode
,
15033 int64_t *n_particles
,
15034 int64_t *stride_length
,
15035 int64_t *n_values_per_frame
,
15038 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15039 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15040 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
15041 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
15042 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15043 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15045 return(tng_gen_data_vector_interval_get(tng_data
, block_id
, TNG_TRUE
,
15046 start_frame_nr
, end_frame_nr
,
15047 hash_mode
, values
, n_particles
,
15048 stride_length
, n_values_per_frame
,
15052 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15053 (const tng_trajectory_t tng_data
,
15054 const int64_t block_id
,
15056 int64_t *stride_length
)
15058 tng_function_status stat
;
15060 int64_t orig_file_pos
, file_pos
;
15061 int is_particle_data
;
15063 if(tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
15070 stat
= tng_frame_set_of_frame_find(tng_data
, frame
);
15071 if(stat
!= TNG_SUCCESS
)
15076 orig_file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
15077 stat
= tng_data_find(tng_data
, block_id
, &data
);
15078 if(stat
!= TNG_SUCCESS
)
15080 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
15081 if(stat
!= TNG_SUCCESS
)
15083 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15084 /* If no specific frame was required read until this data block is found */
15087 file_pos
= ftello(tng_data
->input_file
);
15088 while(stat
!= TNG_SUCCESS
&& file_pos
< tng_data
->input_file_len
)
15090 stat
= tng_frame_set_read_next_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15091 file_pos
= ftello(tng_data
->input_file
);
15094 if(stat
!= TNG_SUCCESS
)
15096 tng_reread_frame_set_at_file_pos(tng_data
, orig_file_pos
);
15100 stat
= tng_data_find(tng_data
, block_id
, &data
);
15101 if(stat
!= TNG_SUCCESS
)
15103 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
15104 if(stat
!= TNG_SUCCESS
)
15106 tng_reread_frame_set_at_file_pos(tng_data
, orig_file_pos
);
15112 is_particle_data
= 1;
15117 is_particle_data
= 0;
15122 is_particle_data
= 1;
15127 is_particle_data
= 0;
15129 if(is_particle_data
)
15131 *stride_length
= data
->stride_length
;
15135 *stride_length
= data
->stride_length
;
15137 tng_reread_frame_set_at_file_pos(tng_data
, orig_file_pos
);
15139 return(TNG_SUCCESS
);
15142 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
15143 (const tng_trajectory_t tng_data
,
15146 struct tm
*time_data
;
15149 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15150 TNG_ASSERT(time
, "TNG library: time must not be a NULL pointer");
15152 secs
= tng_data
->time
;
15154 time_data
= localtime(&secs
); /* Returns a statically allocated variable. */
15155 TNG_SNPRINTF(time
, TNG_MAX_DATE_STR_LEN
,
15156 "%4d-%02d-%02d %02d:%02d:%02d",
15157 time_data
->tm_year
+1900, time_data
->tm_mon
+1, time_data
->tm_mday
,
15158 time_data
->tm_hour
, time_data
->tm_min
, time_data
->tm_sec
);
15160 return(TNG_SUCCESS
);
15164 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
15165 (const char *filename
,
15167 tng_trajectory_t
*tng_data_p
)
15169 tng_function_status stat
;
15171 TNG_ASSERT(filename
, "TNG library: filename must not be a NULL pointer.");
15173 if(mode
!= 'r' && mode
!= 'w' && mode
!= 'a')
15175 return(TNG_FAILURE
);
15178 if(tng_trajectory_init(tng_data_p
) != TNG_SUCCESS
)
15180 tng_trajectory_destroy(tng_data_p
);
15181 return(TNG_CRITICAL
);
15186 stat
= tng_output_file_set(*tng_data_p
, filename
);
15189 tng_input_file_set(*tng_data_p
, filename
);
15191 /* Read the file headers */
15192 tng_file_headers_read(*tng_data_p
, TNG_USE_HASH
);
15194 stat
= tng_num_frame_sets_get(*tng_data_p
, &(*tng_data_p
)->n_trajectory_frame_sets
);
15196 if(stat
!= TNG_SUCCESS
)
15203 if((*tng_data_p
)->output_file
)
15205 fclose((*tng_data_p
)->output_file
);
15207 (*tng_data_p
)->output_file
= (*tng_data_p
)->input_file
;
15208 fseeko((*tng_data_p
)->input_file
,
15209 (*tng_data_p
)->last_trajectory_frame_set_input_file_pos
,
15212 stat
= tng_frame_set_read(*tng_data_p
, TNG_USE_HASH
);
15213 if(stat
!= TNG_SUCCESS
)
15215 fprintf(stderr
, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
15216 __FILE__
, __LINE__
);
15218 (*tng_data_p
)->output_file
= 0;
15220 (*tng_data_p
)->first_trajectory_frame_set_output_file_pos
=
15221 (*tng_data_p
)->first_trajectory_frame_set_input_file_pos
;
15222 (*tng_data_p
)->last_trajectory_frame_set_output_file_pos
=
15223 (*tng_data_p
)->last_trajectory_frame_set_input_file_pos
;
15224 (*tng_data_p
)->current_trajectory_frame_set_output_file_pos
=
15225 (*tng_data_p
)->current_trajectory_frame_set_input_file_pos
;
15226 if((*tng_data_p
)->input_file
)
15228 fclose((*tng_data_p
)->input_file
);
15229 (*tng_data_p
)->input_file
= 0;
15231 if((*tng_data_p
)->input_file_path
)
15233 free((*tng_data_p
)->input_file_path
);
15234 (*tng_data_p
)->input_file_path
= 0;
15236 tng_output_append_file_set(*tng_data_p
, filename
);
15238 fseeko((*tng_data_p
)->output_file
, 0, SEEK_END
);
15240 (*tng_data_p
)->output_endianness_swap_func_32
= (*tng_data_p
)->input_endianness_swap_func_32
;
15241 (*tng_data_p
)->output_endianness_swap_func_64
= (*tng_data_p
)->input_endianness_swap_func_64
;
15247 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
15248 (tng_trajectory_t
*tng_data_p
)
15250 tng_trajectory_frame_set_t frame_set
;
15252 if(tng_data_p
== 0)
15254 fprintf(stderr
, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
15255 __FILE__
, __LINE__
);
15256 return(TNG_FAILURE
);
15259 if(*tng_data_p
== 0)
15261 return(TNG_SUCCESS
);
15264 frame_set
= &(*tng_data_p
)->current_trajectory_frame_set
;
15266 if(frame_set
->n_unwritten_frames
> 0)
15268 frame_set
->n_frames
= frame_set
->n_unwritten_frames
;
15269 tng_frame_set_write(*tng_data_p
, TNG_USE_HASH
);
15272 return(tng_trajectory_destroy(tng_data_p
));
15275 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
15276 (const tng_trajectory_t tng_data
,
15277 const int64_t frame_nr
,
15280 int64_t first_frame
;
15281 tng_trajectory_frame_set_t frame_set
;
15282 tng_function_status stat
;
15284 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15285 TNG_ASSERT(time
, "TNG library: time must not be a NULL pointer");
15287 stat
= tng_frame_set_of_frame_find(tng_data
, frame_nr
);
15288 if(stat
!= TNG_SUCCESS
)
15290 fprintf(stderr
, "TNG library: Cannot find frame nr %" PRId64
". %s: %d\n",
15291 frame_nr
, __FILE__
, __LINE__
);
15295 frame_set
= &tng_data
->current_trajectory_frame_set
;
15296 first_frame
= frame_set
->first_frame
;
15298 if(tng_data
->time_per_frame
<= 0)
15300 return(TNG_FAILURE
);
15303 *time
= frame_set
->first_frame_time
+ (tng_data
->time_per_frame
* (frame_nr
- first_frame
));
15305 return(TNG_SUCCESS
);
15309 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
15310 (const tng_trajectory_t tng_data,
15312 int64_t **molecule_cnt_list,
15313 tng_molecule_t *mols)
15315 tng_trajectory_frame_set_t frame_set;
15317 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15318 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
15320 *n_mols = tng_data->n_molecules;
15322 frame_set = &tng_data->current_trajectory_frame_set;
15323 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
15325 *molecule_cnt_list = frame_set->molecule_cnt_list;
15329 *molecule_cnt_list = tng_data->molecule_cnt_list;
15332 *mols = tng_data->molecules;
15334 return(TNG_SUCCESS);
15338 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
15339 (const tng_trajectory_t tng_data,
15342 tng_molecule_t *mol)
15344 tng_function_status stat;
15346 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
15347 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
15349 stat = tng_molecule_add(tng_data, name, mol);
15350 if(stat != TNG_SUCCESS)
15354 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
15359 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
15360 (const tng_trajectory_t tng_data
,
15361 const tng_molecule_t mol
,
15362 int64_t *n_particles
,
15367 char ***chain_names
,
15368 int64_t **chain_ids
)
15376 *n_particles
= mol
->n_atoms
;
15378 *names
= (char **)malloc(sizeof(char *) * *n_particles
);
15379 *types
= (char **)malloc(sizeof(char *) * *n_particles
);
15380 *res_names
= (char **)malloc(sizeof(char *) * *n_particles
);
15381 *chain_names
= (char **)malloc(sizeof(char *) * *n_particles
);
15382 *res_ids
= (int64_t *)malloc(sizeof(int64_t) * *n_particles
);
15383 *chain_ids
= (int64_t *)malloc(sizeof(int64_t) * *n_particles
);
15385 for(i
= 0; i
< *n_particles
; i
++)
15387 atom
= &mol
->atoms
[i
];
15388 res
= atom
->residue
;
15389 chain
= res
->chain
;
15390 (*names
)[i
] = (char *)malloc(strlen(atom
->name
));
15391 strcpy(*names
[i
], atom
->name
);
15392 (*types
)[i
] = (char *)malloc(strlen(atom
->atom_type
));
15393 strcpy(*types
[i
], atom
->atom_type
);
15394 (*res_names
)[i
] = (char *)malloc(strlen(res
->name
));
15395 strcpy(*res_names
[i
], res
->name
);
15396 (*chain_names
)[i
] = (char *)malloc(strlen(chain
->name
));
15397 strcpy(*chain_names
[i
], chain
->name
);
15398 (*res_ids
)[i
] = res
->id
;
15399 (*chain_ids
)[i
] = chain
->id
;
15402 return(TNG_SUCCESS
);
15405 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
15406 (const tng_trajectory_t tng_data
,
15407 const tng_molecule_t mol
,
15408 const int64_t n_particles
,
15409 const char **names
,
15410 const char **types
,
15411 const char **res_names
,
15412 const int64_t *res_ids
,
15413 const char **chain_names
,
15414 const int64_t *chain_ids
)
15418 tng_residue_t residue
;
15420 tng_function_status stat
;
15422 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15423 TNG_ASSERT(names
, "TNG library: names must not be a NULL pointer");
15424 TNG_ASSERT(types
, "TNG library: types must not be a NULL pointer");
15425 TNG_ASSERT(res_names
, "TNG library: res_names must not be a NULL pointer");
15426 TNG_ASSERT(res_ids
, "TNG library: res_ids must not be a NULL pointer");
15427 TNG_ASSERT(chain_names
, "TNG library: chain_names must not be a NULL pointer");
15428 TNG_ASSERT(chain_ids
, "TNG library: chain_ids must not be a NULL pointer");
15430 for(i
= 0; i
< n_particles
; i
++)
15432 if(tng_molecule_chain_find(tng_data
, mol
, chain_names
[i
], chain_ids
[i
],
15433 &chain
) == TNG_FAILURE
)
15435 stat
= tng_molecule_chain_add(tng_data
, mol
, chain_names
[i
],
15437 if(stat
!= TNG_SUCCESS
)
15442 if(tng_chain_residue_find(tng_data
, chain
, res_names
[i
], res_ids
[i
],
15443 &residue
) == TNG_FAILURE
)
15445 stat
= tng_chain_residue_add(tng_data
, chain
, res_names
[i
],
15447 if(stat
!= TNG_SUCCESS
)
15452 stat
= tng_residue_atom_add(tng_data
, residue
, names
[i
], types
[i
], &atom
);
15453 if(stat
!= TNG_SUCCESS
)
15458 return(TNG_SUCCESS
);
15461 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
15462 (const tng_trajectory_t tng_data
,
15463 float **positions
, int64_t *stride_length
)
15465 int64_t n_frames
, n_particles
, n_values_per_frame
;
15467 tng_function_status stat
;
15469 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15470 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
15471 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
15473 stat
= tng_num_frames_get(tng_data
, &n_frames
);
15474 if(stat
!= TNG_SUCCESS
)
15479 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_POSITIONS
,
15480 0, n_frames
- 1, TNG_USE_HASH
,
15481 (void **)positions
,
15484 &n_values_per_frame
,
15487 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
15489 return(TNG_FAILURE
);
15495 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
15496 (const tng_trajectory_t tng_data
,
15497 float **velocities
, int64_t *stride_length
)
15499 int64_t n_frames
, n_particles
, n_values_per_frame
;
15501 tng_function_status stat
;
15503 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15504 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
15505 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
15507 stat
= tng_num_frames_get(tng_data
, &n_frames
);
15508 if(stat
!= TNG_SUCCESS
)
15513 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_VELOCITIES
,
15514 0, n_frames
- 1, TNG_USE_HASH
,
15515 (void **)velocities
,
15518 &n_values_per_frame
,
15521 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
15523 return(TNG_FAILURE
);
15529 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
15530 (const tng_trajectory_t tng_data
,
15531 float **forces
, int64_t *stride_length
)
15533 int64_t n_frames
, n_particles
, n_values_per_frame
;
15535 tng_function_status stat
;
15537 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15538 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
15539 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
15541 stat
= tng_num_frames_get(tng_data
, &n_frames
);
15542 if(stat
!= TNG_SUCCESS
)
15547 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_FORCES
,
15548 0, n_frames
- 1, TNG_USE_HASH
,
15552 &n_values_per_frame
,
15555 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
15557 return(TNG_FAILURE
);
15563 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
15564 (const tng_trajectory_t tng_data
,
15566 int64_t *stride_length
)
15568 int64_t n_frames
, n_values_per_frame
;
15570 tng_function_status stat
;
15572 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15573 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
15574 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
15576 stat
= tng_num_frames_get(tng_data
, &n_frames
);
15577 if(stat
!= TNG_SUCCESS
)
15582 stat
= tng_data_vector_interval_get(tng_data
, TNG_TRAJ_BOX_SHAPE
,
15583 0, n_frames
- 1, TNG_USE_HASH
,
15584 (void **)box_shape
,
15586 &n_values_per_frame
,
15589 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
15591 return(TNG_FAILURE
);
15597 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
15598 (const tng_trajectory_t tng_data
,
15599 const int64_t block_id
,
15602 int64_t *retrieved_frame_number
,
15603 double *retrieved_time
)
15605 tng_trajectory_frame_set_t frame_set
;
15606 tng_data_t data
= 0;
15607 tng_function_status stat
;
15609 int64_t i
, full_data_len
, n_particles
;
15613 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15614 TNG_ASSERT(values
, "TNG library: The pointer to the values array must not be a NULL pointer");
15615 TNG_ASSERT(data_type
, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15616 TNG_ASSERT(retrieved_frame_number
, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15617 TNG_ASSERT(retrieved_time
, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15619 frame_set
= &tng_data
->current_trajectory_frame_set
;
15621 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
15622 if(stat
!= TNG_SUCCESS
)
15624 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15625 file_pos
= ftello(tng_data
->input_file
);
15626 while(stat
!= TNG_SUCCESS
&& file_pos
< tng_data
->input_file_len
)
15628 stat
= tng_frame_set_read_next_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15629 file_pos
= ftello(tng_data
->input_file
);
15631 if(stat
!= TNG_SUCCESS
)
15635 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
15636 if(stat
!= TNG_SUCCESS
)
15641 if(data
->last_retrieved_frame
< 0)
15643 fseeko(tng_data
->input_file
,
15644 tng_data
->first_trajectory_frame_set_input_file_pos
,
15646 stat
= tng_frame_set_read(tng_data
, TNG_USE_HASH
);
15647 if(stat
!= TNG_SUCCESS
)
15651 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15652 if(stat
!= TNG_SUCCESS
)
15657 i
= data
->first_frame_with_data
;
15661 if(data
->n_frames
== 1 && frame_set
->n_frames
== 1)
15663 i
= data
->last_retrieved_frame
+ 1;
15667 i
= data
->last_retrieved_frame
+ data
->stride_length
;
15669 if(i
< frame_set
->first_frame
|| i
>= frame_set
->first_frame
+ frame_set
->n_frames
)
15671 stat
= tng_frame_set_of_frame_find(tng_data
, i
);
15672 if(stat
!= TNG_SUCCESS
)
15674 /* If the frame set search found the frame set after the starting
15675 * frame set there is a gap in the frame sets. So, even if the frame
15676 * was not found the next frame with data is still in the found
15678 if(stat
== TNG_CRITICAL
)
15682 if(frame_set
->first_frame
+ frame_set
->n_frames
- 1 < i
)
15684 return(TNG_FAILURE
);
15686 i
= frame_set
->first_frame
;
15689 if(data
->last_retrieved_frame
< frame_set
->first_frame
)
15691 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15692 if(stat
!= TNG_SUCCESS
)
15698 data
->last_retrieved_frame
= i
;
15699 *retrieved_frame_number
= i
;
15700 if(frame_set
->first_frame_time
>= 0 && tng_data
->time_per_frame
>= 0)
15702 *retrieved_time
= frame_set
->first_frame_time
+
15703 (i
- frame_set
->first_frame
) *
15704 tng_data
->time_per_frame
;
15708 *retrieved_time
= 0;
15711 if(data
->stride_length
> 1)
15713 i
= (i
- data
->first_frame_with_data
) / data
->stride_length
;
15717 i
= (i
- frame_set
->first_frame
);
15720 tng_num_particles_get(tng_data
, &n_particles
);
15722 *data_type
= data
->datatype
;
15726 case TNG_CHAR_DATA
:
15727 return(TNG_FAILURE
);
15729 size
= sizeof(int64_t);
15731 case TNG_FLOAT_DATA
:
15732 size
= sizeof(float);
15734 case TNG_DOUBLE_DATA
:
15736 size
= sizeof(double);
15739 full_data_len
= size
* n_particles
* data
->n_values_per_frame
;
15741 // fprintf(stderr, "TNG library: TEMP: i = %" PRId64 ", full_data_len = %" PRId64 ", size = %d, n_particles = %" PRId64 ", n_values_per_frame = %" PRId64 "\n",
15742 // i, full_data_len, size, n_particles, data->n_values_per_frame);
15744 temp
= (char *)realloc(*values
, full_data_len
);
15747 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
15748 __FILE__
, __LINE__
);
15751 return(TNG_CRITICAL
);
15756 memcpy(*values
, (char *)data
->values
+ i
* full_data_len
, full_data_len
);
15758 return(TNG_SUCCESS
);
15761 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
15762 (const tng_trajectory_t tng_data
,
15763 const int64_t block_id
,
15766 int64_t *retrieved_frame_number
,
15767 double *retrieved_time
)
15769 tng_trajectory_frame_set_t frame_set
;
15770 tng_data_t data
= 0;
15771 tng_function_status stat
;
15773 int64_t i
, full_data_len
;
15777 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15778 TNG_ASSERT(values
, "TNG library: The pointer to the values array must not be a NULL pointer");
15779 TNG_ASSERT(data_type
, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15780 TNG_ASSERT(retrieved_frame_number
, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15781 TNG_ASSERT(retrieved_time
, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15783 frame_set
= &tng_data
->current_trajectory_frame_set
;
15785 stat
= tng_data_find(tng_data
, block_id
, &data
);
15786 if(stat
!= TNG_SUCCESS
)
15788 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15789 file_pos
= ftello(tng_data
->input_file
);
15790 while(stat
!= TNG_SUCCESS
&& file_pos
< tng_data
->input_file_len
)
15792 stat
= tng_frame_set_read_next_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15793 file_pos
= ftello(tng_data
->input_file
);
15795 if(stat
!= TNG_SUCCESS
)
15799 stat
= tng_data_find(tng_data
, block_id
, &data
);
15800 if(stat
!= TNG_SUCCESS
)
15805 if(data
->last_retrieved_frame
< 0)
15807 fseeko(tng_data
->input_file
,
15808 tng_data
->first_trajectory_frame_set_input_file_pos
,
15810 stat
= tng_frame_set_read(tng_data
, TNG_USE_HASH
);
15811 if(stat
!= TNG_SUCCESS
)
15815 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15816 if(stat
!= TNG_SUCCESS
)
15821 i
= data
->first_frame_with_data
;
15825 if(data
->n_frames
== 1 && frame_set
->n_frames
== 1)
15827 i
= data
->last_retrieved_frame
+ 1;
15831 i
= data
->last_retrieved_frame
+ data
->stride_length
;
15833 if(i
< frame_set
->first_frame
|| i
>= frame_set
->first_frame
+ frame_set
->n_frames
)
15835 stat
= tng_frame_set_of_frame_find(tng_data
, i
);
15836 if(stat
!= TNG_SUCCESS
)
15838 /* If the frame set search found the frame set after the starting
15839 * frame set there is a gap in the frame sets. So, even if the frame
15840 * was not found the next frame with data is still in the found
15842 if(stat
== TNG_CRITICAL
)
15846 if(frame_set
->first_frame
+ frame_set
->n_frames
- 1 < i
)
15848 return(TNG_FAILURE
);
15850 i
= frame_set
->first_frame
;
15853 if(data
->last_retrieved_frame
< frame_set
->first_frame
)
15855 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
15856 if(stat
!= TNG_SUCCESS
)
15862 data
->last_retrieved_frame
= i
;
15863 *retrieved_frame_number
= i
;
15864 if(frame_set
->first_frame_time
>= 0 && tng_data
->time_per_frame
>= 0)
15866 *retrieved_time
= frame_set
->first_frame_time
+
15867 (i
- frame_set
->first_frame
) *
15868 tng_data
->time_per_frame
;
15872 *retrieved_time
= 0;
15875 if(data
->stride_length
> 1)
15877 i
= (i
- data
->first_frame_with_data
) / data
->stride_length
;
15881 i
= (i
- frame_set
->first_frame
);
15884 *data_type
= data
->datatype
;
15888 case TNG_CHAR_DATA
:
15889 return(TNG_FAILURE
);
15891 size
= sizeof(int64_t);
15893 case TNG_FLOAT_DATA
:
15894 size
= sizeof(float);
15896 case TNG_DOUBLE_DATA
:
15898 size
= sizeof(double);
15901 full_data_len
= size
* data
->n_values_per_frame
;
15903 temp
= (char *)realloc(*values
, full_data_len
);
15906 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
15907 __FILE__
, __LINE__
);
15910 return(TNG_CRITICAL
);
15915 memcpy(*values
, (char *)data
->values
+ i
* full_data_len
, full_data_len
);
15917 return(TNG_SUCCESS
);
15920 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
15921 (const tng_trajectory_t tng_data
,
15922 const int64_t first_frame
,
15923 const int64_t last_frame
,
15925 int64_t *stride_length
)
15927 int64_t n_particles
, n_values_per_frame
;
15929 tng_function_status stat
;
15931 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15932 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
15933 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
15934 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
15936 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_POSITIONS
,
15937 first_frame
, last_frame
,
15939 (void **)positions
,
15942 &n_values_per_frame
,
15945 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
15947 return(TNG_FAILURE
);
15953 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
15954 (const tng_trajectory_t tng_data
,
15955 const int64_t first_frame
,
15956 const int64_t last_frame
,
15957 float **velocities
,
15958 int64_t *stride_length
)
15960 int64_t n_particles
, n_values_per_frame
;
15962 tng_function_status stat
;
15964 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15965 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
15966 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
15967 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
15969 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_VELOCITIES
,
15970 first_frame
, last_frame
,
15972 (void **)velocities
,
15975 &n_values_per_frame
,
15978 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
15980 return(TNG_FAILURE
);
15986 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
15987 (const tng_trajectory_t tng_data
,
15988 const int64_t first_frame
,
15989 const int64_t last_frame
,
15991 int64_t *stride_length
)
15993 int64_t n_particles
, n_values_per_frame
;
15995 tng_function_status stat
;
15997 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15998 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
15999 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
16000 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
16002 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_FORCES
,
16003 first_frame
, last_frame
,
16008 &n_values_per_frame
,
16011 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
16013 return(TNG_FAILURE
);
16019 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16020 (const tng_trajectory_t tng_data
,
16021 const int64_t first_frame
,
16022 const int64_t last_frame
,
16024 int64_t *stride_length
)
16026 int64_t n_values_per_frame
;
16028 tng_function_status stat
;
16030 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16031 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
16032 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
16033 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
16035 stat
= tng_data_vector_interval_get(tng_data
, TNG_TRAJ_BOX_SHAPE
,
16036 first_frame
, last_frame
,
16038 (void **)box_shape
,
16040 &n_values_per_frame
,
16043 if(stat
== TNG_SUCCESS
&& type
!= TNG_FLOAT_DATA
)
16045 return(TNG_FAILURE
);
16051 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16052 (const tng_trajectory_t tng_data
,
16054 const int64_t n_values_per_frame
,
16055 const int64_t block_id
,
16056 const char *block_name
,
16057 const char particle_dependency
,
16058 const char compression
)
16060 tng_trajectory_frame_set_t frame_set
;
16062 int64_t n_particles
, n_frames
;
16063 tng_function_status stat
;
16065 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16066 TNG_ASSERT(i
>= 0, "TNG library: i (writing interval) must be >= 0.");
16070 fprintf(stderr
, "TNG library: Cannot set writing frequency to %" PRId64
". %s: %d\n",
16071 i
, __FILE__
, __LINE__
);
16072 return(TNG_FAILURE
);
16075 frame_set
= &tng_data
->current_trajectory_frame_set
;
16077 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
16079 n_frames
= tng_data
->frame_set_n_frames
;
16081 stat
= tng_frame_set_new(tng_data
, 0, n_frames
);
16082 if(stat
!= TNG_SUCCESS
)
16084 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
16091 n_frames
= frame_set
->n_frames
;
16094 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
16096 tng_num_particles_get(tng_data
, &n_particles
);
16097 if(n_particles
<= 0)
16099 return(TNG_FAILURE
);
16102 if(tng_particle_data_find(tng_data
, block_id
, &data
)
16105 stat
= tng_particle_data_block_add(tng_data
, block_id
,
16108 TNG_TRAJECTORY_BLOCK
,
16109 n_frames
, n_values_per_frame
, i
,
16112 if(stat
!= TNG_SUCCESS
)
16114 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16115 __FILE__
, __LINE__
);
16118 data
= &frame_set
->tr_particle_data
[frame_set
->
16119 n_particle_data_blocks
- 1];
16120 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16122 n_values_per_frame
);
16123 if(stat
!= TNG_SUCCESS
)
16125 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16126 __FILE__
, __LINE__
);
16132 if(data
->stride_length
!= i
)
16134 data
->stride_length
= i
;
16135 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16137 n_values_per_frame
);
16138 if(stat
!= TNG_SUCCESS
)
16140 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16141 __FILE__
, __LINE__
);
16149 if(tng_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
16151 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
16152 TNG_FLOAT_DATA
, TNG_TRAJECTORY_BLOCK
,
16153 n_frames
, n_values_per_frame
,
16154 i
, compression
, 0);
16155 if(stat
!= TNG_SUCCESS
)
16157 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16158 __FILE__
, __LINE__
);
16161 data
= &frame_set
->tr_data
[frame_set
->
16162 n_data_blocks
- 1];
16163 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16164 i
, n_values_per_frame
);
16165 if(stat
!= TNG_SUCCESS
)
16167 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16168 __FILE__
, __LINE__
);
16174 if(data
->stride_length
!= i
)
16176 data
->stride_length
= i
;
16177 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16178 i
, n_values_per_frame
);
16179 if(stat
!= TNG_SUCCESS
)
16181 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16182 __FILE__
, __LINE__
);
16189 return(TNG_SUCCESS
);
16192 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
16193 (const tng_trajectory_t tng_data
,
16195 const int64_t n_values_per_frame
,
16196 const int64_t block_id
,
16197 const char *block_name
,
16198 const char particle_dependency
,
16199 const char compression
)
16201 tng_trajectory_frame_set_t frame_set
;
16203 int64_t n_particles
, n_frames
;
16204 tng_function_status stat
;
16206 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16207 TNG_ASSERT(i
>= 0, "TNG library: i (writing interval) must be >= 0.");
16211 fprintf(stderr
, "TNG library: Cannot set writing frequency to %" PRId64
". %s: %d\n",
16212 i
, __FILE__
, __LINE__
);
16213 return(TNG_FAILURE
);
16216 frame_set
= &tng_data
->current_trajectory_frame_set
;
16218 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
16220 n_frames
= tng_data
->frame_set_n_frames
;
16222 stat
= tng_frame_set_new(tng_data
, 0, n_frames
);
16223 if(stat
!= TNG_SUCCESS
)
16225 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
16232 n_frames
= frame_set
->n_frames
;
16235 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
16237 tng_num_particles_get(tng_data
, &n_particles
);
16239 if(n_particles
<= 0)
16241 return(TNG_FAILURE
);
16244 if(tng_particle_data_find(tng_data
, block_id
, &data
)
16247 stat
= tng_particle_data_block_add(tng_data
, block_id
,
16250 TNG_TRAJECTORY_BLOCK
,
16251 n_frames
, n_values_per_frame
, i
,
16254 if(stat
!= TNG_SUCCESS
)
16256 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16257 __FILE__
, __LINE__
);
16260 data
= &frame_set
->tr_particle_data
[frame_set
->
16261 n_particle_data_blocks
- 1];
16262 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16264 n_values_per_frame
);
16265 if(stat
!= TNG_SUCCESS
)
16267 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16268 __FILE__
, __LINE__
);
16274 data
->stride_length
= i
;
16279 if(tng_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
16281 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
16282 TNG_DOUBLE_DATA
, TNG_TRAJECTORY_BLOCK
,
16283 n_frames
, n_values_per_frame
,
16284 i
, compression
, 0);
16285 if(stat
!= TNG_SUCCESS
)
16287 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16288 __FILE__
, __LINE__
);
16291 data
= &frame_set
->tr_data
[frame_set
->
16292 n_data_blocks
- 1];
16293 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16294 i
, n_values_per_frame
);
16295 if(stat
!= TNG_SUCCESS
)
16297 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16298 __FILE__
, __LINE__
);
16304 data
->stride_length
= i
;
16308 return(TNG_SUCCESS
);
16311 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
16312 (const tng_trajectory_t tng_data
,
16314 const int64_t n_values_per_frame
,
16315 const int64_t block_id
,
16316 const char *block_name
,
16317 const char particle_dependency
,
16318 const char compression
)
16320 fprintf(stderr
, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
16321 "See documentation. %s: %d", __FILE__
, __LINE__
);
16322 return(tng_util_generic_write_interval_set(tng_data
, i
, n_values_per_frame
,
16323 block_id
, block_name
,
16324 particle_dependency
,
16327 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
16328 (const tng_trajectory_t tng_data
,
16331 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16332 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16334 return(tng_util_generic_write_interval_set(tng_data
, i
, 3,
16335 TNG_TRAJ_POSITIONS
,
16337 TNG_PARTICLE_BLOCK_DATA
,
16338 TNG_TNG_COMPRESSION
));
16341 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
16342 (const tng_trajectory_t tng_data
,
16345 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16346 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16348 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 3,
16349 TNG_TRAJ_POSITIONS
,
16351 TNG_PARTICLE_BLOCK_DATA
,
16352 TNG_TNG_COMPRESSION
));
16355 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
16356 (const tng_trajectory_t tng_data
,
16359 fprintf(stderr
, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
16360 "See documentation. %s: %d", __FILE__
, __LINE__
);
16361 return(tng_util_pos_write_interval_set(tng_data
, i
));
16364 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
16365 (const tng_trajectory_t tng_data
,
16368 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16369 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16371 return(tng_util_generic_write_interval_set(tng_data
, i
, 3,
16372 TNG_TRAJ_VELOCITIES
,
16374 TNG_PARTICLE_BLOCK_DATA
,
16375 TNG_TNG_COMPRESSION
));
16378 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
16379 (const tng_trajectory_t tng_data
,
16382 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16383 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16385 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 3,
16386 TNG_TRAJ_VELOCITIES
,
16388 TNG_PARTICLE_BLOCK_DATA
,
16389 TNG_TNG_COMPRESSION
));
16392 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
16393 (const tng_trajectory_t tng_data
,
16396 fprintf(stderr
, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
16397 "See documentation. %s: %d", __FILE__
, __LINE__
);
16398 return(tng_util_vel_write_interval_set(tng_data
, i
));
16401 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
16402 (const tng_trajectory_t tng_data
,
16405 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16406 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16408 return(tng_util_generic_write_interval_set(tng_data
, i
, 3,
16411 TNG_PARTICLE_BLOCK_DATA
,
16412 TNG_GZIP_COMPRESSION
));
16415 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
16416 (const tng_trajectory_t tng_data
,
16419 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16420 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16422 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 3,
16425 TNG_PARTICLE_BLOCK_DATA
,
16426 TNG_GZIP_COMPRESSION
));
16429 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
16430 (const tng_trajectory_t tng_data
,
16433 fprintf(stderr
, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
16434 "See documentation. %s: %d", __FILE__
, __LINE__
);
16435 return(tng_util_force_write_interval_set(tng_data
, i
));
16438 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
16439 (const tng_trajectory_t tng_data
,
16442 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16443 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16445 return(tng_util_generic_write_interval_set(tng_data
, i
, 9,
16446 TNG_TRAJ_BOX_SHAPE
,
16448 TNG_NON_PARTICLE_BLOCK_DATA
,
16449 TNG_GZIP_COMPRESSION
));
16452 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
16453 (const tng_trajectory_t tng_data
,
16456 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16457 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
16459 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 9,
16460 TNG_TRAJ_BOX_SHAPE
,
16462 TNG_NON_PARTICLE_BLOCK_DATA
,
16463 TNG_GZIP_COMPRESSION
));
16466 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
16467 (const tng_trajectory_t tng_data
,
16470 fprintf(stderr
, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
16471 "See documentation. %s: %d", __FILE__
, __LINE__
);
16472 return(tng_util_box_shape_write_interval_set(tng_data
, i
));
16475 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
16476 (const tng_trajectory_t tng_data
,
16477 const int64_t frame_nr
,
16478 const float *values
,
16479 const int64_t n_values_per_frame
,
16480 const int64_t block_id
,
16481 const char *block_name
,
16482 const char particle_dependency
,
16483 const char compression
)
16485 tng_trajectory_frame_set_t frame_set
;
16487 int64_t n_particles
= 0, n_frames
, stride_length
= 100, frame_pos
;
16488 int64_t last_frame
;
16489 int is_first_frame_flag
= 0;
16490 char block_type_flag
;
16491 tng_function_status stat
;
16493 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16494 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
16496 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
16498 tng_num_particles_get(tng_data
, &n_particles
);
16499 TNG_ASSERT(n_particles
> 0, "TNG library: There must be particles in the system to write particle data.");
16504 return(TNG_FAILURE
);
16507 frame_set
= &tng_data
->current_trajectory_frame_set
;
16511 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
16512 n_frames
= stride_length
= 1;
16516 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
16518 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
16520 stat
= tng_frame_set_new(tng_data
, 0, tng_data
->frame_set_n_frames
);
16521 if(stat
!= TNG_SUCCESS
)
16523 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
16528 last_frame
= frame_set
->first_frame
+
16529 frame_set
->n_frames
- 1;
16530 if(frame_nr
> last_frame
)
16532 stat
= tng_frame_set_write(tng_data
, TNG_USE_HASH
);
16533 if(stat
!= TNG_SUCCESS
)
16535 fprintf(stderr
, "TNG library: Cannot write frame set. %s: %d\n", __FILE__
,
16539 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
16541 last_frame
= frame_nr
- 1;
16543 stat
= tng_frame_set_new(tng_data
, last_frame
+ 1,
16544 tng_data
->frame_set_n_frames
);
16545 if(stat
!= TNG_SUCCESS
)
16547 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
16552 if(frame_set
->n_unwritten_frames
== 0)
16554 is_first_frame_flag
= 1;
16556 frame_set
->n_unwritten_frames
= frame_nr
-
16557 frame_set
->first_frame
+ 1;
16559 n_frames
= frame_set
->n_frames
;
16562 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
16564 if(tng_particle_data_find(tng_data
, block_id
, &data
)
16567 stat
= tng_particle_data_block_add(tng_data
, block_id
,
16571 n_frames
, n_values_per_frame
,
16575 if(stat
!= TNG_SUCCESS
)
16577 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16578 __FILE__
, __LINE__
);
16581 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16583 data
= &frame_set
->tr_particle_data
[frame_set
->
16584 n_particle_data_blocks
- 1];
16588 data
= &tng_data
->non_tr_particle_data
[tng_data
->
16589 n_particle_data_blocks
- 1];
16591 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16592 stride_length
, n_particles
,
16593 n_values_per_frame
);
16594 if(stat
!= TNG_SUCCESS
)
16596 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16597 __FILE__
, __LINE__
);
16601 /* FIXME: Here we must be able to handle modified n_particles as well. */
16602 else if(n_frames
> data
->n_frames
)
16604 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16605 data
->stride_length
, n_particles
,
16606 n_values_per_frame
);
16607 if(stat
!= TNG_SUCCESS
)
16609 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16610 __FILE__
, __LINE__
);
16615 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16617 stride_length
= data
->stride_length
;
16619 if(is_first_frame_flag
|| data
->first_frame_with_data
< frame_set
->first_frame
)
16621 data
->first_frame_with_data
= frame_nr
;
16626 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
16629 memcpy((char *)data
->values
+ sizeof(float) * frame_pos
* n_particles
*
16630 n_values_per_frame
, values
, sizeof(float) *
16631 n_particles
* n_values_per_frame
);
16635 memcpy(data
->values
, values
, sizeof(float) * n_particles
*
16636 n_values_per_frame
);
16641 if(tng_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
16643 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
16644 TNG_FLOAT_DATA
, block_type_flag
,
16645 n_frames
, n_values_per_frame
,
16646 stride_length
, compression
, 0);
16647 if(stat
!= TNG_SUCCESS
)
16649 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16650 __FILE__
, __LINE__
);
16653 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16655 data
= &frame_set
->tr_data
[frame_set
->
16656 n_data_blocks
- 1];
16660 data
= &tng_data
->non_tr_data
[tng_data
->
16661 n_data_blocks
- 1];
16663 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16664 stride_length
, n_values_per_frame
);
16665 if(stat
!= TNG_SUCCESS
)
16667 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16668 __FILE__
, __LINE__
);
16672 /* FIXME: Here we must be able to handle modified n_particles as well. */
16673 else if(n_frames
> data
->n_frames
)
16675 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16676 data
->stride_length
, n_values_per_frame
);
16677 if(stat
!= TNG_SUCCESS
)
16679 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16680 __FILE__
, __LINE__
);
16685 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16687 stride_length
= data
->stride_length
;
16689 if(is_first_frame_flag
|| data
->first_frame_with_data
< frame_set
->first_frame
)
16691 data
->first_frame_with_data
= frame_nr
;
16696 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
16699 memcpy((char *)data
->values
+ sizeof(float) * frame_pos
*
16700 n_values_per_frame
, values
, sizeof(float) *
16701 n_values_per_frame
);
16705 memcpy(data
->values
, values
, sizeof(float) * n_values_per_frame
);
16709 return(TNG_SUCCESS
);
16712 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
16713 (const tng_trajectory_t tng_data
,
16714 const int64_t frame_nr
,
16715 const double *values
,
16716 const int64_t n_values_per_frame
,
16717 const int64_t block_id
,
16718 const char *block_name
,
16719 const char particle_dependency
,
16720 const char compression
)
16722 tng_trajectory_frame_set_t frame_set
;
16724 int64_t n_particles
= 0, n_frames
, stride_length
= 100, frame_pos
;
16725 int64_t last_frame
;
16726 int is_first_frame_flag
= 0;
16727 char block_type_flag
;
16728 tng_function_status stat
;
16730 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16731 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
16733 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
16735 tng_num_particles_get(tng_data
, &n_particles
);
16736 TNG_ASSERT(n_particles
> 0, "TNG library: There must be particles in the system to write particle data.");
16741 return(TNG_FAILURE
);
16744 frame_set
= &tng_data
->current_trajectory_frame_set
;
16748 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
16749 n_frames
= stride_length
= 1;
16753 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
16755 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
16757 stat
= tng_frame_set_new(tng_data
, 0, tng_data
->frame_set_n_frames
);
16758 if(stat
!= TNG_SUCCESS
)
16760 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
16765 last_frame
= frame_set
->first_frame
+
16766 frame_set
->n_frames
- 1;
16767 if(frame_nr
> last_frame
)
16769 stat
= tng_frame_set_write(tng_data
, TNG_USE_HASH
);
16770 if(stat
!= TNG_SUCCESS
)
16772 fprintf(stderr
, "TNG library: Cannot write frame set. %s: %d\n", __FILE__
,
16776 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
16778 last_frame
= frame_nr
- 1;
16780 stat
= tng_frame_set_new(tng_data
, last_frame
+ 1,
16781 tng_data
->frame_set_n_frames
);
16782 if(stat
!= TNG_SUCCESS
)
16784 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
16789 if(frame_set
->n_unwritten_frames
== 0)
16791 is_first_frame_flag
= 1;
16793 frame_set
->n_unwritten_frames
= frame_nr
-
16794 frame_set
->first_frame
+ 1;
16796 n_frames
= frame_set
->n_frames
;
16800 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
16802 if(tng_particle_data_find(tng_data
, block_id
, &data
)
16805 stat
= tng_particle_data_block_add(tng_data
, block_id
,
16809 n_frames
, n_values_per_frame
,
16813 if(stat
!= TNG_SUCCESS
)
16815 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16816 __FILE__
, __LINE__
);
16819 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16821 data
= &frame_set
->tr_particle_data
[frame_set
->
16822 n_particle_data_blocks
- 1];
16826 data
= &tng_data
->non_tr_particle_data
[tng_data
->
16827 n_particle_data_blocks
- 1];
16829 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16830 stride_length
, n_particles
,
16831 n_values_per_frame
);
16832 if(stat
!= TNG_SUCCESS
)
16834 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16835 __FILE__
, __LINE__
);
16839 /* FIXME: Here we must be able to handle modified n_particles as well. */
16840 else if(n_frames
> data
->n_frames
)
16842 stat
= tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
16843 data
->stride_length
, n_particles
,
16844 n_values_per_frame
);
16845 if(stat
!= TNG_SUCCESS
)
16847 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16848 __FILE__
, __LINE__
);
16853 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16855 stride_length
= data
->stride_length
;
16857 if(is_first_frame_flag
|| data
->first_frame_with_data
< frame_set
->first_frame
)
16859 data
->first_frame_with_data
= frame_nr
;
16864 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
16867 memcpy((char *)data
->values
+ sizeof(double) * frame_pos
* n_particles
*
16868 n_values_per_frame
, values
, sizeof(double) *
16869 n_particles
* n_values_per_frame
);
16873 memcpy(data
->values
, values
, sizeof(double) * n_particles
*
16874 n_values_per_frame
);
16879 if(tng_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
16881 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
16882 TNG_DOUBLE_DATA
, block_type_flag
,
16883 n_frames
, n_values_per_frame
,
16884 stride_length
, compression
, 0);
16885 if(stat
!= TNG_SUCCESS
)
16887 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
16888 __FILE__
, __LINE__
);
16891 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16893 data
= &frame_set
->tr_data
[frame_set
->
16894 n_data_blocks
- 1];
16898 data
= &tng_data
->non_tr_data
[tng_data
->
16899 n_data_blocks
- 1];
16901 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16902 stride_length
, n_values_per_frame
);
16903 if(stat
!= TNG_SUCCESS
)
16905 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16906 __FILE__
, __LINE__
);
16910 /* FIXME: Here we must be able to handle modified n_particles as well. */
16911 else if(n_frames
> data
->n_frames
)
16913 stat
= tng_allocate_data_mem(tng_data
, data
, n_frames
,
16914 data
->stride_length
, n_values_per_frame
);
16915 if(stat
!= TNG_SUCCESS
)
16917 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
16918 __FILE__
, __LINE__
);
16923 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
16925 stride_length
= data
->stride_length
;
16927 if(is_first_frame_flag
|| data
->first_frame_with_data
< frame_set
->first_frame
)
16929 data
->first_frame_with_data
= frame_nr
;
16934 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
16937 memcpy((char *)data
->values
+ sizeof(double) * frame_pos
*
16938 n_values_per_frame
, values
, sizeof(double) *
16939 n_values_per_frame
);
16943 memcpy(data
->values
, values
, sizeof(double) * n_values_per_frame
);
16947 return(TNG_SUCCESS
);
16950 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
16951 (const tng_trajectory_t tng_data
,
16952 const int64_t frame_nr
,
16953 const float *positions
)
16955 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16956 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
16958 return(tng_util_generic_write(tng_data
, frame_nr
, positions
, 3,
16959 TNG_TRAJ_POSITIONS
, "POSITIONS",
16960 TNG_PARTICLE_BLOCK_DATA
,
16961 TNG_TNG_COMPRESSION
));
16964 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
16965 (const tng_trajectory_t tng_data
,
16966 const int64_t frame_nr
,
16967 const double *positions
)
16969 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16970 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
16972 return(tng_util_generic_double_write(tng_data
, frame_nr
, positions
, 3,
16973 TNG_TRAJ_POSITIONS
, "POSITIONS",
16974 TNG_PARTICLE_BLOCK_DATA
,
16975 TNG_TNG_COMPRESSION
));
16978 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
16979 (const tng_trajectory_t tng_data
,
16980 const int64_t frame_nr
,
16981 const float *velocities
)
16983 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16984 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
16986 return(tng_util_generic_write(tng_data
, frame_nr
, velocities
, 3,
16987 TNG_TRAJ_VELOCITIES
, "VELOCITIES",
16988 TNG_PARTICLE_BLOCK_DATA
,
16989 TNG_TNG_COMPRESSION
));
16992 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
16993 (const tng_trajectory_t tng_data
,
16994 const int64_t frame_nr
,
16995 const double *velocities
)
16997 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16998 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
17000 return(tng_util_generic_double_write(tng_data
, frame_nr
, velocities
, 3,
17001 TNG_TRAJ_VELOCITIES
, "VELOCITIES",
17002 TNG_PARTICLE_BLOCK_DATA
,
17003 TNG_TNG_COMPRESSION
));
17006 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17007 (const tng_trajectory_t tng_data
,
17008 const int64_t frame_nr
,
17009 const float *forces
)
17011 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17012 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
17014 return(tng_util_generic_write(tng_data
, frame_nr
, forces
, 3,
17015 TNG_TRAJ_FORCES
, "FORCES",
17016 TNG_PARTICLE_BLOCK_DATA
,
17017 TNG_GZIP_COMPRESSION
));
17020 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17021 (const tng_trajectory_t tng_data
,
17022 const int64_t frame_nr
,
17023 const double *forces
)
17025 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17026 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
17028 return(tng_util_generic_double_write(tng_data
, frame_nr
, forces
, 3,
17029 TNG_TRAJ_FORCES
, "FORCES",
17030 TNG_PARTICLE_BLOCK_DATA
,
17031 TNG_GZIP_COMPRESSION
));
17034 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17035 (const tng_trajectory_t tng_data
,
17036 const int64_t frame_nr
,
17037 const float *box_shape
)
17039 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17040 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
17042 return(tng_util_generic_write(tng_data
, frame_nr
, box_shape
, 9,
17043 TNG_TRAJ_BOX_SHAPE
, "BOX SHAPE",
17044 TNG_NON_PARTICLE_BLOCK_DATA
,
17045 TNG_GZIP_COMPRESSION
));
17048 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17049 (const tng_trajectory_t tng_data
,
17050 const int64_t frame_nr
,
17051 const double *box_shape
)
17053 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17054 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
17056 return(tng_util_generic_double_write(tng_data
, frame_nr
, box_shape
, 9,
17057 TNG_TRAJ_BOX_SHAPE
, "BOX SHAPE",
17058 TNG_NON_PARTICLE_BLOCK_DATA
,
17059 TNG_GZIP_COMPRESSION
));
17062 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17063 (const tng_trajectory_t tng_data
,
17064 const int64_t frame_nr
,
17066 const float *values
,
17067 const int64_t n_values_per_frame
,
17068 const int64_t block_id
,
17069 const char *block_name
,
17070 const char particle_dependency
,
17071 const char compression
)
17073 tng_trajectory_frame_set_t frame_set
;
17074 tng_function_status stat
;
17076 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17077 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17078 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17079 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
17081 stat
= tng_util_generic_write(tng_data
, frame_nr
, values
, n_values_per_frame
,
17082 block_id
, block_name
,
17083 particle_dependency
,
17086 if(stat
!= TNG_SUCCESS
)
17091 frame_set
= &tng_data
->current_trajectory_frame_set
;
17093 /* first_frame_time is -1 when it is not yet set. */
17094 if(frame_set
->first_frame_time
< -0.1)
17096 if(frame_nr
> frame_set
->first_frame
)
17098 stat
= tng_frame_set_first_frame_time_set(tng_data
,
17101 frame_set
->first_frame
) *
17102 tng_data
->time_per_frame
);
17106 stat
= tng_frame_set_first_frame_time_set(tng_data
, time
);
17112 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17113 (const tng_trajectory_t tng_data
,
17114 const int64_t frame_nr
,
17116 const double *values
,
17117 const int64_t n_values_per_frame
,
17118 const int64_t block_id
,
17119 const char *block_name
,
17120 const char particle_dependency
,
17121 const char compression
)
17123 tng_trajectory_frame_set_t frame_set
;
17124 tng_function_status stat
;
17126 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17127 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17128 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17129 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
17131 stat
= tng_util_generic_double_write(tng_data
, frame_nr
, values
, n_values_per_frame
,
17132 block_id
, block_name
,
17133 particle_dependency
,
17136 if(stat
!= TNG_SUCCESS
)
17141 frame_set
= &tng_data
->current_trajectory_frame_set
;
17143 /* first_frame_time is -1 when it is not yet set. */
17144 if(frame_set
->first_frame_time
< -0.1)
17146 if(frame_nr
> frame_set
->first_frame
)
17148 stat
= tng_frame_set_first_frame_time_set(tng_data
,
17151 frame_set
->first_frame
) *
17152 tng_data
->time_per_frame
);
17156 stat
= tng_frame_set_first_frame_time_set(tng_data
, time
);
17162 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17163 (const tng_trajectory_t tng_data
,
17164 const int64_t frame_nr
,
17166 const float *positions
)
17168 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17169 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17170 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17171 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
17173 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
, positions
,
17174 3, TNG_TRAJ_POSITIONS
, "POSITIONS",
17175 TNG_PARTICLE_BLOCK_DATA
,
17176 TNG_TNG_COMPRESSION
));
17179 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17180 (const tng_trajectory_t tng_data
,
17181 const int64_t frame_nr
,
17183 const double *positions
)
17185 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17186 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17187 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17188 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
17190 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
, time
,
17192 TNG_TRAJ_POSITIONS
,
17194 TNG_PARTICLE_BLOCK_DATA
,
17195 TNG_TNG_COMPRESSION
));
17198 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17199 (const tng_trajectory_t tng_data
,
17200 const int64_t frame_nr
,
17202 const float *velocities
)
17204 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17205 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17206 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17207 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
17209 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
,
17211 TNG_TRAJ_VELOCITIES
,
17213 TNG_PARTICLE_BLOCK_DATA
,
17214 TNG_TNG_COMPRESSION
));
17217 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
17218 (const tng_trajectory_t tng_data
,
17219 const int64_t frame_nr
,
17221 const double *velocities
)
17223 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17224 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17225 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17226 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
17228 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
, time
,
17230 TNG_TRAJ_VELOCITIES
,
17232 TNG_PARTICLE_BLOCK_DATA
,
17233 TNG_TNG_COMPRESSION
));
17236 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
17237 (const tng_trajectory_t tng_data
,
17238 const int64_t frame_nr
,
17240 const float *forces
)
17242 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17243 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17244 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17245 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
17247 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
, forces
,
17248 3, TNG_TRAJ_FORCES
, "FORCES",
17249 TNG_PARTICLE_BLOCK_DATA
,
17250 TNG_GZIP_COMPRESSION
));
17253 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
17254 (const tng_trajectory_t tng_data
,
17255 const int64_t frame_nr
,
17257 const double *forces
)
17259 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17260 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17261 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17262 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
17264 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
, time
,
17266 TNG_TRAJ_FORCES
, "FORCES",
17267 TNG_PARTICLE_BLOCK_DATA
,
17268 TNG_GZIP_COMPRESSION
));
17271 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
17272 (const tng_trajectory_t tng_data
,
17273 const int64_t frame_nr
,
17275 const float *box_shape
)
17277 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17278 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17279 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17280 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
17282 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
, box_shape
,
17283 9, TNG_TRAJ_BOX_SHAPE
, "BOX SHAPE",
17284 TNG_NON_PARTICLE_BLOCK_DATA
,
17285 TNG_GZIP_COMPRESSION
));
17288 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
17289 (const tng_trajectory_t tng_data
,
17290 const int64_t frame_nr
,
17292 const double *box_shape
)
17294 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17295 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
17296 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
17297 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
17299 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
,
17300 time
, box_shape
, 9,
17301 TNG_TRAJ_BOX_SHAPE
,
17303 TNG_NON_PARTICLE_BLOCK_DATA
,
17304 TNG_GZIP_COMPRESSION
));
17307 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
17308 (const tng_trajectory_t tng_data
,
17309 const int64_t block_id
,
17313 tng_trajectory_frame_set_t frame_set
;
17314 tng_data_t data
= 0;
17315 tng_function_status stat
;
17317 int block_type
= -1;
17319 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17320 TNG_ASSERT(codec_id
, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
17321 TNG_ASSERT(factor
, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
17323 frame_set
= &tng_data
->current_trajectory_frame_set
;
17325 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
17326 if(stat
== TNG_SUCCESS
)
17328 block_type
= TNG_PARTICLE_BLOCK_DATA
;
17332 stat
= tng_data_find(tng_data
, block_id
, &data
);
17333 if(stat
== TNG_SUCCESS
)
17335 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
17339 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17340 if(stat
!= TNG_SUCCESS
)
17344 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
17345 if(stat
== TNG_SUCCESS
)
17347 block_type
= TNG_PARTICLE_BLOCK_DATA
;
17351 stat
= tng_data_find(tng_data
, block_id
, &data
);
17352 if(stat
== TNG_SUCCESS
)
17354 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
17363 if(block_type
== TNG_PARTICLE_BLOCK_DATA
)
17365 if(data
->last_retrieved_frame
< 0)
17367 i
= data
->first_frame_with_data
;
17371 i
= data
->last_retrieved_frame
;
17374 else if(block_type
== TNG_NON_PARTICLE_BLOCK_DATA
)
17376 if(data
->last_retrieved_frame
< 0)
17378 i
= data
->first_frame_with_data
;
17382 i
= data
->last_retrieved_frame
;
17387 return(TNG_FAILURE
);
17389 if(i
< frame_set
->first_frame
|| i
>= frame_set
->first_frame
+ frame_set
->n_frames
)
17391 stat
= tng_frame_set_of_frame_find(tng_data
, i
);
17392 if(stat
!= TNG_SUCCESS
)
17396 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17397 if(stat
!= TNG_SUCCESS
)
17399 fprintf(stderr
, "TNG library: Cannot read data block of frame set. %s: %d\n",
17400 __FILE__
, __LINE__
);
17404 if(block_type
== TNG_PARTICLE_BLOCK_DATA
)
17406 *codec_id
= data
->codec_id
;
17407 *factor
= data
->compression_multiplier
;
17409 else if(block_type
== TNG_NON_PARTICLE_BLOCK_DATA
)
17411 *codec_id
= data
->codec_id
;
17412 *factor
= data
->compression_multiplier
;
17414 return(TNG_SUCCESS
);
17417 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
17418 (const tng_trajectory_t tng_data
,
17419 int64_t current_frame
,
17420 const int64_t n_requested_data_block_ids
,
17421 const int64_t *requested_data_block_ids
,
17422 int64_t *next_frame
,
17423 int64_t *n_data_blocks_in_next_frame
,
17424 int64_t **data_block_ids_in_next_frame
)
17426 tng_trajectory_frame_set_t frame_set
;
17427 tng_function_status stat
;
17429 tng_gen_block_t block
;
17430 int64_t i
, j
, block_id
, *temp
;
17431 int64_t data_frame
, frame_diff
, min_diff
;
17432 int64_t size
, frame_set_file_pos
;
17433 int found
, read_all
= 0;
17436 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17437 TNG_ASSERT(next_frame
, "TNG library: The pointer to the next frame must not be NULL.");
17438 TNG_ASSERT(n_data_blocks_in_next_frame
, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
17439 TNG_ASSERT(data_block_ids_in_next_frame
, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17441 if(n_requested_data_block_ids
)
17443 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.");
17444 size
= sizeof(int64_t) * n_requested_data_block_ids
;
17445 temp
= (int64_t *)realloc(*data_block_ids_in_next_frame
, size
);
17448 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
17449 __FILE__
, __LINE__
);
17450 free(*data_block_ids_in_next_frame
);
17451 *data_block_ids_in_next_frame
= 0;
17452 return(TNG_CRITICAL
);
17454 *data_block_ids_in_next_frame
= temp
;
17457 frame_set
= &tng_data
->current_trajectory_frame_set
;
17459 current_frame
+= 1;
17461 if(current_frame
< frame_set
->first_frame
||
17462 current_frame
>= frame_set
->first_frame
+ frame_set
->n_frames
)
17464 frame_set_file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
17465 stat
= tng_frame_set_of_frame_find(tng_data
, current_frame
);
17466 if(stat
!= TNG_SUCCESS
)
17468 /* If the frame set search found the frame set after the starting
17469 * frame set there is a gap in the frame sets. So, even if the frame
17470 * was not found the next frame with data is still in the found
17472 if(stat
== TNG_CRITICAL
|| frame_set
->prev_frame_set_file_pos
!=
17473 frame_set_file_pos
)
17477 current_frame
= frame_set
->first_frame
;
17481 /* Check for data blocks only if they have not already been found. */
17482 if(frame_set
->n_particle_data_blocks
<= 0 && frame_set
->n_data_blocks
<= 0)
17484 file_pos
= ftello(tng_data
->input_file
);
17485 if(file_pos
< tng_data
->input_file_len
)
17487 tng_block_init(&block
);
17488 stat
= tng_block_header_read(tng_data
, block
);
17489 while(file_pos
< tng_data
->input_file_len
&&
17490 stat
!= TNG_CRITICAL
&&
17491 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
17494 stat
= tng_block_read_next(tng_data
, block
,
17496 if(stat
!= TNG_CRITICAL
)
17498 file_pos
= ftello(tng_data
->input_file
);
17499 if(file_pos
< tng_data
->input_file_len
)
17501 stat
= tng_block_header_read(tng_data
, block
);
17505 tng_block_destroy(&block
);
17506 if(stat
== TNG_CRITICAL
)
17508 fprintf(stderr
, "TNG library: Cannot read block header at pos %" PRId64
". %s: %d\n",
17509 file_pos
, __FILE__
, __LINE__
);
17518 *n_data_blocks_in_next_frame
= 0;
17520 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
17522 data
= &frame_set
->tr_particle_data
[i
];
17523 block_id
= data
->block_id
;
17525 if(n_requested_data_block_ids
> 0)
17528 for(j
= 0; j
< n_requested_data_block_ids
; j
++)
17530 if(block_id
== requested_data_block_ids
[j
])
17542 if(!read_all
&& (data
->last_retrieved_frame
< frame_set
->first_frame
||
17543 data
->last_retrieved_frame
>=
17544 frame_set
->first_frame
+ frame_set
->n_frames
))
17546 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
,
17547 TNG_USE_HASH
, block_id
);
17548 if(stat
== TNG_CRITICAL
)
17550 fprintf(stderr
, "TNG library: Cannot read data block of frame set. %s: %d\n",
17551 __FILE__
, __LINE__
);
17554 if(stat
== TNG_FAILURE
)
17559 if(frame_set
->first_frame
!= current_frame
&&
17560 data
->last_retrieved_frame
>= 0)
17562 data_frame
= data
->last_retrieved_frame
+ data
->stride_length
;
17566 data_frame
= data
->first_frame_with_data
;
17568 frame_diff
= data_frame
- current_frame
;
17573 if(min_diff
== -1 || frame_diff
<= min_diff
)
17575 if(frame_diff
< min_diff
)
17577 *n_data_blocks_in_next_frame
= 1;
17581 *n_data_blocks_in_next_frame
+= 1;
17583 if(n_requested_data_block_ids
<= 0)
17585 size
= sizeof(int64_t) * (*n_data_blocks_in_next_frame
);
17586 temp
= (int64_t *)realloc(*data_block_ids_in_next_frame
, size
);
17589 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
17590 __FILE__
, __LINE__
);
17591 free(*data_block_ids_in_next_frame
);
17592 *data_block_ids_in_next_frame
= 0;
17593 return(TNG_CRITICAL
);
17595 *data_block_ids_in_next_frame
= temp
;
17599 TNG_ASSERT(*n_data_blocks_in_next_frame
<= n_requested_data_block_ids
, "TNG library: Array of data block IDs out of bounds");
17601 (*data_block_ids_in_next_frame
)[(*n_data_blocks_in_next_frame
) - 1] = block_id
;
17603 min_diff
= frame_diff
;
17606 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
17608 data
= &frame_set
->tr_data
[i
];
17609 block_id
= data
->block_id
;
17611 if(n_requested_data_block_ids
> 0)
17614 for(j
= 0; j
< n_requested_data_block_ids
; j
++)
17616 if(block_id
== requested_data_block_ids
[j
])
17628 if(!read_all
&& (data
->last_retrieved_frame
< frame_set
->first_frame
||
17629 data
->last_retrieved_frame
>=
17630 frame_set
->first_frame
+ frame_set
->n_frames
))
17632 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
,
17633 TNG_USE_HASH
, block_id
);
17634 if(stat
== TNG_CRITICAL
)
17636 fprintf(stderr
, "TNG library: Cannot read data block of frame set. %s: %d\n",
17637 __FILE__
, __LINE__
);
17640 if(stat
== TNG_FAILURE
)
17645 if(frame_set
->first_frame
!= current_frame
&&
17646 data
->last_retrieved_frame
>= 0)
17648 data_frame
= data
->last_retrieved_frame
+ data
->stride_length
;
17652 data_frame
= data
->first_frame_with_data
;
17654 frame_diff
= data_frame
- current_frame
;
17659 if(min_diff
== -1 || frame_diff
<= min_diff
)
17661 if(frame_diff
< min_diff
)
17663 *n_data_blocks_in_next_frame
= 1;
17667 *n_data_blocks_in_next_frame
+= 1;
17669 if(n_requested_data_block_ids
<= 0)
17671 size
= sizeof(int64_t) * (*n_data_blocks_in_next_frame
);
17672 temp
= (int64_t *)realloc(*data_block_ids_in_next_frame
, size
);
17675 fprintf(stderr
, "TNG library: Cannot allocate memory. %s: %d\n",
17676 __FILE__
, __LINE__
);
17677 free(*data_block_ids_in_next_frame
);
17678 *data_block_ids_in_next_frame
= 0;
17679 return(TNG_CRITICAL
);
17681 *data_block_ids_in_next_frame
= temp
;
17685 TNG_ASSERT(*n_data_blocks_in_next_frame
<= n_requested_data_block_ids
, "TNG library: Array of data block IDs out of bounds");
17687 (*data_block_ids_in_next_frame
)[(*n_data_blocks_in_next_frame
) - 1] = block_id
;
17689 min_diff
= frame_diff
;
17694 return(TNG_FAILURE
);
17696 *next_frame
= current_frame
+ min_diff
;
17698 return(TNG_SUCCESS
);
17702 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
17703 (const tng_trajectory_t tng_data,
17704 int64_t *n_data_blocks,
17705 int64_t **data_block_ids,
17706 char ***data_block_names,
17707 int64_t **stride_lengths,
17708 int64_t **n_values_per_frame,
17709 char **block_types,
17710 char **dependencies,
17711 char **compressions)
17713 tng_gen_block_t block;
17714 int64_t orig_file_pos, file_pos;
17716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17717 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
17718 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17719 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
17720 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
17722 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17724 return(TNG_CRITICAL);
17727 orig_file_pos = ftello(tng_data->input_file);
17729 fseeko(tng_data->input_file, 0, SEEK_SET);
17732 *n_data_blocks = 0;
17734 tng_block_init(&block);
17736 while(file_pos < tng_data->input_file_len &&
17737 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
17739 if(block->id > TNG_TRAJECTORY_FRAME_SET)
17743 file_pos += (block->block_contents_size + block->header_contents_size);
17744 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
17747 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
17749 return(TNG_SUCCESS);
17752 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
17753 (const tng_trajectory_t tng_data
,
17754 const int64_t prev_frame
)
17756 tng_function_status stat
;
17757 FILE *temp
= tng_data
->input_file
;
17759 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17760 TNG_ASSERT(prev_frame
>= 0, "TNG library: The previous frame must not be negative.");
17762 tng_data
->input_file
= tng_data
->output_file
;
17764 stat
= tng_frame_set_of_frame_find(tng_data
, prev_frame
);
17765 if(stat
!= TNG_SUCCESS
)
17770 tng_data
->current_trajectory_frame_set_output_file_pos
=
17771 tng_data
->current_trajectory_frame_set_input_file_pos
;
17773 tng_data
->input_file
= temp
;
17775 return(TNG_SUCCESS
);
17778 tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
17779 (const tng_trajectory_t tng_data
,
17780 const int64_t block_id
,
17783 int64_t curr_file_pos
, first_frame_set_file_pos
, curr_n_frames
;
17784 tng_function_status stat
;
17786 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17790 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
17792 return(TNG_CRITICAL
);
17795 first_frame_set_file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
17796 curr_file_pos
= ftello(tng_data
->input_file
);
17797 fseeko(tng_data
->input_file
, first_frame_set_file_pos
, SEEK_SET
);
17799 stat
= tng_frame_set_n_frames_of_data_block_get(tng_data
, block_id
, &curr_n_frames
);
17801 while(stat
== TNG_SUCCESS
&& tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
!= -1)
17803 *n_frames
+= curr_n_frames
;
17804 fseeko(tng_data
->input_file
,
17805 tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
,
17807 stat
= tng_frame_set_n_frames_of_data_block_get(tng_data
, block_id
, &curr_n_frames
);
17809 if(stat
== TNG_SUCCESS
)
17811 *n_frames
+= curr_n_frames
;
17813 fseeko(tng_data
->input_file
, curr_file_pos
, SEEK_SET
);
17814 if(stat
== TNG_CRITICAL
)
17816 return(TNG_CRITICAL
);
17818 return(TNG_SUCCESS
);