1 /* This code is part of the tng binary trajectory format.
3 * Written by Magnus Lundborg
4 * Copyright (c) 2012-2014, The GROMACS development team.
5 * Check out http://www.gromacs.org for more information.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the Revised BSD License.
12 #ifdef USE_STD_INTTYPES_H
25 #include "tng/tng_io.h"
27 #include "compression/tng_compress.h"
28 #include "tng/version.h"
32 /** One of the atoms of the bond */
34 /** The other atom of the bond */
39 /** The residue containing this atom */
40 tng_residue_t residue
;
41 /** A unique (per molecule) ID number of the atom */
43 /** The atom_type (depending on the forcefield) */
45 /** The name of the atom */
50 /** The chain containing this residue */
52 /** A unique (per chain) ID number of the residue */
54 /** The name of the residue */
56 /** The number of atoms in the residue */
58 /** A list of atoms in the residue */
63 /** The molecule containing this chain */
64 tng_molecule_t molecule
;
65 /** A unique (per molecule) ID number of the chain */
67 /** The name of the chain */
69 /** The number of residues in the chain */
71 /** A list of residues in the chain */
72 tng_residue_t residues
;
76 /** A unique ID number of the molecule */
78 /** Quaternary structure of the molecule.
83 int64_t quaternary_str
;
84 /** The number of chains in the molecule */
86 /** The number of residues in the molecule */
88 /** The number of atoms in the molecule */
90 /** The number of bonds in the molecule. If the bonds are not specified this
93 /** The name of the molecule */
95 /** A list of chains in the molecule */
97 /** A list of residues in the molecule */
98 tng_residue_t residues
;
99 /** A list of the atoms in the molecule */
101 /** A list of the bonds in the molecule */
105 struct tng_gen_block
{
106 /** The size of the block header in bytes */
107 int64_t header_contents_size
;
108 /** The size of the block contents in bytes */
109 int64_t block_contents_size
;
110 /** The ID of the block to determine its type */
112 /** The MD5 hash of the block to verify integrity */
113 char md5_hash
[TNG_MD5_HASH_LEN
];
114 /** The name of the block */
116 /** The library version used to write the block */
117 int64_t block_version
;
118 int64_t alt_hash_type
;
119 int64_t alt_hash_len
;
121 int64_t signature_type
;
122 int64_t signature_len
;
124 /** The full block header contents */
125 char *header_contents
;
126 /** The full block contents */
127 char *block_contents
;
130 struct tng_particle_mapping
{
131 /** The index number of the first particle in this mapping block */
132 int64_t num_first_particle
;
133 /** The number of particles list in this mapping block */
135 /** the mapping of index numbers to the real particle numbers in the
136 * trajectory. real_particle_numbers[0] is the real particle number
137 * (as it is numbered in the molecular system) of the first particle
138 * in the data blocks covered by this particle mapping block */
139 int64_t *real_particle_numbers
;
142 struct tng_trajectory_frame_set
{
143 /** The number of different particle mapping blocks present. */
144 int64_t n_mapping_blocks
;
145 /** The atom mappings of this frame set */
146 struct tng_particle_mapping
*mappings
;
147 /** The first frame of this frame set */
149 /** The number of frames in this frame set */
151 /** The number of written frames in this frame set (used when writing one
152 * frame at a time). */
153 int64_t n_written_frames
;
154 /** The number of frames not yet written to file in this frame set
155 * (used from the utility functions to finish the writing properly. */
156 int64_t n_unwritten_frames
;
159 /** A list of the number of each molecule type - only used when using
160 * variable number of atoms */
161 int64_t *molecule_cnt_list
;
162 /** The number of particles/atoms - only used when using variable number
165 /** The file position of the next frame set */
166 int64_t next_frame_set_file_pos
;
167 /** The file position of the previous frame set */
168 int64_t prev_frame_set_file_pos
;
169 /** The file position of the frame set one long stride step ahead */
170 int64_t medium_stride_next_frame_set_file_pos
;
171 /** The file position of the frame set one long stride step behind */
172 int64_t medium_stride_prev_frame_set_file_pos
;
173 /** The file position of the frame set one long stride step ahead */
174 int64_t long_stride_next_frame_set_file_pos
;
175 /** The file position of the frame set one long stride step behind */
176 int64_t long_stride_prev_frame_set_file_pos
;
177 /** Time stamp (in seconds) of first frame in frame set */
178 double first_frame_time
;
180 /* The data blocks in a frame set are trajectory data blocks */
181 /** The number of trajectory data blocks of particle dependent data */
182 int n_particle_data_blocks
;
183 /** A list of data blocks containing particle dependent data */
184 struct tng_particle_data
*tr_particle_data
;
185 /** The number of trajectory data blocks independent of particles */
187 /** A list of data blocks containing particle indepdendent data */
188 struct tng_non_particle_data
*tr_data
;
191 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
192 /* FIXME: Make only one data block struct */
193 struct tng_particle_data
{
194 /** The block ID of the data block containing this particle data.
195 * This is used to determine the kind of data that is stored */
197 /** The name of the data block. This is used to determine the kind of
198 * data that is stored */
200 /** The type of data stored. */
202 /** The frame number of the first data value */
203 int64_t first_frame_with_data
;
204 /** The number of frames in this frame set */
206 /** The number of values stored per frame */
207 int64_t n_values_per_frame
;
208 /** The number of frames between each data point - e.g. when
209 * storing sparse data. */
210 int64_t stride_length
;
211 /** ID of the CODEC used for compression 0 == no compression. */
213 /** If reading one frame at a time this is the last read frame */
214 int64_t last_retrieved_frame
;
215 /** The multiplier used for getting integer values for compression */
216 double compression_multiplier
;
217 /** A 1-dimensional array of values of length
218 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
220 /** If storing character data store it in a 3-dimensional array */
224 struct tng_non_particle_data
{
225 /** The ID of the data block */
227 /** The name of the data block. This is used to determine the kind of
228 * data that is stored */
230 /** The type of data stored. */
232 /** The first frame number of the first data value */
233 int64_t first_frame_with_data
;
234 /** The number of frames in this data block */
236 /** The number of values stored per frame */
237 int64_t n_values_per_frame
;
238 /** The number of frames between each data value, e.g. if storing data
239 * that is not saved every frame. */
240 int64_t stride_length
;
241 /** ID of the CODEC used for compression. 0 == no compression. */
243 /** If reading one frame at a time this is the last read frame */
244 int64_t last_retrieved_frame
;
245 /** Compressed data is stored as integers. This compression multiplier is
246 * the multiplication factor to convert from integer to float/double */
247 double compression_multiplier
;
248 /** A 1-dimensional array of values of length
249 * [sizeof (datatype)] * n_frames * n_values_per_frame */
251 /** If storing character data store it in a 2-dimensional array */
257 struct tng_trajectory
{
258 /** The path of the input trajectory file */
259 char *input_file_path
;
260 /** A handle to the input file */
262 /** The length of the input file */
264 /** The path of the output trajectory file */
265 char *output_file_path
;
266 /** A handle to the output file */
268 /** Function to swap 32 bit values to and from the endianness of the
270 tng_function_status (*input_endianness_swap_func_32
)(const tng_trajectory_t
, int32_t *);
271 /** Function to swap 64 bit values to and from the endianness of the
273 tng_function_status (*input_endianness_swap_func_64
)(const tng_trajectory_t
, int64_t *);
274 /** Function to swap 32 bit values to and from the endianness of the
276 tng_function_status (*output_endianness_swap_func_32
)(const tng_trajectory_t
, int32_t *);
277 /** Function to swap 64 bit values to and from the endianness of the
279 tng_function_status (*output_endianness_swap_func_64
)(const tng_trajectory_t
, int64_t *);
280 /** The endianness of 32 bit values of the current computer */
282 /** The endianness of 64 bit values of the current computer */
285 /** The name of the program producing this trajectory */
286 char *first_program_name
;
287 /** The forcefield used in the simulations */
288 char *forcefield_name
;
289 /** The name of the user running the simulations */
290 char *first_user_name
;
291 /** The name of the computer on which the simulations were performed */
292 char *first_computer_name
;
293 /** The PGP signature of the user creating the file. */
294 char *first_pgp_signature
;
295 /** The name of the program used when making last modifications to the
297 char *last_program_name
;
298 /** The name of the user making the last modifications to the file */
299 char *last_user_name
;
300 /** The name of the computer on which the last modifications were made */
301 char *last_computer_name
;
302 /** The PGP signature of the user making the last modifications to the
304 char *last_pgp_signature
;
305 /** The time (n seconds since 1970) when the file was created */
307 /** The exponential of the value of the distance unit used. The default
308 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
309 * the measurements are in Ã… the distance_unit_exponential = -10. */
310 int64_t distance_unit_exponential
;
312 /** A flag indicating if the number of atoms can vary throughout the
313 * simulation, e.g. using a grand canonical ensemble */
314 char var_num_atoms_flag
;
315 /** The number of frames in a frame set. It is allowed to have frame sets
316 * with fewer frames, but this will help searching for specific frames */
317 int64_t frame_set_n_frames
;
318 /** The number of frame sets in a medium stride step */
319 int64_t medium_stride_length
;
320 /** The number of frame sets in a long stride step */
321 int64_t long_stride_length
;
322 /** The current (can change from one frame set to another) time length
323 * (in seconds) of one frame */
324 double time_per_frame
;
326 /** The number of different kinds of molecules in the trajectory */
328 /** A list of molecules in the trajectory */
329 tng_molecule_t molecules
;
330 /** A list of the count of each molecule - if using variable number of
331 * particles this will be specified in each frame set */
332 int64_t *molecule_cnt_list
;
333 /** The total number of particles/atoms. If using variable number of
334 * particles this will be specified in each frame set */
337 /** The pos in the src file of the first frame set */
338 int64_t first_trajectory_frame_set_input_file_pos
;
339 /** The pos in the dest file of the first frame set */
340 int64_t first_trajectory_frame_set_output_file_pos
;
341 /** The pos in the src file of the last frame set */
342 int64_t last_trajectory_frame_set_input_file_pos
;
343 /** The pos in the dest file of the last frame set */
344 int64_t last_trajectory_frame_set_output_file_pos
;
345 /** The currently active frame set */
346 struct tng_trajectory_frame_set current_trajectory_frame_set
;
347 /** The pos in the src file of the current frame set */
348 long current_trajectory_frame_set_input_file_pos
;
349 /** The pos in the dest file of the current frame set */
350 long current_trajectory_frame_set_output_file_pos
;
351 /** The number of frame sets in the trajectory N.B. Not saved in file and
352 * cannot be trusted to be up-to-date */
353 int64_t n_trajectory_frame_sets
;
355 /* These data blocks are non-trajectory data blocks */
356 /** The number of non-frame dependent particle dependent data blocks */
357 int n_particle_data_blocks
;
358 /** A list of data blocks containing particle dependent data */
359 struct tng_particle_data
*non_tr_particle_data
;
361 /** The number of frame and particle independent data blocks */
363 /** A list of frame and particle indepdendent data blocks */
364 struct tng_non_particle_data
*non_tr_data
;
366 /** TNG compression algorithm for compressing positions */
367 int *compress_algo_pos
;
368 /** TNG compression algorithm for compressing velocities */
369 int *compress_algo_vel
;
370 /** The precision used for lossy compression */
371 double compression_precision
;
375 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
377 #endif /* win32... */
378 #endif /* not defined USE_WINDOWS */
381 #define TNG_INLINE __inline
382 #define TNG_SNPRINTF _snprintf
384 #define TNG_INLINE inline
385 #define TNG_SNPRINTF snprintf
388 static TNG_INLINE
int tng_min_i(int a
, int b
)
390 return (a
< b
? a
: b
);
394 static TNG_INLINE int tng_max_i(int a, int b)
396 return (a > b ? a : b);
399 static TNG_INLINE
int64_t tng_min_i64(int64_t a
, int64_t b
)
401 return (a
< b
? a
: b
);
404 static TNG_INLINE
int64_t tng_max_i64(int64_t a
, int64_t b
)
406 return (a
> b
? a
: b
);
410 static TNG_INLINE float tng_min_f(float a, float b)
412 return (a < b ? a : b);
415 static TNG_INLINE float tng_max_f(float a, float b)
417 return (a > b ? a : b);
420 static TNG_INLINE double tng_min_d(double a, double b)
422 return (a < b ? a : b);
425 static TNG_INLINE double tng_max_d(double a, double b)
427 return (a > b ? a : b);
431 /** This function swaps the byte order of a 32 bit numerical variable
433 * It does not only work with integer, but e.g. floats need casting.
434 * If the byte order is already big endian no change is needed.
435 * @param tng_data is a trajectory data container.
436 * @param v is a pointer to a 32 bit numerical value (float or integer).
437 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
438 * byte order is not recognised.
440 static tng_function_status tng_swap_byte_order_big_endian_32
441 (const tng_trajectory_t tng_data
, int32_t *v
)
443 switch(tng_data
->endianness_32
)
445 case TNG_LITTLE_ENDIAN_32
: /* Byte order is reversed. */
446 *v
= ((*v
& 0xFF000000) >> 24) | /* Move first byte to end */
447 ((*v
& 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
448 ((*v
& 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
449 ((*v
& 0x000000FF) << 24); /* Move last byte to first */
453 case TNG_BYTE_PAIR_SWAP_32
: /* byte pair swap */
454 *v
= ((*v
& 0xFFFF0000) >> 16) |
455 ((*v
& 0x0000FFFF) << 16);
459 case TNG_BIG_ENDIAN_32
: /* Already correct */
467 /** This function swaps the byte order of a 64 bit numerical variable
469 * It does not only work with integer, but e.g. floats need casting.
470 * The byte order swapping routine can convert four different byte
471 * orders to big endian.
472 * If the byte order is already big endian no change is needed.
473 * @param tng_data is a trajectory data container.
474 * @param v is a pointer to a 64 bit numerical value (double or integer).
475 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
476 * byte order is not recognised.
478 static tng_function_status tng_swap_byte_order_big_endian_64
479 (const tng_trajectory_t tng_data
, int64_t *v
)
481 switch(tng_data
->endianness_64
)
483 case TNG_LITTLE_ENDIAN_64
: /* Byte order is reversed. */
484 *v
= ((*v
& 0xFF00000000000000LL
) >> 56) | /* Move first byte to end */
485 ((*v
& 0x00FF000000000000LL
) >> 40) | /* Move 2nd byte to pos 7 */
486 ((*v
& 0x0000FF0000000000LL
) >> 24) | /* Move 3rd byte to pos 6 */
487 ((*v
& 0x000000FF00000000LL
) >> 8 ) | /* Move 4th byte to pos 5 */
488 ((*v
& 0x00000000FF000000LL
) << 8 ) | /* Move 5th byte to pos 4 */
489 ((*v
& 0x0000000000FF0000LL
) << 24) | /* Move 6th byte to pos 3 */
490 ((*v
& 0x000000000000FF00LL
) << 40) | /* Move 7th byte to pos 2 */
491 ((*v
& 0x00000000000000FFLL
) << 56); /* Move last byte to first */
495 case TNG_QUAD_SWAP_64
: /* Byte quad swap */
496 *v
= ((*v
& 0xFFFFFFFF00000000LL
) >> 32) |
497 ((*v
& 0x00000000FFFFFFFFLL
) << 32);
501 case TNG_BYTE_PAIR_SWAP_64
: /* Byte pair swap */
502 *v
= ((*v
& 0xFFFF0000FFFF0000LL
) >> 16) |
503 ((*v
& 0x0000FFFF0000FFFFLL
) << 16);
507 case TNG_BYTE_SWAP_64
: /* Byte swap */
508 *v
= ((*v
& 0xFF00FF00FF00FF00LL
) >> 8) |
509 ((*v
& 0x00FF00FF00FF00FFLL
) << 8);
513 case TNG_BIG_ENDIAN_64
: /* Already correct */
521 /** This function swaps the byte order of a 32 bit numerical variable
523 * It does not only work with integer, but e.g. floats need casting.
524 * If the byte order is already little endian no change is needed.
525 * @param tng_data is a trajectory data container.
526 * @param v is a pointer to a 32 bit numerical value (float or integer).
527 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
528 * byte order is not recognised.
530 static tng_function_status tng_swap_byte_order_little_endian_32
531 (const tng_trajectory_t tng_data
, int32_t *v
)
533 switch(tng_data
->endianness_32
)
535 case TNG_LITTLE_ENDIAN_32
: /* Already correct */
538 case TNG_BYTE_PAIR_SWAP_32
: /* byte pair swapped big endian to little endian */
539 *v
= ((*v
& 0xFF00FF00) >> 8) |
540 ((*v
& 0x00FF00FF) << 8);
544 case TNG_BIG_ENDIAN_32
: /* Byte order is reversed. */
545 *v
= ((*v
& 0xFF000000) >> 24) | /* Move first byte to end */
546 ((*v
& 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
547 ((*v
& 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
548 ((*v
& 0x000000FF) << 24); /* Move last byte to first */
557 /** This function swaps the byte order of a 64 bit numerical variable
559 * It does not only work with integer, but e.g. floats need casting.
560 * The byte order swapping routine can convert four different byte
561 * orders to little endian.
562 * If the byte order is already little endian no change is needed.
563 * @param tng_data is a trajectory data container.
564 * @param v is a pointer to a 64 bit numerical value (double or integer).
565 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
566 * byte order is not recognised.
568 static tng_function_status tng_swap_byte_order_little_endian_64
569 (const tng_trajectory_t tng_data
, int64_t *v
)
571 switch(tng_data
->endianness_64
)
573 case TNG_LITTLE_ENDIAN_64
: /* Already correct */
576 case TNG_QUAD_SWAP_64
: /* Byte quad swapped big endian to little endian */
577 *v
= ((*v
& 0xFF000000FF000000LL
) >> 24) |
578 ((*v
& 0x00FF000000FF0000LL
) >> 8) |
579 ((*v
& 0x0000FF000000FF00LL
) << 8) |
580 ((*v
& 0x000000FF000000FFLL
) << 24);
584 case TNG_BYTE_PAIR_SWAP_64
: /* Byte pair swapped big endian to little endian */
585 *v
= ((*v
& 0xFF00FF0000000000LL
) >> 40) |
586 ((*v
& 0x00FF00FF00000000LL
) >> 24) |
587 ((*v
& 0x00000000FF00FF00LL
) << 24) |
588 ((*v
& 0x0000000000FF00FFLL
) << 40);
592 case TNG_BYTE_SWAP_64
: /* Byte swapped big endian to little endian */
593 *v
= ((*v
& 0xFFFF000000000000LL
) >> 48) |
594 ((*v
& 0x0000FFFF00000000LL
) >> 16) |
595 ((*v
& 0x00000000FFFF0000LL
) << 16) |
596 ((*v
& 0x000000000000FFFFLL
) << 48);
600 case TNG_BIG_ENDIAN_64
: /* Byte order is reversed. */
601 *v
= ((*v
& 0xFF00000000000000LL
) >> 56) | /* Move first byte to end */
602 ((*v
& 0x00FF000000000000LL
) >> 40) | /* Move 2nd byte to pos 7 */
603 ((*v
& 0x0000FF0000000000LL
) >> 24) | /* Move 3rd byte to pos 6 */
604 ((*v
& 0x000000FF00000000LL
) >> 8 ) | /* Move 4th byte to pos 5 */
605 ((*v
& 0x00000000FF000000LL
) << 8 ) | /* Move 5th byte to pos 4 */
606 ((*v
& 0x0000000000FF0000LL
) << 24) | /* Move 6th byte to pos 3 */
607 ((*v
& 0x000000000000FF00LL
) << 40) | /* Move 7th byte to pos 2 */
608 ((*v
& 0x00000000000000FFLL
) << 56); /* Move last byte to first */
616 /** Generate the md5 hash of a block.
617 * The hash is created based on the actual block contents.
618 * @param block is a general block container.
619 * @return TNG_SUCCESS (0) if successful.
621 static tng_function_status
tng_block_md5_hash_generate(tng_gen_block_t block
)
623 md5_state_t md5_state
;
625 md5_init(&md5_state
);
626 md5_append(&md5_state
, (md5_byte_t
*)block
->block_contents
,
627 (int)block
->block_contents_size
);
628 md5_finish(&md5_state
, (md5_byte_t
*)block
->md5_hash
);
633 /** Compare the current block md5 hash (e.g. read from file) with the md5 hash
634 * calculated from the current contents.
635 * If the current md5 hash is not set skip the comparison.
636 * @param block is a general block container.
637 * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
638 * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
639 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
642 static tng_function_status
tng_md5_hash_match_verify(tng_gen_block_t block
,
645 md5_state_t md5_state
;
646 char hash
[TNG_MD5_HASH_LEN
];
648 TNG_ASSERT(block
->block_contents_size
> 0, "The block contents size must be > 0");
651 if(strncmp(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
655 md5_init(&md5_state
);
656 md5_append(&md5_state
, (md5_byte_t
*)block
->block_contents
,
657 (int)block
->block_contents_size
);
658 md5_finish(&md5_state
, (md5_byte_t
*)hash
);
660 if(strncmp(block
->md5_hash
, hash
, 16) != 0)
662 *results
= TNG_FALSE
;
668 /** Open the input file if it is not already opened.
669 * @param tng_data is a trajectory data container.
670 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
673 static tng_function_status
tng_input_file_init(tng_trajectory_t tng_data
)
675 if(!tng_data
->input_file
)
677 if(!tng_data
->input_file_path
)
679 fprintf(stderr
, "TNG library: No file specified for reading. %s: %d\n",
681 return(TNG_CRITICAL
);
683 tng_data
->input_file
= fopen(tng_data
->input_file_path
, "rb");
684 if(!tng_data
->input_file
)
686 fprintf(stderr
, "TNG library: Cannot open file %s. %s: %d\n",
687 tng_data
->input_file_path
, __FILE__
, __LINE__
);
688 return(TNG_CRITICAL
);
694 /** Open the output file if it is not already opened
695 * @param tng_data is a trajectory data container.
696 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
699 static tng_function_status
tng_output_file_init(tng_trajectory_t tng_data
)
701 if(!tng_data
->output_file
)
703 if(!tng_data
->output_file_path
)
705 fprintf(stderr
, "TNG library: No file specified for writing. %s: %d\n",
707 return(TNG_CRITICAL
);
710 tng_data
->output_file
= fopen(tng_data
->output_file_path
, "wb+");
712 if(!tng_data
->output_file
)
714 fprintf(stderr
, "TNG library: Cannot open file %s. %s: %d\n",
715 tng_data
->output_file_path
, __FILE__
, __LINE__
);
716 return(TNG_CRITICAL
);
722 /** Setup a file block container.
723 * @param block_p a pointer to memory to initialise as a file block container.
724 * @details Memory is allocated during initialisation.
725 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
728 static tng_function_status
tng_block_init(struct tng_gen_block
**block_p
)
730 tng_gen_block_t block
;
732 *block_p
= malloc(sizeof(struct tng_gen_block
));
735 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
736 sizeof(struct tng_gen_block
), __FILE__
, __LINE__
);
737 return(TNG_CRITICAL
);
743 /* Reset the md5_hash */
744 memcpy(block
->md5_hash
, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN
);
746 block
->block_version
= TNG_API_VERSION
;
747 block
->header_contents
= 0;
748 block
->header_contents_size
= 0;
749 block
->block_contents
= 0;
750 block
->block_contents_size
= 0;
756 * @brief Clean up a file block container.
757 * @param block_p a pointer to the file block container to destroy.
758 * @details All allocated memory in the data structure is freed, as well as
760 * @return TNG_SUCCESS (0) if successful.
762 static tng_function_status
tng_block_destroy(struct tng_gen_block
**block_p
)
764 tng_gen_block_t block
= *block_p
;
771 /* fprintf(stderr, "TNG library: Destroying block\n"); */
777 if(block
->header_contents
)
779 free(block
->header_contents
);
780 block
->header_contents
= 0;
782 if(block
->block_contents
)
784 free(block
->block_contents
);
785 block
->block_contents
= 0;
794 /** Read the header of a data block, regardless of its type
795 * @param tng_data is a trajectory data container.
796 * @param block is a general block container.
797 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
798 * error has occured (not able to read the header size, thus skipping
799 * the block) or TNG_CRITICAL (2) if a major error has occured.
801 static tng_function_status tng_block_header_read
802 (tng_trajectory_t tng_data
, tng_gen_block_t block
)
806 TNG_ASSERT(block
!= 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
808 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
810 return(TNG_CRITICAL
);
813 /* First read the header size to be able to read the whole header. */
814 if(fread(&block
->header_contents_size
, sizeof(block
->header_contents_size
),
815 1, tng_data
->input_file
) == 0)
817 fprintf(stderr
, "TNG library: Cannot read header size. %s: %d\n",
819 return(TNG_CRITICAL
);
822 if(block
->header_contents_size
== 0)
828 /* If this was the size of the general info block check the endianness */
829 if(ftell(tng_data
->input_file
) < 9)
831 /* File is little endian */
832 if ( *((const char*)&block
->header_contents_size
) != 0x00 &&
833 *((const char*)(&block
->header_contents_size
) + 7) == 0x00)
835 /* If the architecture endianness is little endian no byte swap
836 * will be needed. Otherwise use the functions to swap to little
838 if(tng_data
->endianness_32
== TNG_LITTLE_ENDIAN_32
)
840 tng_data
->input_endianness_swap_func_32
= 0;
844 tng_data
->input_endianness_swap_func_32
=
845 &tng_swap_byte_order_little_endian_32
;
847 if(tng_data
->endianness_64
== TNG_LITTLE_ENDIAN_64
)
849 tng_data
->input_endianness_swap_func_64
= 0;
853 tng_data
->input_endianness_swap_func_64
=
854 &tng_swap_byte_order_little_endian_64
;
857 /* File is big endian */
860 /* If the architecture endianness is big endian no byte swap
861 * will be needed. Otherwise use the functions to swap to big
863 if(tng_data
->endianness_32
== TNG_BIG_ENDIAN_32
)
865 tng_data
->input_endianness_swap_func_32
= 0;
869 tng_data
->input_endianness_swap_func_32
=
870 &tng_swap_byte_order_big_endian_32
;
872 if(tng_data
->endianness_64
== TNG_BIG_ENDIAN_64
)
874 tng_data
->input_endianness_swap_func_64
= 0;
878 tng_data
->input_endianness_swap_func_64
=
879 &tng_swap_byte_order_big_endian_64
;
884 if(tng_data
->input_endianness_swap_func_64
)
886 if(tng_data
->input_endianness_swap_func_64(tng_data
,
887 &block
->header_contents_size
)
890 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
895 /* Move the reading position to the beginning of the header. */
896 fseek(tng_data
->input_file
, -(long)sizeof(block
->header_contents_size
),
899 /* If there is already memory allocated for the contents free it (we do not
900 * know if the size is correct). */
901 if(block
->header_contents
)
903 free(block
->header_contents
);
906 block
->header_contents
= malloc(block
->header_contents_size
);
907 if(!block
->header_contents
)
909 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
910 block
->header_contents_size
, __FILE__
, __LINE__
);
911 return(TNG_CRITICAL
);
914 /* Read the whole header into header_contents. This way it can be saved
915 * even if it cannot be interpreted
916 * for one reason or another. */
917 if(fread(block
->header_contents
, block
->header_contents_size
, 1,
918 tng_data
->input_file
) == 0)
920 fprintf(stderr
, "TNG library: Cannot read header. %s: %d\n", __FILE__
, __LINE__
);
921 return(TNG_CRITICAL
);
924 /* The header contents size has already been read. Skip ahead. */
925 offset
= sizeof(block
->header_contents_size
);
928 /* Copy the respective parameters from the header contents block */
929 memcpy(&block
->block_contents_size
, block
->header_contents
+offset
,
930 sizeof(block
->block_contents_size
));
931 if(tng_data
->input_endianness_swap_func_64
)
933 if(tng_data
->input_endianness_swap_func_64(tng_data
,
934 &block
->block_contents_size
)
937 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
942 offset
+= sizeof(block
->block_contents_size
);
944 memcpy(&block
->id
, block
->header_contents
+offset
, sizeof(block
->id
));
945 if(tng_data
->input_endianness_swap_func_64
)
947 if(tng_data
->input_endianness_swap_func_64(tng_data
,
951 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
956 offset
+= sizeof(block
->id
);
958 memcpy(block
->md5_hash
, block
->header_contents
+offset
, TNG_MD5_HASH_LEN
);
959 offset
+= TNG_MD5_HASH_LEN
;
961 if(block
->name
&& strcmp(block
->name
, block
->header_contents
+offset
) != 0)
966 len
= tng_min_i((int)strlen(block
->header_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
969 block
->name
= malloc(len
);
972 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
974 return(TNG_CRITICAL
);
976 strncpy(block
->name
, block
->header_contents
+offset
, len
);
980 memcpy(&block
->block_version
, block
->header_contents
+offset
,
981 sizeof(block
->block_version
));
982 if(tng_data
->input_endianness_swap_func_64
)
984 if(tng_data
->input_endianness_swap_func_64(tng_data
,
985 &block
->block_version
)
988 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
996 /** Write a whole block, both header and contents, regardless of it type
997 * @param tng_data is a trajectory data container.
998 * @param block is a general block container.
999 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1000 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1002 /* Disabled until it is used.*/
1004 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1005 // tng_gen_block_t block)
1007 // if(!block->header_contents)
1009 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1010 // return(TNG_FAILURE);
1012 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1013 // tng_data->output_file) != 1)
1015 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1016 // __FILE__, __LINE__);
1017 // return(TNG_CRITICAL);
1020 // if(!block->block_contents)
1022 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1023 // __FILE__, __LINE__);
1024 // return(TNG_FAILURE);
1026 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1027 // tng_data->output_file) != 1)
1029 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1030 // __FILE__, __LINE__);
1031 // return(TNG_CRITICAL);
1033 // return(TNG_SUCCESS);
1037 /** Update the md5 hash of a block already written to the file
1038 * @param tng_data is a trajectory data container.
1039 * @param block is the block, of which to update the md5 hash.
1040 * @param header_start_pos is the file position where the block header starts.
1041 * @param contents_start_pos is the file position where the block contents
1043 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1044 * error has occured.
1046 static tng_function_status
tng_md5_hash_update(tng_trajectory_t tng_data
,
1047 tng_gen_block_t block
,
1048 const int64_t header_start_pos
,
1049 const int64_t contents_start_pos
)
1051 if(block
->block_contents
)
1053 free(block
->block_contents
);
1056 block
->block_contents
= malloc(block
->block_contents_size
);
1057 if(!block
->block_contents
)
1059 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
1060 block
->block_contents_size
, __FILE__
, __LINE__
);
1061 return(TNG_CRITICAL
);
1064 fseek(tng_data
->output_file
, (long)contents_start_pos
, SEEK_SET
);
1065 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
1066 tng_data
->output_file
) == 0)
1068 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
1069 return(TNG_CRITICAL
);
1072 tng_block_md5_hash_generate(block
);
1074 fseek(tng_data
->output_file
, (long)header_start_pos
+ 3 * sizeof(int64_t),
1076 fwrite(block
->md5_hash
, TNG_MD5_HASH_LEN
, 1, tng_data
->output_file
);
1078 return(TNG_SUCCESS
);
1081 /** Update the frame set pointers in the file header (general info block),
1082 * already written to disk
1083 * @param tng_data is a trajectory data container.
1084 * @param hash_mode specifies whether to update the block md5 hash when
1085 * updating the pointers.
1086 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1087 * error has occured.
1089 static tng_function_status tng_header_pointers_update
1090 (tng_trajectory_t tng_data
, const char hash_mode
)
1092 tng_gen_block_t block
;
1093 FILE *temp
= tng_data
->input_file
;
1094 int64_t output_file_pos
, pos
, contents_start_pos
;
1096 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
1098 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
1099 __FILE__
, __LINE__
);
1100 return(TNG_CRITICAL
);
1103 tng_data
->input_file
= tng_data
->output_file
;
1105 tng_block_init(&block
);
1107 output_file_pos
= ftell(tng_data
->output_file
);
1108 fseek(tng_data
->output_file
, 0, SEEK_SET
);
1110 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1112 fprintf(stderr
, "TNG library: Cannot read general info header. %s: %d\n",
1113 __FILE__
, __LINE__
);
1114 tng_data
->input_file
= temp
;
1115 tng_block_destroy(&block
);
1116 return(TNG_CRITICAL
);
1119 contents_start_pos
= ftell(tng_data
->output_file
);
1121 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- 5 *
1122 sizeof(int64_t), SEEK_CUR
);
1124 tng_data
->input_file
= temp
;
1126 pos
= tng_data
->first_trajectory_frame_set_output_file_pos
;
1128 if(tng_data
->input_endianness_swap_func_64
)
1130 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1134 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1135 __FILE__
, __LINE__
);
1139 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1141 tng_block_destroy(&block
);
1142 return(TNG_CRITICAL
);
1145 pos
= tng_data
->last_trajectory_frame_set_output_file_pos
;
1147 if(tng_data
->input_endianness_swap_func_64
)
1149 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1153 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1154 __FILE__
, __LINE__
);
1159 sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1161 tng_block_destroy(&block
);
1162 return(TNG_CRITICAL
);
1165 if(hash_mode
== TNG_USE_HASH
)
1167 tng_md5_hash_update(tng_data
, block
, 0, contents_start_pos
);
1170 tng_block_destroy(&block
);
1172 fseek(tng_data
->output_file
, (long)output_file_pos
, SEEK_SET
);
1174 return(TNG_SUCCESS
);
1177 /** Update the frame set pointers in the current frame set block, already
1178 * written to disk. It also updates the pointers of the blocks pointing to
1179 * the current frame set block.
1180 * @param tng_data is a trajectory data container.
1181 * @param hash_mode specifies whether to update the block md5 hash when
1182 * updating the pointers.
1183 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1184 * error has occured.
1186 static tng_function_status tng_frame_set_pointers_update
1187 (tng_trajectory_t tng_data
, const char hash_mode
)
1189 tng_gen_block_t block
;
1190 tng_trajectory_frame_set_t frame_set
;
1191 FILE *temp
= tng_data
->input_file
;
1192 int64_t pos
, output_file_pos
, contents_start_pos
;
1194 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
1196 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
1197 __FILE__
, __LINE__
);
1198 return(TNG_CRITICAL
);
1201 tng_block_init(&block
);
1202 output_file_pos
= ftell(tng_data
->output_file
);
1204 tng_data
->input_file
= tng_data
->output_file
;
1206 frame_set
= &tng_data
->current_trajectory_frame_set
;
1208 pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
1210 /* Update next frame set */
1211 if(frame_set
->next_frame_set_file_pos
> 0)
1213 fseek(tng_data
->output_file
, (long)frame_set
->next_frame_set_file_pos
,
1216 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1218 fprintf(stderr
, "TNG library: Cannot read frame header. %s: %d\n",
1219 __FILE__
, __LINE__
);
1220 tng_data
->input_file
= temp
;
1221 tng_block_destroy(&block
);
1222 return(TNG_CRITICAL
);
1225 contents_start_pos
= ftell(tng_data
->output_file
);
1227 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (5 *
1228 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1230 if(tng_data
->input_endianness_swap_func_64
)
1232 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1236 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1237 __FILE__
, __LINE__
);
1241 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1243 tng_data
->input_file
= temp
;
1244 tng_block_destroy(&block
);
1245 return(TNG_CRITICAL
);
1248 if(hash_mode
== TNG_USE_HASH
)
1250 tng_md5_hash_update(tng_data
, block
, frame_set
->next_frame_set_file_pos
,
1251 contents_start_pos
);
1253 fseek(tng_data
->output_file
, (long)output_file_pos
, SEEK_SET
);
1255 /* Update previous frame set */
1256 if(frame_set
->prev_frame_set_file_pos
> 0)
1258 fseek(tng_data
->output_file
, (long)frame_set
->prev_frame_set_file_pos
,
1261 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1263 fprintf(stderr
, "TNG library: Cannot read frame header. %s: %d\n",
1264 __FILE__
, __LINE__
);
1265 tng_data
->input_file
= temp
;
1266 tng_block_destroy(&block
);
1267 return(TNG_CRITICAL
);
1270 contents_start_pos
= ftell(tng_data
->output_file
);
1272 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (6 *
1273 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1275 if(tng_data
->input_endianness_swap_func_64
)
1277 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1281 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1282 __FILE__
, __LINE__
);
1286 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1288 tng_data
->input_file
= temp
;
1289 tng_block_destroy(&block
);
1290 return(TNG_CRITICAL
);
1293 if(hash_mode
== TNG_USE_HASH
)
1295 tng_md5_hash_update(tng_data
, block
, frame_set
->prev_frame_set_file_pos
,
1296 contents_start_pos
);
1298 fseek(tng_data
->output_file
, (long)output_file_pos
, SEEK_SET
);
1301 /* Update the frame set one medium stride step after */
1302 if(frame_set
->medium_stride_next_frame_set_file_pos
> 0)
1304 fseek(tng_data
->output_file
,
1305 (long)frame_set
->medium_stride_next_frame_set_file_pos
,
1308 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1310 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1311 __FILE__
, __LINE__
);
1312 tng_data
->input_file
= temp
;
1313 tng_block_destroy(&block
);
1314 return(TNG_CRITICAL
);
1317 contents_start_pos
= ftell(tng_data
->output_file
);
1319 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (3 *
1320 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1322 if(tng_data
->input_endianness_swap_func_64
)
1324 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1328 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1329 __FILE__
, __LINE__
);
1333 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1335 tng_data
->input_file
= temp
;
1336 tng_block_destroy(&block
);
1337 return(TNG_CRITICAL
);
1340 if(hash_mode
== TNG_USE_HASH
)
1342 tng_md5_hash_update(tng_data
, block
,
1343 frame_set
->medium_stride_next_frame_set_file_pos
,
1344 contents_start_pos
);
1347 /* Update the frame set one medium stride step before */
1348 if(frame_set
->medium_stride_prev_frame_set_file_pos
> 0)
1350 fseek(tng_data
->output_file
,
1351 (long)frame_set
->medium_stride_prev_frame_set_file_pos
,
1354 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1356 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1357 __FILE__
, __LINE__
);
1358 tng_data
->input_file
= temp
;
1359 tng_block_destroy(&block
);
1360 return(TNG_CRITICAL
);
1363 contents_start_pos
= ftell(tng_data
->output_file
);
1365 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (4 *
1366 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1368 if(tng_data
->input_endianness_swap_func_64
)
1370 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1374 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1375 __FILE__
, __LINE__
);
1379 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1381 tng_data
->input_file
= temp
;
1382 tng_block_destroy(&block
);
1383 return(TNG_CRITICAL
);
1386 if(hash_mode
== TNG_USE_HASH
)
1388 tng_md5_hash_update(tng_data
, block
,
1389 frame_set
->medium_stride_prev_frame_set_file_pos
,
1390 contents_start_pos
);
1394 /* Update the frame set one long stride step after */
1395 if(frame_set
->long_stride_next_frame_set_file_pos
> 0)
1397 fseek(tng_data
->output_file
,
1398 (long)frame_set
->long_stride_next_frame_set_file_pos
,
1401 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1403 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1404 __FILE__
, __LINE__
);
1405 tng_data
->input_file
= temp
;
1406 tng_block_destroy(&block
);
1407 return(TNG_CRITICAL
);
1410 contents_start_pos
= ftell(tng_data
->output_file
);
1412 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (1 *
1413 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1415 if(tng_data
->input_endianness_swap_func_64
)
1417 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1421 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1422 __FILE__
, __LINE__
);
1426 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1428 tng_data
->input_file
= temp
;
1429 tng_block_destroy(&block
);
1430 return(TNG_CRITICAL
);
1433 if(hash_mode
== TNG_USE_HASH
)
1435 tng_md5_hash_update(tng_data
, block
,
1436 frame_set
->long_stride_next_frame_set_file_pos
,
1437 contents_start_pos
);
1440 /* Update the frame set one long stride step before */
1441 if(frame_set
->long_stride_prev_frame_set_file_pos
> 0)
1443 fseek(tng_data
->output_file
,
1444 (long)frame_set
->long_stride_prev_frame_set_file_pos
,
1447 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
1449 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
1450 __FILE__
, __LINE__
);
1451 tng_data
->input_file
= temp
;
1452 tng_block_destroy(&block
);
1453 return(TNG_CRITICAL
);
1456 contents_start_pos
= ftell(tng_data
->output_file
);
1458 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (2 *
1459 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
1461 if(tng_data
->input_endianness_swap_func_64
)
1463 if(tng_data
->input_endianness_swap_func_64(tng_data
,
1467 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1468 __FILE__
, __LINE__
);
1472 if(fwrite(&pos
, sizeof(int64_t), 1, tng_data
->output_file
) != 1)
1474 tng_data
->input_file
= temp
;
1475 tng_block_destroy(&block
);
1476 return(TNG_CRITICAL
);
1479 if(hash_mode
== TNG_USE_HASH
)
1481 tng_md5_hash_update(tng_data
, block
,
1482 frame_set
->long_stride_prev_frame_set_file_pos
,
1483 contents_start_pos
);
1487 fseek(tng_data
->output_file
, (long)output_file_pos
, SEEK_SET
);
1489 tng_data
->input_file
= temp
;
1491 tng_block_destroy(&block
);
1493 return(TNG_SUCCESS
);
1496 static tng_function_status tng_reread_frame_set_at_file_pos
1497 (tng_trajectory_t tng_data
,
1500 tng_gen_block_t block
;
1501 tng_function_status stat
;
1503 tng_block_init(&block
);
1505 fseek(tng_data
->input_file
, pos
, SEEK_SET
);
1508 stat
= tng_block_header_read(tng_data
, block
);
1509 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1511 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n", pos
,
1512 __FILE__
, __LINE__
);
1513 tng_block_destroy(&block
);
1514 return(TNG_FAILURE
);
1517 if(tng_block_read_next(tng_data
, block
,
1518 TNG_SKIP_HASH
) != TNG_SUCCESS
)
1520 tng_block_destroy(&block
);
1521 return(TNG_CRITICAL
);
1525 tng_block_destroy(&block
);
1527 return(TNG_SUCCESS
);
1530 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1531 (tng_trajectory_t tng_data
,
1534 int64_t orig_pos
, curr_frame_set_pos
;
1535 tng_gen_block_t block
;
1536 tng_function_status stat
;
1537 tng_trajectory_frame_set_t frame_set
=
1538 &tng_data
->current_trajectory_frame_set
;
1540 orig_pos
= ftell(tng_data
->input_file
);
1541 curr_frame_set_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
1543 *pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
1547 return(TNG_SUCCESS
);
1550 fseek(tng_data
->input_file
, *pos
, SEEK_SET
);
1552 tng_block_init(&block
);
1553 /* Read block headers first to see that a frame set block is found. */
1554 stat
= tng_block_header_read(tng_data
, block
);
1555 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1557 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n", *pos
,
1558 __FILE__
, __LINE__
);
1559 tng_block_destroy(&block
);
1560 return(TNG_FAILURE
);
1563 if(tng_block_read_next(tng_data
, block
,
1564 TNG_SKIP_HASH
) != TNG_SUCCESS
)
1566 tng_block_destroy(&block
);
1567 return(TNG_CRITICAL
);
1570 /* Read all frame set blocks (not the blocks between them) */
1571 while(frame_set
->next_frame_set_file_pos
> 0)
1573 fseek(tng_data
->input_file
, frame_set
->next_frame_set_file_pos
, SEEK_SET
);
1574 stat
= tng_block_header_read(tng_data
, block
);
1575 if(stat
== TNG_CRITICAL
)
1577 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n", *pos
,
1578 __FILE__
, __LINE__
);
1579 tng_block_destroy(&block
);
1580 return(TNG_CRITICAL
);
1582 if(stat
!= TNG_SUCCESS
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1584 return(TNG_FAILURE
);
1587 stat
= tng_block_read_next(tng_data
, block
, TNG_SKIP_HASH
);
1588 if(stat
!= TNG_SUCCESS
)
1590 tng_block_destroy(&block
);
1593 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1594 if(tng_data
->current_trajectory_frame_set_input_file_pos
< *pos
&&
1595 tng_data
->current_trajectory_frame_set_input_file_pos
> orig_pos
)
1597 *pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
1601 /* Re-read the frame set that used to be the current one */
1602 tng_reread_frame_set_at_file_pos(tng_data
, curr_frame_set_pos
);
1604 fseek(tng_data
->input_file
, orig_pos
, SEEK_SET
);
1606 tng_block_destroy(&block
);
1608 return(TNG_SUCCESS
);
1611 static tng_function_status tng_frame_set_complete_migrate
1612 (tng_trajectory_t tng_data
,
1613 int64_t block_start_pos
,
1618 tng_bool updated
= TNG_FALSE
;
1622 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
1624 return(TNG_CRITICAL
);
1627 fseek(tng_data
->input_file
, block_start_pos
, SEEK_SET
);
1629 contents
= malloc(block_len
);
1632 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
1633 block_len
, __FILE__
, __LINE__
);
1634 return(TNG_CRITICAL
);
1637 if(fread(contents
, block_len
, 1, tng_data
->input_file
) == 0)
1639 fprintf(stderr
, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1640 __FILE__
, __LINE__
);
1642 return(TNG_CRITICAL
);
1644 fseek(tng_data
->output_file
, new_pos
, SEEK_SET
);
1646 if(fwrite(contents
, block_len
, 1, tng_data
->output_file
) != 1)
1648 fprintf(stderr
, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1649 __FILE__
, __LINE__
);
1651 return(TNG_CRITICAL
);
1654 tng_data
->current_trajectory_frame_set_output_file_pos
= new_pos
;
1656 tng_frame_set_pointers_update(tng_data
, TNG_USE_HASH
);
1658 /* Update the general info block if needed */
1659 if(block_start_pos
== tng_data
->first_trajectory_frame_set_output_file_pos
)
1661 tng_data
->first_trajectory_frame_set_output_file_pos
= new_pos
;
1664 if(block_start_pos
== tng_data
->last_trajectory_frame_set_output_file_pos
)
1666 tng_data
->last_trajectory_frame_set_output_file_pos
= new_pos
;
1671 tng_header_pointers_update(tng_data
, TNG_USE_HASH
);
1674 /* Fill the block with NULL to avoid confusion. */
1675 for(i
= 0; i
< block_len
; i
++)
1679 fseek(tng_data
->output_file
, block_start_pos
, SEEK_SET
);
1681 /* FIXME: casting block_len to size_t is dangerous */
1682 fwrite(contents
, 1, block_len
, tng_data
->output_file
);
1686 return(TNG_SUCCESS
);
1689 static tng_function_status tng_length_of_current_frame_set_contents_get
1690 (tng_trajectory_t tng_data
,
1693 int64_t orig_pos
, pos
, curr_frame_set_pos
;
1694 tng_gen_block_t block
;
1695 tng_function_status stat
;
1697 orig_pos
= ftell(tng_data
->input_file
);
1698 curr_frame_set_pos
= pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
1702 fseek(tng_data
->input_file
, curr_frame_set_pos
, SEEK_SET
);
1704 tng_block_init(&block
);
1705 /* Read block headers first to see that a frame set block is found. */
1706 stat
= tng_block_header_read(tng_data
, block
);
1707 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1709 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
1710 curr_frame_set_pos
, __FILE__
, __LINE__
);
1711 tng_block_destroy(&block
);
1712 return(TNG_FAILURE
);
1715 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1716 while(stat
== TNG_SUCCESS
)
1718 fseek(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
1719 *len
+= block
->header_contents_size
+ block
->block_contents_size
;
1720 pos
+= block
->header_contents_size
+ block
->block_contents_size
;
1721 if(pos
>= tng_data
->input_file_len
)
1725 stat
= tng_block_header_read(tng_data
, block
);
1726 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
1732 /* Re-read the frame set that used to be the current one */
1733 tng_reread_frame_set_at_file_pos(tng_data
, curr_frame_set_pos
);
1735 fseek(tng_data
->input_file
, orig_pos
, SEEK_SET
);
1737 tng_block_destroy(&block
);
1739 return(TNG_SUCCESS
);
1742 /** Migrate blocks in the file to make room for new data in a block. This
1743 * is required e.g. when adding data to a block or extending strings in a
1745 * @param tng_data is a trajectory data container.
1746 * @param start_pos is the position from which to start moving data, usually
1747 * the byte after the end of the block to which data was added.
1748 * @param offset is the number of bytes that were inserted.
1749 * @details Trajectory blocks (frame sets and their related blocks) are moved
1750 * to the end of the file (if needed) in order to make room for non-trajectory
1753 static tng_function_status tng_migrate_data_in_file
1754 (tng_trajectory_t tng_data
,
1758 int64_t traj_start_pos
, empty_space
, orig_file_pos
, frame_set_length
;
1759 tng_gen_block_t block
;
1760 tng_function_status stat
;
1765 return(TNG_SUCCESS
);
1768 temp
= tng_data
->input_file
;
1770 stat
= tng_file_pos_of_subsequent_trajectory_block_get(tng_data
, &traj_start_pos
);
1771 if(stat
!= TNG_SUCCESS
)
1773 tng_data
->input_file
= temp
;
1777 tng_data
->current_trajectory_frame_set_input_file_pos
= traj_start_pos
;
1779 empty_space
= traj_start_pos
- (start_pos
- 1);
1781 if(empty_space
>= offset
)
1783 return(TNG_SUCCESS
);
1786 orig_file_pos
= ftell(tng_data
->input_file
);
1787 tng_block_init(&block
);
1789 while(empty_space
< offset
)
1791 fseek(tng_data
->input_file
, traj_start_pos
, SEEK_SET
);
1792 stat
= tng_block_header_read(tng_data
, block
);
1793 if(stat
== TNG_CRITICAL
)
1795 fprintf(stderr
, "TNG library: Cannot read block header. %s: %d\n",
1796 __FILE__
, __LINE__
);
1797 tng_block_destroy(&block
);
1798 tng_data
->input_file
= temp
;
1799 return(TNG_CRITICAL
);
1801 if(stat
!= TNG_SUCCESS
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
1803 tng_data
->input_file
= temp
;
1804 tng_block_destroy(&block
);
1805 return(TNG_FAILURE
);
1807 stat
= tng_length_of_current_frame_set_contents_get(tng_data
, &frame_set_length
);
1808 if(stat
!= TNG_SUCCESS
)
1810 tng_data
->input_file
= temp
;
1811 tng_block_destroy(&block
);
1814 stat
= tng_frame_set_complete_migrate(tng_data
, traj_start_pos
,
1815 frame_set_length
, tng_data
->input_file_len
);
1816 if(stat
!= TNG_SUCCESS
)
1818 tng_data
->input_file
= temp
;
1819 tng_block_destroy(&block
);
1823 empty_space
+= frame_set_length
;
1825 fseek(tng_data
->input_file
, orig_file_pos
, SEEK_SET
);
1826 tng_block_destroy(&block
);
1828 return(TNG_SUCCESS
);
1831 static tng_function_status tng_block_header_len_calculate
1832 (const tng_trajectory_t tng_data
,
1833 tng_gen_block_t block
,
1839 /* If the string is unallocated allocate memory for just string
1843 block
->name
= malloc(1);
1846 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1847 __FILE__
, __LINE__
);
1848 return(TNG_CRITICAL
);
1853 name_len
= tng_min_i((int)strlen(block
->name
) + 1, TNG_MAX_STR_LEN
);
1855 /* Calculate the size of the header to write */
1856 *len
= sizeof(block
->header_contents_size
) +
1857 sizeof(block
->block_contents_size
) +
1859 sizeof(block
->block_version
) +
1863 return (TNG_SUCCESS
);
1866 /** Write the header of a data block, regardless of its type
1867 * @param tng_data is a trajectory data container.
1868 * @param block is a general block container.
1869 * @param hash_mode is an option to decide whether to use the md5 hash or not.
1870 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
1871 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1872 * error has occured.
1874 static tng_function_status tng_block_header_write
1875 (tng_trajectory_t tng_data
,
1876 tng_gen_block_t block
,
1877 const char hash_mode
)
1879 int name_len
, offset
= 0;
1881 TNG_ASSERT(block
!= 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
1883 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
1885 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
1886 __FILE__
, __LINE__
);
1887 return(TNG_CRITICAL
);
1890 if(tng_block_header_len_calculate(tng_data
, block
, &block
->header_contents_size
) !=
1893 fprintf(stderr
, "TNG library: Cannot calculate length of block header. %s: %d\n",
1894 __FILE__
, __LINE__
);
1895 return(TNG_CRITICAL
);
1898 if(hash_mode
== TNG_USE_HASH
)
1900 tng_block_md5_hash_generate(block
);
1903 if(block
->header_contents
)
1905 free(block
->header_contents
);
1908 block
->header_contents
= malloc(block
->header_contents_size
);
1909 if(!block
->header_contents
)
1911 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
1912 block
->header_contents_size
, __FILE__
, __LINE__
);
1913 return(TNG_CRITICAL
);
1916 name_len
= tng_min_i((int)strlen(block
->name
) + 1, TNG_MAX_STR_LEN
);
1918 /* First copy all data into the header_contents block and finally write
1919 * the whole block at once. */
1920 memcpy(block
->header_contents
, &block
->header_contents_size
,
1921 sizeof(block
->header_contents_size
));
1922 if(tng_data
->output_endianness_swap_func_64
)
1924 if(tng_data
->output_endianness_swap_func_64(tng_data
,
1925 (int64_t *)block
->header_contents
+offset
)
1928 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1929 __FILE__
, __LINE__
);
1932 offset
+= sizeof(block
->header_contents_size
);
1934 memcpy(block
->header_contents
+offset
, &block
->block_contents_size
,
1935 sizeof(block
->block_contents_size
));
1936 if(tng_data
->output_endianness_swap_func_64
)
1938 if(tng_data
->output_endianness_swap_func_64(tng_data
,
1939 (int64_t *)block
->header_contents
+offset
)
1942 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1943 __FILE__
, __LINE__
);
1946 offset
+= sizeof(block
->block_contents_size
);
1948 memcpy(block
->header_contents
+offset
, &block
->id
, sizeof(block
->id
));
1949 if(tng_data
->output_endianness_swap_func_64
)
1951 if(tng_data
->output_endianness_swap_func_64(tng_data
,
1952 (int64_t *)block
->header_contents
+offset
)
1955 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1956 __FILE__
, __LINE__
);
1959 offset
+= sizeof(block
->id
);
1961 memcpy(block
->header_contents
+offset
, block
->md5_hash
, TNG_MD5_HASH_LEN
);
1962 offset
+= TNG_MD5_HASH_LEN
;
1964 strncpy(block
->header_contents
+offset
, block
->name
, name_len
);
1967 memcpy(block
->header_contents
+offset
, &block
->block_version
,
1968 sizeof(block
->block_version
));
1969 if(tng_data
->output_endianness_swap_func_64
)
1971 if(tng_data
->output_endianness_swap_func_64(tng_data
,
1972 (int64_t *)block
->header_contents
+offset
)
1975 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
1976 __FILE__
, __LINE__
);
1980 if(fwrite(block
->header_contents
, block
->header_contents_size
,
1981 1, tng_data
->output_file
) != 1)
1983 fprintf(stderr
, "TNG library: Could not write all header data. %s: %d\n", __FILE__
, __LINE__
);
1984 return(TNG_CRITICAL
);
1986 return(TNG_SUCCESS
);
1989 static tng_function_status tng_general_info_block_len_calculate
1990 (tng_trajectory_t tng_data
,
1993 int first_program_name_len
, first_user_name_len
;
1994 int first_computer_name_len
, first_pgp_signature_len
;
1995 int last_program_name_len
, last_user_name_len
;
1996 int last_computer_name_len
, last_pgp_signature_len
;
1997 int forcefield_name_len
;
1999 /* If the strings are unallocated allocate memory for just string
2001 if(!tng_data
->first_program_name
)
2003 tng_data
->first_program_name
= malloc(1);
2004 if(!tng_data
->first_program_name
)
2006 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2007 __FILE__
, __LINE__
);
2008 return(TNG_CRITICAL
);
2010 tng_data
->first_program_name
[0] = 0;
2012 if(!tng_data
->last_program_name
)
2014 tng_data
->last_program_name
= malloc(1);
2015 if(!tng_data
->last_program_name
)
2017 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2018 __FILE__
, __LINE__
);
2019 return(TNG_CRITICAL
);
2021 tng_data
->last_program_name
[0] = 0;
2023 if(!tng_data
->first_user_name
)
2025 tng_data
->first_user_name
= malloc(1);
2026 if(!tng_data
->first_user_name
)
2028 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2029 __FILE__
, __LINE__
);
2030 return(TNG_CRITICAL
);
2032 tng_data
->first_user_name
[0] = 0;
2034 if(!tng_data
->last_user_name
)
2036 tng_data
->last_user_name
= malloc(1);
2037 if(!tng_data
->last_user_name
)
2039 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2040 __FILE__
, __LINE__
);
2041 return(TNG_CRITICAL
);
2043 tng_data
->last_user_name
[0] = 0;
2045 if(!tng_data
->first_computer_name
)
2047 tng_data
->first_computer_name
= malloc(1);
2048 if(!tng_data
->first_computer_name
)
2050 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2051 __FILE__
, __LINE__
);
2052 return(TNG_CRITICAL
);
2054 tng_data
->first_computer_name
[0] = 0;
2056 if(!tng_data
->last_computer_name
)
2058 tng_data
->last_computer_name
= malloc(1);
2059 if(!tng_data
->last_computer_name
)
2061 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2062 __FILE__
, __LINE__
);
2063 return(TNG_CRITICAL
);
2065 tng_data
->last_computer_name
[0] = 0;
2067 if(!tng_data
->first_pgp_signature
)
2069 tng_data
->first_pgp_signature
= malloc(1);
2070 if(!tng_data
->first_pgp_signature
)
2072 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2073 __FILE__
, __LINE__
);
2074 return(TNG_CRITICAL
);
2076 tng_data
->first_pgp_signature
[0] = 0;
2078 if(!tng_data
->last_pgp_signature
)
2080 tng_data
->last_pgp_signature
= malloc(1);
2081 if(!tng_data
->last_pgp_signature
)
2083 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2084 __FILE__
, __LINE__
);
2085 return(TNG_CRITICAL
);
2087 tng_data
->last_pgp_signature
[0] = 0;
2089 if(!tng_data
->forcefield_name
)
2091 tng_data
->forcefield_name
= malloc(1);
2092 if(!tng_data
->forcefield_name
)
2094 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2095 __FILE__
, __LINE__
);
2096 return(TNG_CRITICAL
);
2098 tng_data
->forcefield_name
[0] = 0;
2101 first_program_name_len
= tng_min_i((int)strlen(tng_data
->first_program_name
) + 1,
2103 last_program_name_len
= tng_min_i((int)strlen(tng_data
->last_program_name
) + 1,
2105 first_user_name_len
= tng_min_i((int)strlen(tng_data
->first_user_name
) + 1,
2107 last_user_name_len
= tng_min_i((int)strlen(tng_data
->last_user_name
) + 1,
2109 first_computer_name_len
= tng_min_i((int)strlen(tng_data
->first_computer_name
) + 1,
2111 last_computer_name_len
= tng_min_i((int)strlen(tng_data
->last_computer_name
) + 1,
2113 first_pgp_signature_len
= tng_min_i((int)strlen(tng_data
->first_pgp_signature
) + 1,
2115 last_pgp_signature_len
= tng_min_i((int)strlen(tng_data
->last_pgp_signature
) + 1,
2117 forcefield_name_len
= tng_min_i((int)strlen(tng_data
->forcefield_name
) + 1,
2120 *len
= sizeof(tng_data
->time
) +
2121 sizeof(tng_data
->var_num_atoms_flag
) +
2122 sizeof(tng_data
->frame_set_n_frames
) +
2123 sizeof(tng_data
->first_trajectory_frame_set_input_file_pos
) +
2124 sizeof(tng_data
->last_trajectory_frame_set_input_file_pos
) +
2125 sizeof(tng_data
->medium_stride_length
) +
2126 sizeof(tng_data
->long_stride_length
) +
2127 sizeof(tng_data
->distance_unit_exponential
) +
2128 first_program_name_len
+
2129 last_program_name_len
+
2130 first_user_name_len
+
2131 last_user_name_len
+
2132 first_computer_name_len
+
2133 last_computer_name_len
+
2134 first_pgp_signature_len
+
2135 last_pgp_signature_len
+
2136 forcefield_name_len
;
2138 return(TNG_SUCCESS
);
2141 /** Read a general info block. This is the first block of a TNG file.
2142 * Populate the fields in tng_data.
2143 * @param tng_data is a trajectory data container.
2144 * @param block is a general block container.
2145 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2146 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2147 * compared to the md5 hash of the read contents to ensure valid data.
2148 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2149 * error has occured.
2151 static tng_function_status tng_general_info_block_read
2152 (tng_trajectory_t tng_data
, tng_gen_block_t block
,
2153 const char hash_mode
)
2155 int len
, offset
= 0;
2160 TNG_ASSERT(block
!= 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2162 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
2164 return(TNG_CRITICAL
);
2167 temp
= realloc(block
->block_contents
, block
->block_contents_size
);
2170 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
2171 block
->block_contents_size
, __FILE__
, __LINE__
);
2172 free(block
->block_contents
);
2173 block
->block_contents
= 0;
2174 return(TNG_CRITICAL
);
2176 block
->block_contents
= temp
;
2178 /* Read the whole block into block_contents to be able to write it to disk
2179 * even if it cannot be interpreted. */
2180 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
2181 tng_data
->input_file
) == 0)
2183 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
2184 return(TNG_CRITICAL
);
2187 /* FIXME: Does not check if the size of the contents matches the expected
2188 * size or if the contents can be read. */
2190 if(hash_mode
== TNG_USE_HASH
)
2192 tng_md5_hash_match_verify(block
, &same_hash
);
2193 if(same_hash
!= TNG_TRUE
)
2195 fprintf(stderr
, "TNG library: General info block contents corrupt. Hashes do not match. "
2197 __FILE__
, __LINE__
);
2198 /* return(TNG_FAILURE); */
2202 len
= tng_min_i((int)strlen(block
->block_contents
) + 1, TNG_MAX_STR_LEN
);
2203 temp
= realloc(tng_data
->first_program_name
, len
);
2206 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2207 __FILE__
, __LINE__
);
2208 free(tng_data
->first_program_name
);
2209 tng_data
->first_program_name
= 0;
2210 return(TNG_CRITICAL
);
2212 tng_data
->first_program_name
= temp
;
2213 strncpy(tng_data
->first_program_name
, block
->block_contents
, len
);
2216 len
= tng_min_i((int)strlen(block
->block_contents
+ offset
) + 1, TNG_MAX_STR_LEN
);
2217 temp
= realloc(tng_data
->last_program_name
, len
);
2220 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2221 __FILE__
, __LINE__
);
2222 free(tng_data
->last_program_name
);
2223 tng_data
->last_program_name
= 0;
2224 return(TNG_CRITICAL
);
2226 tng_data
->last_program_name
= temp
;
2227 strncpy(tng_data
->last_program_name
, block
->block_contents
+ offset
, len
);
2230 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2231 temp
= realloc(tng_data
->first_user_name
, len
);
2234 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2235 __FILE__
, __LINE__
);
2236 free(tng_data
->first_user_name
);
2237 tng_data
->first_user_name
= 0;
2238 return(TNG_CRITICAL
);
2240 tng_data
->first_user_name
= temp
;
2241 strncpy(tng_data
->first_user_name
, block
->block_contents
+offset
, len
);
2244 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2245 temp
= realloc(tng_data
->last_user_name
, len
);
2248 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2249 __FILE__
, __LINE__
);
2250 free(tng_data
->last_user_name
);
2251 tng_data
->last_user_name
= 0;
2252 return(TNG_CRITICAL
);
2254 tng_data
->last_user_name
= temp
;
2255 strncpy(tng_data
->last_user_name
, block
->block_contents
+offset
, len
);
2258 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2259 temp
= realloc(tng_data
->first_computer_name
, len
);
2262 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2263 __FILE__
, __LINE__
);
2264 free(tng_data
->first_computer_name
);
2265 tng_data
->first_computer_name
= 0;
2266 return(TNG_CRITICAL
);
2268 tng_data
->first_computer_name
= temp
;
2269 strncpy(tng_data
->first_computer_name
, block
->block_contents
+offset
, len
);
2272 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2273 temp
= realloc(tng_data
->last_computer_name
, len
);
2276 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2277 __FILE__
, __LINE__
);
2278 free(tng_data
->last_computer_name
);
2279 tng_data
->last_computer_name
= 0;
2280 return(TNG_CRITICAL
);
2282 tng_data
->last_computer_name
= temp
;
2283 strncpy(tng_data
->last_computer_name
, block
->block_contents
+offset
, len
);
2286 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2287 temp
= realloc(tng_data
->first_pgp_signature
, len
);
2290 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2291 __FILE__
, __LINE__
);
2292 free(tng_data
->first_pgp_signature
);
2293 tng_data
->first_pgp_signature
= 0;
2294 return(TNG_CRITICAL
);
2296 tng_data
->first_pgp_signature
= temp
;
2297 strncpy(tng_data
->first_pgp_signature
, block
->block_contents
+offset
, len
);
2300 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2301 temp
= realloc(tng_data
->last_pgp_signature
, len
);
2304 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2305 __FILE__
, __LINE__
);
2306 free(tng_data
->last_pgp_signature
);
2307 tng_data
->last_pgp_signature
= 0;
2308 return(TNG_CRITICAL
);
2310 tng_data
->last_pgp_signature
= temp
;
2311 strncpy(tng_data
->last_pgp_signature
, block
->block_contents
+offset
, len
);
2314 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
2315 temp
= realloc(tng_data
->forcefield_name
, len
);
2318 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
2319 __FILE__
, __LINE__
);
2320 free(tng_data
->forcefield_name
);
2321 tng_data
->forcefield_name
= 0;
2322 return(TNG_CRITICAL
);
2324 tng_data
->forcefield_name
= temp
;
2325 strncpy(tng_data
->forcefield_name
, block
->block_contents
+offset
, len
);
2328 memcpy(&tng_data
->time
, block
->block_contents
+offset
,
2329 sizeof(tng_data
->time
));
2330 if(tng_data
->input_endianness_swap_func_64
)
2332 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2336 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2337 __FILE__
, __LINE__
);
2340 offset
+= sizeof(tng_data
->time
);
2342 memcpy(&tng_data
->var_num_atoms_flag
, block
->block_contents
+offset
,
2343 sizeof(tng_data
->var_num_atoms_flag
));
2344 offset
+= sizeof(tng_data
->var_num_atoms_flag
);
2346 memcpy(&tng_data
->frame_set_n_frames
, block
->block_contents
+offset
,
2347 sizeof(tng_data
->frame_set_n_frames
));
2348 if(tng_data
->input_endianness_swap_func_64
)
2350 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2351 &tng_data
->frame_set_n_frames
)
2354 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2355 __FILE__
, __LINE__
);
2358 offset
+= sizeof(tng_data
->frame_set_n_frames
);
2360 memcpy(&tng_data
->first_trajectory_frame_set_input_file_pos
,
2361 block
->block_contents
+offset
,
2362 sizeof(tng_data
->first_trajectory_frame_set_input_file_pos
));
2363 if(tng_data
->input_endianness_swap_func_64
)
2365 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2366 &tng_data
->first_trajectory_frame_set_input_file_pos
)
2369 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2370 __FILE__
, __LINE__
);
2373 offset
+= sizeof(tng_data
->first_trajectory_frame_set_input_file_pos
);
2375 tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
=
2376 tng_data
->first_trajectory_frame_set_input_file_pos
;
2379 memcpy(&tng_data
->last_trajectory_frame_set_input_file_pos
,
2380 block
->block_contents
+offset
,
2381 sizeof(tng_data
->last_trajectory_frame_set_input_file_pos
));
2382 if(tng_data
->input_endianness_swap_func_64
)
2384 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2385 &tng_data
->last_trajectory_frame_set_input_file_pos
)
2388 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2389 __FILE__
, __LINE__
);
2392 offset
+= sizeof(tng_data
->last_trajectory_frame_set_input_file_pos
);
2394 memcpy(&tng_data
->medium_stride_length
, block
->block_contents
+offset
,
2395 sizeof(tng_data
->medium_stride_length
));
2396 if(tng_data
->input_endianness_swap_func_64
)
2398 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2399 &tng_data
->medium_stride_length
)
2402 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2403 __FILE__
, __LINE__
);
2406 offset
+= sizeof(tng_data
->medium_stride_length
);
2408 memcpy(&tng_data
->long_stride_length
, block
->block_contents
+offset
,
2409 sizeof(tng_data
->long_stride_length
));
2410 if(tng_data
->input_endianness_swap_func_64
)
2412 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2413 &tng_data
->long_stride_length
)
2416 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2417 __FILE__
, __LINE__
);
2420 offset
+= sizeof(tng_data
->long_stride_length
);
2422 if(block
->block_version
>= 3)
2424 memcpy(&tng_data
->distance_unit_exponential
, block
->block_contents
+offset
,
2425 sizeof(tng_data
->distance_unit_exponential
));
2426 if(tng_data
->input_endianness_swap_func_64
)
2428 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2429 &tng_data
->distance_unit_exponential
)
2432 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2433 __FILE__
, __LINE__
);
2438 return(TNG_SUCCESS
);
2441 /** Write a general info block. This is the first block of a TNG file.
2442 * @param tng_data is a trajectory data container.
2443 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2444 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2445 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2446 * error has occured.
2448 static tng_function_status tng_general_info_block_write
2449 (tng_trajectory_t tng_data
,
2450 const char hash_mode
)
2452 int first_program_name_len
, first_user_name_len
;
2453 int first_computer_name_len
, first_pgp_signature_len
;
2454 int last_program_name_len
, last_user_name_len
;
2455 int last_computer_name_len
, last_pgp_signature_len
;
2456 int forcefield_name_len
, name_len
;
2458 tng_gen_block_t block
;
2460 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
2462 return(TNG_CRITICAL
);
2465 fseek(tng_data
->output_file
, 0, SEEK_SET
);
2467 tng_block_init(&block
);
2469 name_len
= (int)strlen("GENERAL INFO");
2471 block
->name
= malloc(name_len
+ 1);
2474 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
2475 name_len
+1, __FILE__
, __LINE__
);
2476 tng_block_destroy(&block
);
2477 return(TNG_CRITICAL
);
2480 strcpy(block
->name
, "GENERAL INFO");
2481 block
->id
= TNG_GENERAL_INFO
;
2483 if(tng_general_info_block_len_calculate(tng_data
, &block
->block_contents_size
) !=
2486 fprintf(stderr
, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2487 __FILE__
, __LINE__
);
2488 tng_block_destroy(&block
);
2489 return(TNG_CRITICAL
);
2492 first_program_name_len
= tng_min_i((int)strlen(tng_data
->first_program_name
) + 1,
2494 last_program_name_len
= tng_min_i((int)strlen(tng_data
->last_program_name
) + 1,
2496 first_user_name_len
= tng_min_i((int)strlen(tng_data
->first_user_name
) + 1,
2498 last_user_name_len
= tng_min_i((int)strlen(tng_data
->last_user_name
) + 1,
2500 first_computer_name_len
= tng_min_i((int)strlen(tng_data
->first_computer_name
) + 1,
2502 last_computer_name_len
= tng_min_i((int)strlen(tng_data
->last_computer_name
) + 1,
2504 first_pgp_signature_len
= tng_min_i((int)strlen(tng_data
->first_pgp_signature
) + 1,
2506 last_pgp_signature_len
= tng_min_i((int)strlen(tng_data
->last_pgp_signature
) + 1,
2508 forcefield_name_len
= tng_min_i((int)strlen(tng_data
->forcefield_name
) + 1,
2511 if(block
->block_contents
)
2513 free(block
->block_contents
);
2515 block
->block_contents
= malloc(block
->block_contents_size
);
2516 if(!block
->block_contents
)
2518 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
2519 block
->block_contents_size
, __FILE__
, __LINE__
);
2520 tng_block_destroy(&block
);
2521 return(TNG_CRITICAL
);
2524 strncpy(block
->block_contents
, tng_data
->first_program_name
, first_program_name_len
);
2525 offset
+= first_program_name_len
;
2527 strncpy(block
->block_contents
+offset
, tng_data
->last_program_name
, last_program_name_len
);
2528 offset
+= last_program_name_len
;
2530 strncpy(block
->block_contents
+offset
, tng_data
->first_user_name
, first_user_name_len
);
2531 offset
+= first_user_name_len
;
2533 strncpy(block
->block_contents
+offset
, tng_data
->last_user_name
, last_user_name_len
);
2534 offset
+= last_user_name_len
;
2536 strncpy(block
->block_contents
+offset
, tng_data
->first_computer_name
,
2537 first_computer_name_len
);
2538 offset
+= first_computer_name_len
;
2540 strncpy(block
->block_contents
+offset
, tng_data
->last_computer_name
,
2541 last_computer_name_len
);
2542 offset
+= last_computer_name_len
;
2544 strncpy(block
->block_contents
+offset
, tng_data
->first_pgp_signature
,
2545 first_pgp_signature_len
);
2546 offset
+= first_pgp_signature_len
;
2548 strncpy(block
->block_contents
+offset
, tng_data
->last_pgp_signature
,
2549 last_pgp_signature_len
);
2550 offset
+= last_pgp_signature_len
;
2552 strncpy(block
->block_contents
+offset
, tng_data
->forcefield_name
,
2553 forcefield_name_len
);
2554 offset
+= forcefield_name_len
;
2556 memcpy(block
->block_contents
+offset
, &tng_data
->time
,
2557 sizeof(tng_data
->time
));
2558 if(tng_data
->output_endianness_swap_func_64
)
2560 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2561 (int64_t *)block
->header_contents
+offset
)
2564 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2565 __FILE__
, __LINE__
);
2568 offset
+= sizeof(tng_data
->time
);
2570 memcpy(block
->block_contents
+offset
, &tng_data
->var_num_atoms_flag
,
2571 sizeof(tng_data
->var_num_atoms_flag
));
2572 offset
+= sizeof(tng_data
->var_num_atoms_flag
);
2574 memcpy(block
->block_contents
+offset
, &tng_data
->frame_set_n_frames
,
2575 sizeof(tng_data
->frame_set_n_frames
));
2576 if(tng_data
->output_endianness_swap_func_64
)
2578 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2579 (int64_t *)block
->header_contents
+offset
)
2582 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2583 __FILE__
, __LINE__
);
2586 offset
+= sizeof(tng_data
->frame_set_n_frames
);
2588 memcpy(block
->block_contents
+offset
,
2589 &tng_data
->first_trajectory_frame_set_output_file_pos
,
2590 sizeof(tng_data
->first_trajectory_frame_set_output_file_pos
));
2591 if(tng_data
->output_endianness_swap_func_64
)
2593 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2594 (int64_t *)block
->header_contents
+offset
)
2597 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2598 __FILE__
, __LINE__
);
2601 offset
+= sizeof(tng_data
->first_trajectory_frame_set_output_file_pos
);
2603 memcpy(block
->block_contents
+offset
,
2604 &tng_data
->last_trajectory_frame_set_output_file_pos
,
2605 sizeof(tng_data
->last_trajectory_frame_set_output_file_pos
));
2606 if(tng_data
->output_endianness_swap_func_64
)
2608 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2609 (int64_t *)block
->header_contents
+offset
)
2612 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2613 __FILE__
, __LINE__
);
2616 offset
+= sizeof(tng_data
->last_trajectory_frame_set_output_file_pos
);
2618 memcpy(block
->block_contents
+offset
, &tng_data
->medium_stride_length
,
2619 sizeof(tng_data
->medium_stride_length
));
2620 if(tng_data
->output_endianness_swap_func_64
)
2622 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2623 (int64_t *)block
->header_contents
+offset
)
2626 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2627 __FILE__
, __LINE__
);
2630 offset
+= sizeof(tng_data
->medium_stride_length
);
2632 memcpy(block
->block_contents
+offset
, &tng_data
->long_stride_length
,
2633 sizeof(tng_data
->long_stride_length
));
2634 if(tng_data
->output_endianness_swap_func_64
)
2636 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2637 (int64_t *)block
->header_contents
+offset
)
2640 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2641 __FILE__
, __LINE__
);
2644 offset
+= sizeof(tng_data
->long_stride_length
);
2646 memcpy(block
->block_contents
+offset
, &tng_data
->distance_unit_exponential
,
2647 sizeof(tng_data
->distance_unit_exponential
));
2648 if(tng_data
->output_endianness_swap_func_64
)
2650 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2651 (int64_t *)block
->header_contents
+offset
)
2654 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2655 __FILE__
, __LINE__
);
2659 if(tng_block_header_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
2661 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
2662 tng_data
->output_file_path
, __FILE__
, __LINE__
);
2663 tng_block_destroy(&block
);
2664 return(TNG_CRITICAL
);
2667 if(fwrite(block
->block_contents
, block
->block_contents_size
, 1,
2668 tng_data
->output_file
) != 1)
2670 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n", __FILE__
, __LINE__
);
2671 tng_block_destroy(&block
);
2672 return(TNG_CRITICAL
);
2675 tng_block_destroy(&block
);
2677 return(TNG_SUCCESS
);
2680 /** Read the chain data of a molecules block.
2681 * @param tng_data is a trajectory data container.
2682 * @param block is a general block container.
2683 * @param chain is the chain data container.
2684 * @param offset is the offset of the block input and is updated when reading.
2685 * @return TNG_SUCCESS(0) is successful.
2687 static tng_function_status
tng_chain_data_read(tng_trajectory_t tng_data
,
2688 tng_gen_block_t block
,
2694 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
2696 memcpy(&chain
->id
, block
->block_contents
+*offset
,
2698 if(tng_data
->input_endianness_swap_func_64
)
2700 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2704 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2705 __FILE__
, __LINE__
);
2708 *offset
+= sizeof(chain
->id
);
2710 len
= tng_min_i((int)strlen(block
->block_contents
+*offset
) + 1,
2712 chain
->name
= malloc(len
);
2713 strncpy(chain
->name
,
2714 block
->block_contents
+*offset
, len
);
2717 memcpy(&chain
->n_residues
, block
->block_contents
+*offset
,
2718 sizeof(chain
->n_residues
));
2719 if(tng_data
->input_endianness_swap_func_64
)
2721 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2725 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2726 __FILE__
, __LINE__
);
2729 *offset
+= sizeof(chain
->n_residues
);
2731 return(TNG_SUCCESS
);
2734 /** Write the chain data of a molecules block.
2735 * @param tng_data is a trajectory data container.
2736 * @param block is a general block container.
2737 * @param chain is the chain data container.
2738 * @param offset is the offset of the block output and is updated when writing.
2739 * @return TNG_SUCCESS(0) is successful.
2741 static tng_function_status
tng_chain_data_write(tng_trajectory_t tng_data
,
2742 tng_gen_block_t block
,
2748 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
2750 memcpy(block
->block_contents
+*offset
, &chain
->id
, sizeof(chain
->id
));
2751 if(tng_data
->output_endianness_swap_func_64
)
2753 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2754 (int64_t *)block
->header_contents
+*offset
)
2757 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2758 __FILE__
, __LINE__
);
2761 *offset
+= sizeof(chain
->id
);
2763 len
= tng_min_i((int)strlen(chain
->name
) + 1, TNG_MAX_STR_LEN
);
2764 strncpy(block
->block_contents
+ *offset
, chain
->name
, len
);
2767 memcpy(block
->block_contents
+*offset
, &chain
->n_residues
,
2768 sizeof(chain
->n_residues
));
2769 if(tng_data
->output_endianness_swap_func_64
)
2771 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2772 (int64_t *)block
->header_contents
+*offset
)
2775 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2776 __FILE__
, __LINE__
);
2779 *offset
+= sizeof(chain
->n_residues
);
2781 return(TNG_SUCCESS
);
2784 /** Read the residue data of a molecules block.
2785 * @param tng_data is a trajectory data container.
2786 * @param block is a general block container.
2787 * @param residue is the residue data container.
2788 * @param offset is the offset of the block input and is updated when reading.
2789 * @return TNG_SUCCESS(0) is successful.
2791 static tng_function_status
tng_residue_data_read(tng_trajectory_t tng_data
,
2792 tng_gen_block_t block
,
2793 tng_residue_t residue
,
2798 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
2800 memcpy(&residue
->id
, block
->block_contents
+*offset
,
2801 sizeof(residue
->id
));
2802 if(tng_data
->input_endianness_swap_func_64
)
2804 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2808 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2809 __FILE__
, __LINE__
);
2812 *offset
+= sizeof(residue
->id
);
2814 len
= tng_min_i((int)strlen(block
->block_contents
+*offset
) + 1,
2816 residue
->name
= malloc(len
);
2817 strncpy(residue
->name
,
2818 block
->block_contents
+*offset
, len
);
2821 memcpy(&residue
->n_atoms
, block
->block_contents
+*offset
,
2822 sizeof(residue
->n_atoms
));
2823 if(tng_data
->input_endianness_swap_func_64
)
2825 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2829 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2830 __FILE__
, __LINE__
);
2833 *offset
+= sizeof(residue
->n_atoms
);
2835 return(TNG_SUCCESS
);
2838 /** Write the residue data of a molecules block.
2839 * @param tng_data is a trajectory data container.
2840 * @param block is a general block container.
2841 * @param residue is the residue data container.
2842 * @param offset is the offset of the block output and is updated when writing.
2843 * @return TNG_SUCCESS(0) is successful.
2845 static tng_function_status
tng_residue_data_write(tng_trajectory_t tng_data
,
2846 tng_gen_block_t block
,
2847 tng_residue_t residue
,
2852 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
2854 memcpy(block
->block_contents
+*offset
, &residue
->id
, sizeof(residue
->id
));
2855 if(tng_data
->output_endianness_swap_func_64
)
2857 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2858 (int64_t *)block
->header_contents
+*offset
)
2861 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2862 __FILE__
, __LINE__
);
2865 *offset
+= sizeof(residue
->id
);
2867 len
= tng_min_i((int)strlen(residue
->name
) + 1, TNG_MAX_STR_LEN
);
2868 strncpy(block
->block_contents
+ *offset
, residue
->name
, len
);
2871 memcpy(block
->block_contents
+*offset
, &residue
->n_atoms
,
2872 sizeof(residue
->n_atoms
));
2873 if(tng_data
->output_endianness_swap_func_64
)
2875 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2876 (int64_t *)block
->header_contents
+*offset
)
2879 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2880 __FILE__
, __LINE__
);
2883 *offset
+= sizeof(residue
->n_atoms
);
2885 return(TNG_SUCCESS
);
2888 /** Read the atom data of a molecules block.
2889 * @param tng_data is a trajectory data container.
2890 * @param block is a general block container.
2891 * @param atom is the atom data container.
2892 * @param offset is the offset of the block input and is updated when reading.
2893 * @return TNG_SUCCESS(0) is successful.
2895 static tng_function_status
tng_atom_data_read(tng_trajectory_t tng_data
,
2896 tng_gen_block_t block
,
2902 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
2904 memcpy(&atom
->id
, block
->block_contents
+*offset
,
2906 if(tng_data
->input_endianness_swap_func_64
)
2908 if(tng_data
->input_endianness_swap_func_64(tng_data
,
2912 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2913 __FILE__
, __LINE__
);
2916 *offset
+= sizeof(atom
->id
);
2918 len
= tng_min_i((int)strlen(block
->block_contents
+*offset
) + 1,
2920 atom
->name
= malloc(len
);
2922 block
->block_contents
+*offset
, len
);
2925 len
= tng_min_i((int)strlen(block
->block_contents
+*offset
) + 1,
2927 atom
->atom_type
= malloc(len
);
2928 strncpy(atom
->atom_type
,
2929 block
->block_contents
+*offset
, len
);
2932 return(TNG_SUCCESS
);
2935 /** Write the atom data of a molecules block.
2936 * @param tng_data is a trajectory data container.
2937 * @param block is a general block container.
2938 * @param atom is the atom data container.
2939 * @param offset is the offset of the block output and is updated when writing.
2940 * @return TNG_SUCCESS(0) is successful.
2942 static tng_function_status
tng_atom_data_write(tng_trajectory_t tng_data
,
2943 tng_gen_block_t block
,
2949 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
2951 memcpy(block
->block_contents
+*offset
, &atom
->id
,
2953 if(tng_data
->output_endianness_swap_func_64
)
2955 if(tng_data
->output_endianness_swap_func_64(tng_data
,
2956 (int64_t *)block
->header_contents
+*offset
)
2959 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
2960 __FILE__
, __LINE__
);
2963 *offset
+= sizeof(atom
->id
);
2965 len
= tng_min_i((int)strlen(atom
->name
) + 1, TNG_MAX_STR_LEN
);
2966 strncpy(block
->block_contents
+ *offset
, atom
->name
, len
);
2969 len
= tng_min_i((int)strlen(atom
->atom_type
) + 1, TNG_MAX_STR_LEN
);
2970 strncpy(block
->block_contents
+ *offset
, atom
->atom_type
, len
);
2973 return(TNG_SUCCESS
);
2976 static tng_function_status tng_molecules_block_len_calculate
2977 (const tng_trajectory_t tng_data
,
2981 tng_molecule_t molecule
;
2983 tng_residue_t residue
;
2989 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
2991 molecule
= &tng_data
->molecules
[i
];
2994 molecule
->name
= malloc(1);
2997 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2998 __FILE__
, __LINE__
);
2999 return(TNG_CRITICAL
);
3001 molecule
->name
[0] = 0;
3003 *len
+= tng_min_i((int)strlen(molecule
->name
) + 1, TNG_MAX_STR_LEN
);
3005 chain
= molecule
->chains
;
3006 for(j
= 0; j
< molecule
->n_chains
; j
++)
3008 *len
+= sizeof(chain
->id
);
3012 chain
->name
= malloc(1);
3015 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3016 __FILE__
, __LINE__
);
3017 return(TNG_CRITICAL
);
3021 *len
+= tng_min_i((int)strlen(chain
->name
) + 1, TNG_MAX_STR_LEN
);
3023 *len
+= sizeof(chain
->n_residues
);
3028 residue
= molecule
->residues
;
3029 for(j
= 0; j
< molecule
->n_residues
; j
++)
3031 *len
+= sizeof(residue
->id
);
3035 residue
->name
= malloc(1);
3038 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3039 __FILE__
, __LINE__
);
3040 return(TNG_CRITICAL
);
3042 residue
->name
[0] = 0;
3044 *len
+= tng_min_i((int)strlen(residue
->name
) + 1, TNG_MAX_STR_LEN
);
3046 *len
+= sizeof(residue
->n_atoms
);
3051 atom
= molecule
->atoms
;
3052 for(j
= 0; j
< molecule
->n_atoms
; j
++)
3054 *len
+= sizeof(atom
->id
);
3057 atom
->name
= malloc(1);
3060 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3061 __FILE__
, __LINE__
);
3062 return(TNG_CRITICAL
);
3066 *len
+= tng_min_i((int)strlen(atom
->name
) + 1, TNG_MAX_STR_LEN
);
3068 if(!atom
->atom_type
)
3070 atom
->atom_type
= malloc(1);
3071 if(!atom
->atom_type
)
3073 fprintf(stderr
, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3074 __FILE__
, __LINE__
);
3075 return(TNG_CRITICAL
);
3077 atom
->atom_type
[0] = 0;
3079 *len
+= tng_min_i((int)strlen(atom
->atom_type
) + 1, TNG_MAX_STR_LEN
);
3084 for(j
= 0; j
< molecule
->n_bonds
; j
++)
3086 *len
+= sizeof(bond
->from_atom_id
) + sizeof(bond
->to_atom_id
);
3089 *len
+= sizeof(tng_data
->n_molecules
) +
3090 (sizeof(molecule
->id
) +
3091 sizeof(molecule
->quaternary_str
) +
3092 sizeof(molecule
->n_chains
) +
3093 sizeof(molecule
->n_residues
) +
3094 sizeof(molecule
->n_atoms
) +
3095 sizeof(molecule
->n_bonds
)) *
3096 tng_data
->n_molecules
;
3098 if(!tng_data
->var_num_atoms_flag
)
3100 *len
+= tng_data
->n_molecules
* sizeof(int64_t);
3103 return(TNG_SUCCESS
);
3106 /** Read a molecules block. Contains chain, residue and atom data
3107 * @param tng_data is a trajectory data container.
3108 * @param block is a general block container.
3109 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3110 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3111 * compared to the md5 hash of the read contents to ensure valid data.
3112 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3113 * error has occured.
3115 static tng_function_status tng_molecules_block_read
3116 (tng_trajectory_t tng_data
,
3117 tng_gen_block_t block
,
3118 const char hash_mode
)
3121 int len
, offset
= 0;
3122 tng_molecule_t molecule
;
3124 tng_residue_t residue
;
3129 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
3131 return(TNG_CRITICAL
);
3134 if(block
->block_contents
)
3136 free(block
->block_contents
);
3139 block
->block_contents
= malloc(block
->block_contents_size
);
3140 if(!block
->block_contents
)
3142 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3143 block
->block_contents_size
, __FILE__
, __LINE__
);
3144 return(TNG_CRITICAL
);
3147 /* Read the whole block into block_contents to be able to write it to disk
3148 * even if it cannot be interpreted. */
3149 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
3150 tng_data
->input_file
) == 0)
3152 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
3155 /* FIXME: Does not check if the size of the contents matches the expected
3156 * size or if the contents can be read. */
3158 if(hash_mode
== TNG_USE_HASH
)
3160 tng_md5_hash_match_verify(block
, &same_hash
);
3161 if(same_hash
!= TNG_TRUE
)
3163 fprintf(stderr
, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3165 __FILE__
, __LINE__
);
3169 if(tng_data
->molecules
)
3171 for(i
=0; i
<tng_data
->n_molecules
; i
++)
3173 tng_molecule_destroy(tng_data
, &tng_data
->molecules
[i
]);
3175 free(tng_data
->molecules
);
3176 tng_data
->molecules
= 0;
3177 tng_data
->n_molecules
= 0;
3180 memcpy(&tng_data
->n_molecules
, block
->block_contents
,
3181 sizeof(tng_data
->n_molecules
));
3182 if(tng_data
->input_endianness_swap_func_64
)
3184 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3185 &tng_data
->n_molecules
)
3188 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3189 __FILE__
, __LINE__
);
3192 offset
+= sizeof(tng_data
->n_molecules
);
3194 if(tng_data
->molecules
)
3196 free(tng_data
->molecules
);
3199 tng_data
->n_particles
= 0;
3201 tng_data
->molecules
= malloc(tng_data
->n_molecules
*
3202 sizeof(struct tng_molecule
));
3203 if(!tng_data
->molecules
)
3205 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3206 tng_data
->n_molecules
* sizeof(struct tng_molecule
),
3207 __FILE__
, __LINE__
);
3208 return(TNG_CRITICAL
);
3211 if(!tng_data
->var_num_atoms_flag
)
3213 if(tng_data
->molecule_cnt_list
)
3215 free(tng_data
->molecule_cnt_list
);
3217 tng_data
->molecule_cnt_list
= malloc(sizeof(int64_t) *
3218 tng_data
->n_molecules
);
3219 if(!tng_data
->molecule_cnt_list
)
3221 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3222 tng_data
->n_molecules
* sizeof(struct tng_molecule
),
3223 __FILE__
, __LINE__
);
3224 return(TNG_CRITICAL
);
3228 /* Read each molecule from file */
3229 for(i
=0; i
< tng_data
->n_molecules
; i
++)
3231 molecule
= &tng_data
->molecules
[i
];
3233 memcpy(&molecule
->id
, block
->block_contents
+offset
,
3234 sizeof(molecule
->id
));
3235 if(tng_data
->input_endianness_swap_func_64
)
3237 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3241 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3242 __FILE__
, __LINE__
);
3245 offset
+= sizeof(molecule
->id
);
3247 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
3248 len
= tng_min_i((int)strlen(block
->block_contents
+offset
) + 1, TNG_MAX_STR_LEN
);
3249 molecule
->name
= malloc(len
);
3250 strncpy(molecule
->name
, block
->block_contents
+offset
, len
);
3253 memcpy(&molecule
->quaternary_str
, block
->block_contents
+offset
,
3254 sizeof(molecule
->quaternary_str
));
3255 if(tng_data
->input_endianness_swap_func_64
)
3257 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3258 &molecule
->quaternary_str
)
3261 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3262 __FILE__
, __LINE__
);
3265 offset
+= sizeof(molecule
->quaternary_str
);
3267 if(!tng_data
->var_num_atoms_flag
)
3269 memcpy(&tng_data
->molecule_cnt_list
[i
],
3270 block
->block_contents
+offset
,
3272 if(tng_data
->input_endianness_swap_func_64
)
3274 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3275 &tng_data
->molecule_cnt_list
[i
])
3278 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3279 __FILE__
, __LINE__
);
3282 offset
+= sizeof(int64_t);
3286 memcpy(&molecule
->n_chains
, block
->block_contents
+offset
,
3287 sizeof(molecule
->n_chains
));
3288 if(tng_data
->input_endianness_swap_func_64
)
3290 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3291 &molecule
->n_chains
)
3294 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3295 __FILE__
, __LINE__
);
3298 offset
+= sizeof(molecule
->n_chains
);
3300 memcpy(&molecule
->n_residues
, block
->block_contents
+offset
,
3301 sizeof(molecule
->n_residues
));
3302 if(tng_data
->input_endianness_swap_func_64
)
3304 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3305 &molecule
->n_residues
)
3308 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3309 __FILE__
, __LINE__
);
3312 offset
+= sizeof(molecule
->n_residues
);
3314 memcpy(&molecule
->n_atoms
, block
->block_contents
+offset
,
3315 sizeof(molecule
->n_atoms
));
3316 if(tng_data
->input_endianness_swap_func_64
)
3318 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3322 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3323 __FILE__
, __LINE__
);
3326 offset
+= sizeof(molecule
->n_atoms
);
3328 tng_data
->n_particles
+= molecule
->n_atoms
*
3329 tng_data
->molecule_cnt_list
[i
];
3331 if(molecule
->n_chains
> 0)
3333 molecule
->chains
= malloc(molecule
->n_chains
*
3334 sizeof(struct tng_chain
));
3335 if(!molecule
->chains
)
3337 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3338 molecule
->n_chains
* sizeof(struct tng_chain
),
3339 __FILE__
, __LINE__
);
3340 return(TNG_CRITICAL
);
3343 chain
= molecule
->chains
;
3350 if(molecule
->n_residues
> 0)
3352 molecule
->residues
= malloc(molecule
->n_residues
*
3353 sizeof(struct tng_residue
));
3354 if(!molecule
->residues
)
3356 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3357 molecule
->n_residues
* sizeof(struct tng_residue
),
3358 __FILE__
, __LINE__
);
3359 if(molecule
->chains
)
3361 free(molecule
->chains
);
3362 molecule
->chains
= 0;
3364 return(TNG_CRITICAL
);
3367 residue
= molecule
->residues
;
3374 molecule
->atoms
= malloc(molecule
->n_atoms
*
3375 sizeof(struct tng_atom
));
3376 if(!molecule
->atoms
)
3378 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3379 molecule
->n_atoms
* sizeof(struct tng_atom
),
3380 __FILE__
, __LINE__
);
3381 if(molecule
->chains
)
3383 free(molecule
->chains
);
3384 molecule
->chains
= 0;
3386 if(molecule
->residues
)
3388 free(molecule
->residues
);
3389 molecule
->residues
= 0;
3391 return(TNG_CRITICAL
);
3394 atom
= molecule
->atoms
;
3396 if(molecule
->n_chains
> 0)
3398 /* Read the chains of the molecule */
3399 for(j
=0; j
<molecule
->n_chains
; j
++)
3401 chain
->molecule
= molecule
;
3403 tng_chain_data_read(tng_data
, block
, chain
, &offset
);
3405 chain
->residues
= molecule
->residues
;
3406 residue
= chain
->residues
;
3408 /* Read the residues of the chain */
3409 for(k
=0; k
<chain
->n_residues
; k
++)
3411 residue
->chain
= chain
;
3413 tng_residue_data_read(tng_data
, block
, residue
, &offset
);
3415 residue
->atoms_offset
= atom
- molecule
->atoms
;
3416 /* Read the atoms of the residue */
3417 for(l
=0; l
<residue
->n_atoms
; l
++)
3419 atom
->residue
= residue
;
3421 tng_atom_data_read(tng_data
, block
, atom
, &offset
);
3432 if(molecule
->n_residues
> 0)
3434 for(k
=0; k
<molecule
->n_residues
; k
++)
3438 tng_residue_data_read(tng_data
, block
, residue
, &offset
);
3440 residue
->atoms_offset
= atom
- molecule
->atoms
;
3441 /* Read the atoms of the residue */
3442 for(l
=0; l
<residue
->n_atoms
; l
++)
3444 atom
->residue
= residue
;
3446 tng_atom_data_read(tng_data
, block
, atom
, &offset
);
3455 for(l
=0; l
<molecule
->n_atoms
; l
++)
3459 tng_atom_data_read(tng_data
, block
, atom
, &offset
);
3466 memcpy(&molecule
->n_bonds
, block
->block_contents
+offset
,
3467 sizeof(molecule
->n_bonds
));
3468 if(tng_data
->input_endianness_swap_func_64
)
3470 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3474 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3475 __FILE__
, __LINE__
);
3478 offset
+= sizeof(molecule
->n_bonds
);
3480 if(molecule
->n_bonds
> 0)
3482 tng_data
->molecules
[i
].bonds
= malloc(molecule
->n_bonds
*
3483 sizeof(struct tng_bond
));
3484 if(!molecule
->bonds
)
3486 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3487 molecule
->n_bonds
* sizeof(struct tng_bond
),
3488 __FILE__
, __LINE__
);
3489 if(molecule
->chains
)
3491 free(molecule
->chains
);
3492 molecule
->chains
= 0;
3494 if(molecule
->residues
)
3496 free(molecule
->residues
);
3497 molecule
->residues
= 0;
3501 free(molecule
->atoms
);
3502 molecule
->atoms
= 0;
3504 return(TNG_CRITICAL
);
3507 bond
= molecule
->bonds
;
3509 for(j
=0; j
<molecule
->n_bonds
; j
++)
3511 memcpy(&bond
->from_atom_id
, block
->block_contents
+offset
,
3512 sizeof(bond
->from_atom_id
));
3513 if(tng_data
->input_endianness_swap_func_64
)
3515 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3516 &bond
->from_atom_id
)
3519 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3520 __FILE__
, __LINE__
);
3523 offset
+= sizeof(bond
->from_atom_id
);
3525 memcpy(&bond
->to_atom_id
, block
->block_contents
+offset
,
3526 sizeof(bond
->to_atom_id
));
3527 if(tng_data
->input_endianness_swap_func_64
)
3529 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3533 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3534 __FILE__
, __LINE__
);
3537 offset
+= sizeof(bond
->to_atom_id
);
3544 molecule
->bonds
= 0;
3548 return(TNG_SUCCESS
);
3551 /** Write a molecules block.
3552 * @param tng_data is a trajectory data container.
3553 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3554 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3555 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3556 * error has occured.
3558 static tng_function_status tng_molecules_block_write
3559 (tng_trajectory_t tng_data
,
3560 const char hash_mode
)
3562 int len
= 0, name_len
, offset
= 0;
3564 tng_molecule_t molecule
;
3566 tng_residue_t residue
;
3569 tng_gen_block_t block
;
3571 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
3573 return(TNG_CRITICAL
);
3576 tng_block_init(&block
);
3578 name_len
= (int)strlen("MOLECULES");
3580 block
->name
= malloc(name_len
+ 1);
3583 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3584 name_len
+1, __FILE__
, __LINE__
);
3585 tng_block_destroy(&block
);
3586 return(TNG_CRITICAL
);
3589 strcpy(block
->name
, "MOLECULES");
3590 block
->id
= TNG_MOLECULES
;
3592 if(tng_molecules_block_len_calculate(tng_data
, &block
->block_contents_size
) !=
3595 fprintf(stderr
, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3596 __FILE__
, __LINE__
);
3597 tng_block_destroy(&block
);
3598 return(TNG_CRITICAL
);
3601 block
->block_contents
= malloc(block
->block_contents_size
);
3602 if(!block
->block_contents
)
3604 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3605 block
->block_contents_size
, __FILE__
, __LINE__
);
3606 tng_block_destroy(&block
);
3607 return(TNG_CRITICAL
);
3610 memcpy(block
->block_contents
+offset
, &tng_data
->n_molecules
,
3611 sizeof(tng_data
->n_molecules
));
3612 if(tng_data
->output_endianness_swap_func_64
)
3614 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3615 (int64_t *)block
->header_contents
+offset
)
3618 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3619 __FILE__
, __LINE__
);
3622 offset
+= sizeof(tng_data
->n_molecules
);
3624 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
3626 molecule
= &tng_data
->molecules
[i
];
3627 memcpy(block
->block_contents
+offset
, &molecule
->id
,
3628 sizeof(molecule
->id
));
3629 if(tng_data
->output_endianness_swap_func_64
)
3631 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3632 (int64_t *)block
->header_contents
+offset
)
3635 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3636 __FILE__
, __LINE__
);
3639 offset
+= sizeof(molecule
->id
);
3641 /* fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
3642 len
= tng_min_i((int)strlen(molecule
->name
) + 1, TNG_MAX_STR_LEN
);
3643 strncpy(block
->block_contents
+ offset
, molecule
->name
, len
);
3646 memcpy(block
->block_contents
+offset
, &molecule
->quaternary_str
,
3647 sizeof(molecule
->quaternary_str
));
3648 if(tng_data
->output_endianness_swap_func_64
)
3650 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3651 (int64_t *)block
->header_contents
+offset
)
3654 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3655 __FILE__
, __LINE__
);
3658 offset
+= sizeof(molecule
->quaternary_str
);
3660 if(!tng_data
->var_num_atoms_flag
)
3662 memcpy(block
->block_contents
+offset
,
3663 &tng_data
->molecule_cnt_list
[i
], sizeof(int64_t));
3664 if(tng_data
->output_endianness_swap_func_64
)
3666 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3667 (int64_t *)block
->header_contents
+offset
)
3670 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3671 __FILE__
, __LINE__
);
3674 offset
+= sizeof(int64_t);
3677 memcpy(block
->block_contents
+offset
, &molecule
->n_chains
,
3678 sizeof(molecule
->n_chains
));
3679 if(tng_data
->output_endianness_swap_func_64
)
3681 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3682 (int64_t *)block
->header_contents
+offset
)
3685 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3686 __FILE__
, __LINE__
);
3689 offset
+= sizeof(molecule
->n_chains
);
3691 memcpy(block
->block_contents
+offset
, &molecule
->n_residues
,
3692 sizeof(molecule
->n_residues
));
3693 if(tng_data
->output_endianness_swap_func_64
)
3695 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3696 (int64_t *)block
->header_contents
+offset
)
3699 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3700 __FILE__
, __LINE__
);
3703 offset
+= sizeof(molecule
->n_residues
);
3705 memcpy(block
->block_contents
+offset
, &molecule
->n_atoms
,
3706 sizeof(molecule
->n_atoms
));
3707 if(tng_data
->output_endianness_swap_func_64
)
3709 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3710 (int64_t *)block
->header_contents
+offset
)
3713 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3714 __FILE__
, __LINE__
);
3717 offset
+= sizeof(molecule
->n_atoms
);
3719 if(molecule
->n_chains
> 0)
3721 chain
= molecule
->chains
;
3722 for(j
= 0; j
< molecule
->n_chains
; j
++)
3724 tng_chain_data_write(tng_data
, block
, chain
, &offset
);
3726 residue
= chain
->residues
;
3727 for(k
= 0; k
< chain
->n_residues
; k
++)
3729 tng_residue_data_write(tng_data
, block
, residue
, &offset
);
3731 atom
= molecule
->atoms
+ residue
->atoms_offset
;
3732 for(l
= 0; l
< residue
->n_atoms
; l
++)
3734 tng_atom_data_write(tng_data
, block
, atom
, &offset
);
3745 if(molecule
->n_residues
> 0)
3747 residue
= molecule
->residues
;
3748 for(k
= 0; k
< molecule
->n_residues
; k
++)
3750 tng_residue_data_write(tng_data
, block
, residue
, &offset
);
3752 atom
= molecule
->atoms
+ residue
->atoms_offset
;
3753 for(l
= 0; l
< residue
->n_atoms
; l
++)
3755 tng_atom_data_write(tng_data
, block
, atom
, &offset
);
3764 atom
= molecule
->atoms
;
3765 for(l
= 0; l
< molecule
->n_atoms
; l
++)
3767 tng_atom_data_write(tng_data
, block
, atom
, &offset
);
3774 memcpy(block
->block_contents
+offset
, &molecule
->n_bonds
,
3775 sizeof(molecule
->n_bonds
));
3776 if(tng_data
->output_endianness_swap_func_64
)
3778 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3779 (int64_t *)block
->header_contents
+offset
)
3782 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3783 __FILE__
, __LINE__
);
3786 offset
+= sizeof(molecule
->n_bonds
);
3788 bond
= molecule
->bonds
;
3789 for(j
= 0; j
< molecule
->n_bonds
; j
++)
3791 memcpy(block
->block_contents
+offset
, &bond
->from_atom_id
,
3792 sizeof(bond
->from_atom_id
));
3793 if(tng_data
->output_endianness_swap_func_64
)
3795 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3796 (int64_t *)block
->header_contents
+offset
)
3799 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3800 __FILE__
, __LINE__
);
3803 offset
+= sizeof(bond
->from_atom_id
);
3805 memcpy(block
->block_contents
+offset
, &bond
->to_atom_id
,
3806 sizeof(bond
->to_atom_id
));
3807 if(tng_data
->output_endianness_swap_func_64
)
3809 if(tng_data
->output_endianness_swap_func_64(tng_data
,
3810 (int64_t *)block
->header_contents
+offset
)
3813 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3814 __FILE__
, __LINE__
);
3817 offset
+= sizeof(bond
->to_atom_id
);
3823 if(tng_block_header_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
3825 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
3826 tng_data
->output_file_path
, __FILE__
, __LINE__
);
3827 tng_block_destroy(&block
);
3828 return(TNG_CRITICAL
);
3831 if(fwrite(block
->block_contents
, block
->block_contents_size
, 1,
3832 tng_data
->output_file
) != 1)
3834 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n",
3835 __FILE__
, __LINE__
);
3836 tng_block_destroy(&block
);
3837 return(TNG_CRITICAL
);
3840 tng_block_destroy(&block
);
3842 return(TNG_SUCCESS
);
3845 static tng_function_status tng_frame_set_block_len_calculate
3846 (const tng_trajectory_t tng_data
,
3849 *len
= sizeof(int64_t) * 8;
3850 *len
+= sizeof(double) * 2;
3852 if(tng_data
->var_num_atoms_flag
)
3854 *len
+= sizeof(int64_t) * tng_data
->n_molecules
;
3856 return(TNG_SUCCESS
);
3859 /** Read a frame set block. Update tng_data->current_trajectory_frame_set
3860 * @param tng_data is a trajectory data container.
3861 * @param block is a general block container.
3862 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3863 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3864 * compared to the md5 hash of the read contents to ensure valid data.
3865 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3866 * error has occured.
3868 static tng_function_status tng_frame_set_block_read
3869 (tng_trajectory_t tng_data
,
3870 tng_gen_block_t block
,
3871 const char hash_mode
)
3875 int64_t i
, prev_n_particles
;
3877 tng_trajectory_frame_set_t frame_set
=
3878 &tng_data
->current_trajectory_frame_set
;
3880 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
3882 return(TNG_CRITICAL
);
3885 if(block
->block_contents
)
3887 free(block
->block_contents
);
3890 block
->block_contents
= malloc(block
->block_contents_size
);
3891 if(!block
->block_contents
)
3893 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3894 block
->block_contents_size
, __FILE__
, __LINE__
);
3895 return(TNG_CRITICAL
);
3898 /* Read the whole block into block_contents to be able to write it to
3899 * disk even if it cannot be interpreted. */
3900 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
3901 tng_data
->input_file
) == 0)
3903 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
3904 return(TNG_CRITICAL
);
3907 /* FIXME: Does not check if the size of the contents matches the expected
3908 * size or if the contents can be read. */
3910 file_pos
= (int64_t)ftell(tng_data
->input_file
) -
3911 (long)(block
->block_contents_size
+ block
->header_contents_size
);
3913 if(hash_mode
== TNG_USE_HASH
)
3915 tng_md5_hash_match_verify(block
, &same_hash
);
3916 if(same_hash
!= TNG_TRUE
)
3918 fprintf(stderr
, "TNG library: Frame set block contents corrupt. File pos %ld Hashes do not match. "
3920 file_pos
, __FILE__
, __LINE__
);
3921 /* return(TNG_FAILURE); */
3925 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
3927 tng_frame_set_particle_mapping_free(tng_data
);
3929 if(tng_data
->first_trajectory_frame_set_input_file_pos
<= 0)
3931 tng_data
->first_trajectory_frame_set_input_file_pos
= file_pos
;
3933 /* FIXME: Should check the frame number instead of the file_pos, in case
3934 * frame sets are not in order */
3935 if(tng_data
->last_trajectory_frame_set_input_file_pos
< file_pos
)
3937 tng_data
->last_trajectory_frame_set_input_file_pos
= file_pos
;
3940 memcpy(&frame_set
->first_frame
, block
->block_contents
,
3941 sizeof(frame_set
->first_frame
));
3942 if(tng_data
->input_endianness_swap_func_64
)
3944 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3945 &frame_set
->first_frame
)
3948 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3949 __FILE__
, __LINE__
);
3952 offset
+= sizeof(frame_set
->first_frame
);
3954 memcpy(&frame_set
->n_frames
, block
->block_contents
+ offset
,
3955 sizeof(frame_set
->n_frames
));
3956 if(tng_data
->input_endianness_swap_func_64
)
3958 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3959 &frame_set
->n_frames
)
3962 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3963 __FILE__
, __LINE__
);
3966 offset
+= sizeof(frame_set
->n_frames
);
3968 if(tng_data
->var_num_atoms_flag
)
3970 prev_n_particles
= frame_set
->n_particles
;
3971 frame_set
->n_particles
= 0;
3972 /* If the list of molecule counts has already been created assume that
3973 * it is of correct size. */
3974 if(!frame_set
->molecule_cnt_list
)
3976 frame_set
->molecule_cnt_list
=
3977 malloc(sizeof(int64_t) * tng_data
->n_molecules
);
3979 if(!frame_set
->molecule_cnt_list
)
3981 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
3982 sizeof(int64_t) * tng_data
->n_molecules
,
3983 __FILE__
, __LINE__
);
3984 return(TNG_CRITICAL
);
3987 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
3989 memcpy(&frame_set
->molecule_cnt_list
[i
],
3990 block
->block_contents
+ offset
,
3992 if(tng_data
->input_endianness_swap_func_64
)
3994 if(tng_data
->input_endianness_swap_func_64(tng_data
,
3995 &frame_set
->molecule_cnt_list
[i
])
3998 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
3999 __FILE__
, __LINE__
);
4002 offset
+= sizeof(int64_t);
4003 frame_set
->n_particles
+= tng_data
->molecules
[i
].n_atoms
*
4004 frame_set
->molecule_cnt_list
[i
];
4006 if(prev_n_particles
&& frame_set
->n_particles
!= prev_n_particles
)
4008 /* FIXME: Particle dependent data memory management */
4012 memcpy(&frame_set
->next_frame_set_file_pos
,
4013 block
->block_contents
+ offset
,
4014 sizeof(frame_set
->next_frame_set_file_pos
));
4015 if(tng_data
->input_endianness_swap_func_64
)
4017 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4018 &frame_set
->next_frame_set_file_pos
)
4021 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4022 __FILE__
, __LINE__
);
4025 offset
+= sizeof(frame_set
->next_frame_set_file_pos
);
4027 memcpy(&frame_set
->prev_frame_set_file_pos
,
4028 block
->block_contents
+ offset
,
4029 sizeof(frame_set
->prev_frame_set_file_pos
));
4030 if(tng_data
->input_endianness_swap_func_64
)
4032 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4033 &frame_set
->prev_frame_set_file_pos
)
4036 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4037 __FILE__
, __LINE__
);
4040 offset
+= sizeof(frame_set
->prev_frame_set_file_pos
);
4042 memcpy(&frame_set
->medium_stride_next_frame_set_file_pos
,
4043 block
->block_contents
+ offset
,
4044 sizeof(frame_set
->medium_stride_next_frame_set_file_pos
));
4045 if(tng_data
->input_endianness_swap_func_64
)
4047 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4048 &frame_set
->medium_stride_next_frame_set_file_pos
)
4051 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4052 __FILE__
, __LINE__
);
4055 offset
+= sizeof(frame_set
->medium_stride_next_frame_set_file_pos
);
4057 memcpy(&frame_set
->medium_stride_prev_frame_set_file_pos
,
4058 block
->block_contents
+ offset
,
4059 sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
));
4060 if(tng_data
->input_endianness_swap_func_64
)
4062 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4063 &frame_set
->medium_stride_prev_frame_set_file_pos
)
4066 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4067 __FILE__
, __LINE__
);
4070 offset
+= sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
);
4072 memcpy(&frame_set
->long_stride_next_frame_set_file_pos
,
4073 block
->block_contents
+ offset
,
4074 sizeof(frame_set
->long_stride_next_frame_set_file_pos
));
4075 if(tng_data
->input_endianness_swap_func_64
)
4077 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4078 &frame_set
->long_stride_next_frame_set_file_pos
)
4081 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4082 __FILE__
, __LINE__
);
4085 offset
+= sizeof(frame_set
->long_stride_next_frame_set_file_pos
);
4087 memcpy(&frame_set
->long_stride_prev_frame_set_file_pos
,
4088 block
->block_contents
+ offset
,
4089 sizeof(frame_set
->long_stride_prev_frame_set_file_pos
));
4090 if(tng_data
->input_endianness_swap_func_64
)
4092 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4093 &frame_set
->long_stride_prev_frame_set_file_pos
)
4096 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4097 __FILE__
, __LINE__
);
4100 offset
+= sizeof(frame_set
->long_stride_prev_frame_set_file_pos
);
4102 if(block
->block_version
>= 3)
4104 memcpy(&frame_set
->first_frame_time
,
4105 block
->block_contents
+ offset
,
4106 sizeof(frame_set
->first_frame_time
));
4107 if(tng_data
->input_endianness_swap_func_64
)
4109 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4110 (int64_t *)&frame_set
->first_frame_time
)
4113 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4114 __FILE__
, __LINE__
);
4117 offset
+= sizeof(frame_set
->first_frame_time
);
4119 memcpy(&tng_data
->time_per_frame
,
4120 block
->block_contents
+ offset
,
4121 sizeof(tng_data
->time_per_frame
));
4122 if(tng_data
->input_endianness_swap_func_64
)
4124 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4125 (int64_t *)&tng_data
->time_per_frame
)
4128 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4129 __FILE__
, __LINE__
);
4135 frame_set
->first_frame_time
= -1;
4136 tng_data
->time_per_frame
= -1;
4139 /* If the output file and the input files are the same the number of
4140 * frames in the file are the same number as has just been read.
4141 * This is updated here to later on see if there have been new frames
4142 * added and thereby the frame set needs to be rewritten. */
4143 if(tng_data
->output_file
== tng_data
->input_file
)
4145 frame_set
->n_written_frames
= frame_set
->n_frames
;
4148 return(TNG_SUCCESS
);
4151 /** Write tng_data->current_trajectory_frame_set to file
4152 * @param tng_data is a trajectory data container.
4153 * @param block is a general block container.
4154 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4155 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4156 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4157 * error has occured.
4159 static tng_function_status tng_frame_set_block_write
4160 (tng_trajectory_t tng_data
,
4161 tng_gen_block_t block
,
4162 const char hash_mode
)
4167 unsigned int name_len
;
4168 tng_trajectory_frame_set_t frame_set
=
4169 &tng_data
->current_trajectory_frame_set
;
4171 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
4173 return(TNG_CRITICAL
);
4176 name_len
= (int)strlen("TRAJECTORY FRAME SET");
4178 if(!block
->name
|| strlen(block
->name
) < name_len
)
4180 temp_name
= realloc(block
->name
, name_len
+ 1);
4183 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4184 name_len
+1, __FILE__
, __LINE__
);
4187 return(TNG_CRITICAL
);
4189 block
->name
= temp_name
;
4191 strcpy(block
->name
, "TRAJECTORY FRAME SET");
4192 block
->id
= TNG_TRAJECTORY_FRAME_SET
;
4194 if(tng_frame_set_block_len_calculate(tng_data
, &block
->block_contents_size
) !=
4197 fprintf(stderr
, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
4198 __FILE__
, __LINE__
);
4199 return(TNG_CRITICAL
);
4202 if(block
->block_contents
)
4204 free(block
->block_contents
);
4206 block
->block_contents
= malloc(block
->block_contents_size
);
4207 if(!block
->block_contents
)
4209 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
4210 block
->block_contents_size
, __FILE__
, __LINE__
);
4211 return(TNG_CRITICAL
);
4214 memcpy(block
->block_contents
, &frame_set
->first_frame
,
4215 sizeof(frame_set
->first_frame
));
4216 if(tng_data
->output_endianness_swap_func_64
)
4218 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4219 (int64_t *)block
->header_contents
+offset
)
4222 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4223 __FILE__
, __LINE__
);
4226 offset
+= sizeof(frame_set
->first_frame
);
4228 memcpy(block
->block_contents
+offset
, &frame_set
->n_frames
,
4229 sizeof(frame_set
->n_frames
));
4230 if(tng_data
->output_endianness_swap_func_64
)
4232 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4233 (int64_t *)block
->header_contents
+offset
)
4236 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4237 __FILE__
, __LINE__
);
4240 offset
+= sizeof(frame_set
->n_frames
);
4242 if(tng_data
->var_num_atoms_flag
)
4244 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
4246 memcpy(block
->block_contents
+offset
,
4247 &frame_set
->molecule_cnt_list
[i
],
4249 if(tng_data
->output_endianness_swap_func_64
)
4251 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4252 (int64_t *)block
->header_contents
+offset
)
4255 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4256 __FILE__
, __LINE__
);
4259 offset
+= sizeof(int64_t);
4264 memcpy(block
->block_contents
+offset
, &frame_set
->next_frame_set_file_pos
,
4265 sizeof(frame_set
->next_frame_set_file_pos
));
4266 if(tng_data
->output_endianness_swap_func_64
)
4268 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4269 (int64_t *)block
->header_contents
+offset
)
4272 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4273 __FILE__
, __LINE__
);
4276 offset
+= sizeof(frame_set
->next_frame_set_file_pos
);
4278 memcpy(block
->block_contents
+offset
, &frame_set
->prev_frame_set_file_pos
,
4279 sizeof(frame_set
->prev_frame_set_file_pos
));
4280 if(tng_data
->output_endianness_swap_func_64
)
4282 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4283 (int64_t *)block
->header_contents
+offset
)
4286 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4287 __FILE__
, __LINE__
);
4290 offset
+= sizeof(frame_set
->prev_frame_set_file_pos
);
4292 memcpy(block
->block_contents
+offset
,
4293 &frame_set
->medium_stride_next_frame_set_file_pos
,
4294 sizeof(frame_set
->medium_stride_next_frame_set_file_pos
));
4295 if(tng_data
->output_endianness_swap_func_64
)
4297 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4298 (int64_t *)block
->header_contents
+offset
)
4301 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4302 __FILE__
, __LINE__
);
4305 offset
+= sizeof(frame_set
->medium_stride_next_frame_set_file_pos
);
4307 memcpy(block
->block_contents
+offset
,
4308 &frame_set
->medium_stride_prev_frame_set_file_pos
,
4309 sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
));
4310 if(tng_data
->output_endianness_swap_func_64
)
4312 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4313 (int64_t *)block
->header_contents
+offset
)
4316 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4317 __FILE__
, __LINE__
);
4320 offset
+= sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
);
4322 memcpy(block
->block_contents
+offset
,
4323 &frame_set
->long_stride_next_frame_set_file_pos
,
4324 sizeof(frame_set
->long_stride_next_frame_set_file_pos
));
4325 if(tng_data
->output_endianness_swap_func_64
)
4327 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4328 (int64_t *)block
->header_contents
+offset
)
4331 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4332 __FILE__
, __LINE__
);
4335 offset
+= sizeof(frame_set
->long_stride_next_frame_set_file_pos
);
4337 memcpy(block
->block_contents
+offset
,
4338 &frame_set
->long_stride_prev_frame_set_file_pos
,
4339 sizeof(frame_set
->long_stride_prev_frame_set_file_pos
));
4340 if(tng_data
->output_endianness_swap_func_64
)
4342 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4343 (int64_t *)block
->header_contents
+offset
)
4346 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4347 __FILE__
, __LINE__
);
4350 offset
+= sizeof(frame_set
->long_stride_prev_frame_set_file_pos
);
4352 memcpy(block
->block_contents
+offset
,
4353 &frame_set
->first_frame_time
,
4354 sizeof(frame_set
->first_frame_time
));
4355 if(tng_data
->output_endianness_swap_func_64
)
4357 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4358 (int64_t *)block
->header_contents
+offset
)
4361 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4362 __FILE__
, __LINE__
);
4365 offset
+= sizeof(frame_set
->first_frame_time
);
4367 memcpy(block
->block_contents
+offset
,
4368 &tng_data
->time_per_frame
,
4369 sizeof(tng_data
->time_per_frame
));
4370 if(tng_data
->output_endianness_swap_func_64
)
4372 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4373 (int64_t *)block
->header_contents
+offset
)
4376 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4377 __FILE__
, __LINE__
);
4381 if(tng_block_header_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
4383 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
4384 tng_data
->output_file_path
, __FILE__
, __LINE__
);
4385 return(TNG_CRITICAL
);
4388 if(fwrite(block
->block_contents
, block
->block_contents_size
, 1,
4389 tng_data
->output_file
) != 1)
4391 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n", __FILE__
, __LINE__
);
4392 return(TNG_CRITICAL
);
4395 return(TNG_SUCCESS
);
4398 static tng_function_status tng_trajectory_mapping_block_len_calculate
4399 (const tng_trajectory_t tng_data
,
4400 const int64_t n_particles
,
4404 *len
= sizeof(int64_t) * (2 + n_particles
);
4406 return(TNG_SUCCESS
);
4409 /** Read an atom mappings block (translating between real atom indexes and how
4410 * the atom info is written in this frame set).
4411 * @param tng_data is a trajectory data container.
4412 * @param block is a general block container.
4413 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4414 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
4415 * compared to the md5 hash of the read contents to ensure valid data.
4416 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4417 * error has occured.
4419 static tng_function_status tng_trajectory_mapping_block_read
4420 (tng_trajectory_t tng_data
,
4421 tng_gen_block_t block
,
4422 const char hash_mode
)
4427 tng_trajectory_frame_set_t frame_set
=
4428 &tng_data
->current_trajectory_frame_set
;
4430 tng_particle_mapping_t mapping
, mappings
;
4432 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
4434 return(TNG_CRITICAL
);
4437 if(block
->block_contents
)
4439 free(block
->block_contents
);
4442 block
->block_contents
= malloc(block
->block_contents_size
);
4443 if(!block
->block_contents
)
4445 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
4446 block
->block_contents_size
, __FILE__
, __LINE__
);
4447 return(TNG_CRITICAL
);
4450 /* Read the whole block into block_contents to be able to write it to disk
4451 * even if it cannot be interpreted. */
4452 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
4453 tng_data
->input_file
) == 0)
4455 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
4456 return(TNG_CRITICAL
);
4459 /* FIXME: Does not check if the size of the contents matches the expected
4460 * size or if the contents can be read. */
4462 if(hash_mode
== TNG_USE_HASH
)
4464 tng_md5_hash_match_verify(block
, &same_hash
);
4465 if(same_hash
!= TNG_TRUE
)
4467 fprintf(stderr
, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4469 __FILE__
, __LINE__
);
4470 /* return(TNG_FAILURE); */
4474 frame_set
->n_mapping_blocks
++;
4475 mappings
= realloc(frame_set
->mappings
,
4476 sizeof(struct tng_particle_mapping
) *
4477 frame_set
->n_mapping_blocks
);
4480 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
4481 block
->block_contents_size
, __FILE__
, __LINE__
);
4482 free(frame_set
->mappings
);
4483 frame_set
->mappings
= 0;
4484 return(TNG_CRITICAL
);
4486 frame_set
->mappings
= mappings
;
4487 mapping
= &mappings
[frame_set
->n_mapping_blocks
- 1];
4490 memcpy(&mapping
->num_first_particle
, block
->block_contents
+offset
,
4491 sizeof(mapping
->num_first_particle
));
4492 if(tng_data
->input_endianness_swap_func_64
)
4494 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4495 &mapping
->num_first_particle
)
4498 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4499 __FILE__
, __LINE__
);
4502 offset
+= sizeof(mapping
->num_first_particle
);
4504 memcpy(&mapping
->n_particles
, block
->block_contents
+offset
,
4505 sizeof(mapping
->n_particles
));
4506 if(tng_data
->input_endianness_swap_func_64
)
4508 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4509 &mapping
->n_particles
)
4512 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4513 __FILE__
, __LINE__
);
4516 offset
+= sizeof(mapping
->n_particles
);
4518 mapping
->real_particle_numbers
= malloc(mapping
->n_particles
*
4520 if(!mapping
->real_particle_numbers
)
4522 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
4523 mapping
->n_particles
* sizeof(int64_t), __FILE__
, __LINE__
);
4524 return(TNG_CRITICAL
);
4527 /* If the byte order needs to be swapped the data must be read one value at
4528 * a time and swapped */
4529 if(tng_data
->input_endianness_swap_func_64
)
4531 for(i
= 0; i
< mapping
->n_particles
; i
++)
4533 memcpy(&mapping
->real_particle_numbers
[i
],
4534 block
->block_contents
+ offset
,
4536 if(tng_data
->input_endianness_swap_func_64(tng_data
,
4537 &mapping
->real_particle_numbers
[i
])
4540 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4541 __FILE__
, __LINE__
);
4543 offset
+= sizeof(int64_t);
4546 /* Otherwise the data can be read all at once */
4549 memcpy(mapping
->real_particle_numbers
, block
->block_contents
+ offset
,
4550 mapping
->n_particles
* sizeof(int64_t));
4554 return(TNG_SUCCESS
);
4557 /** Write the atom mappings of the current trajectory frame set
4558 * @param tng_data is a trajectory data container.
4559 * @param block is a general block container.
4560 * @param mapping_block_nr is the index of the mapping block to write.
4561 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4562 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4563 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4564 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4566 static tng_function_status tng_trajectory_mapping_block_write
4567 (tng_trajectory_t tng_data
,
4568 tng_gen_block_t block
,
4569 int mapping_block_nr
,
4570 const char hash_mode
)
4574 unsigned int name_len
;
4575 tng_particle_mapping_t mapping
=
4576 &tng_data
->current_trajectory_frame_set
.mappings
[mapping_block_nr
];
4578 if(mapping_block_nr
>=
4579 tng_data
->current_trajectory_frame_set
.n_mapping_blocks
)
4581 fprintf(stderr
, "TNG library: Mapping block index out of bounds. %s: %d\n",
4582 __FILE__
, __LINE__
);
4583 return(TNG_FAILURE
);
4586 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
4588 return(TNG_CRITICAL
);
4591 name_len
= (int)strlen("PARTICLE MAPPING");
4593 if(!block
->name
|| strlen(block
->name
) < name_len
)
4595 temp_name
= realloc(block
->name
, name_len
+ 1);
4598 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4599 name_len
+1, __FILE__
, __LINE__
);
4602 return(TNG_CRITICAL
);
4604 block
->name
= temp_name
;
4606 strcpy(block
->name
, "PARTICLE MAPPING");
4607 block
->id
= TNG_PARTICLE_MAPPING
;
4609 if(tng_trajectory_mapping_block_len_calculate(tng_data
,
4610 mapping
->n_particles
,
4611 &block
->block_contents_size
) !=
4614 fprintf(stderr
, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4615 __FILE__
, __LINE__
);
4616 return(TNG_CRITICAL
);
4619 if(block
->block_contents
)
4621 free(block
->block_contents
);
4623 block
->block_contents
= malloc(block
->block_contents_size
);
4624 if(!block
->block_contents
)
4626 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
4627 block
->block_contents_size
, __FILE__
, __LINE__
);
4628 return(TNG_CRITICAL
);
4631 memcpy(block
->block_contents
, &mapping
->num_first_particle
,
4632 sizeof(mapping
->num_first_particle
));
4633 if(tng_data
->output_endianness_swap_func_64
)
4635 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4636 (int64_t *)block
->header_contents
+offset
)
4639 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4640 __FILE__
, __LINE__
);
4643 offset
+= sizeof(mapping
->num_first_particle
);
4645 memcpy(block
->block_contents
+offset
, &mapping
->n_particles
,
4646 sizeof(mapping
->n_particles
));
4647 if(tng_data
->output_endianness_swap_func_64
)
4649 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4650 (int64_t *)block
->header_contents
+offset
)
4653 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4654 __FILE__
, __LINE__
);
4657 offset
+= sizeof(mapping
->n_particles
);
4659 if(tng_data
->output_endianness_swap_func_64
)
4661 for(i
= 0; i
< mapping
->n_particles
; i
++)
4663 memcpy(block
->block_contents
+offset
, &mapping
->real_particle_numbers
[i
],
4665 if(tng_data
->output_endianness_swap_func_64(tng_data
,
4666 (int64_t *)block
->header_contents
+offset
)
4669 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
4670 __FILE__
, __LINE__
);
4672 offset
+= sizeof(int64_t);
4677 memcpy(block
->block_contents
+offset
, mapping
->real_particle_numbers
,
4678 mapping
->n_particles
* sizeof(int64_t));
4682 if(tng_block_header_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
4684 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
4685 tng_data
->output_file_path
, __FILE__
, __LINE__
);
4686 return(TNG_CRITICAL
);
4689 if(fwrite(block
->block_contents
, block
->block_contents_size
, 1,
4690 tng_data
->output_file
) != 1)
4692 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n", __FILE__
, __LINE__
);
4693 return(TNG_CRITICAL
);
4696 return(TNG_SUCCESS
);
4699 /** Prepare a block for storing particle data
4700 * @param tng_data is a trajectory data container.
4701 * @param block_type_flag specifies if this is a trajectory block or a
4702 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4703 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4704 * error has occured.
4706 static tng_function_status tng_particle_data_block_create
4707 (tng_trajectory_t tng_data
,
4708 const char block_type_flag
)
4710 tng_trajectory_frame_set_t frame_set
=
4711 &tng_data
->current_trajectory_frame_set
;
4713 tng_particle_data_t data
;
4715 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
4717 frame_set
->n_particle_data_blocks
++;
4718 data
= realloc(frame_set
->tr_particle_data
,
4719 sizeof(struct tng_particle_data
) *
4720 frame_set
->n_particle_data_blocks
);
4723 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4724 sizeof(struct tng_particle_data
) *
4725 frame_set
->n_particle_data_blocks
,
4726 __FILE__
, __LINE__
);
4727 free(frame_set
->tr_particle_data
);
4728 frame_set
->tr_particle_data
= 0;
4729 return(TNG_CRITICAL
);
4731 frame_set
->tr_particle_data
= data
;
4735 tng_data
->n_particle_data_blocks
++;
4736 data
= realloc(tng_data
->non_tr_particle_data
,
4737 sizeof(struct tng_particle_data
) *
4738 tng_data
->n_particle_data_blocks
);
4741 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4742 sizeof(struct tng_particle_data
) *
4743 tng_data
->n_particle_data_blocks
,
4744 __FILE__
, __LINE__
);
4745 free(tng_data
->non_tr_particle_data
);
4746 tng_data
->non_tr_particle_data
= 0;
4747 return(TNG_CRITICAL
);
4749 tng_data
->non_tr_particle_data
= data
;
4752 return(TNG_SUCCESS
);
4755 static tng_function_status
tng_compress(tng_trajectory_t tng_data
,
4756 tng_gen_block_t block
,
4757 const int64_t n_frames
,
4758 const int64_t n_particles
,
4766 int64_t algo_find_n_frames
;
4767 unsigned long offset
;
4771 if(block
->id
!= TNG_TRAJ_POSITIONS
&&
4772 block
->id
!= TNG_TRAJ_VELOCITIES
)
4774 fprintf(stderr
, "TNG library: Can only compress positions and velocities with the "
4775 "TNG method. %s: %d\n", __FILE__
, __LINE__
);
4776 return(TNG_FAILURE
);
4778 if(type
!= TNG_FLOAT_DATA
&& type
!= TNG_DOUBLE_DATA
)
4780 fprintf(stderr
, "TNG library: Data type not supported. %s: %d\n", __FILE__
, __LINE__
);
4781 return(TNG_FAILURE
);
4784 if(n_frames
<= 0 || n_particles
<= 0)
4786 fprintf(stderr
, "TNG library: Missing frames or particles. Cannot compress data "
4787 "with the TNG method. %s: %d\n", __FILE__
, __LINE__
);
4788 return(TNG_FAILURE
);
4791 f_precision
= 1/(float)tng_data
->compression_precision
;
4792 d_precision
= 1/tng_data
->compression_precision
;
4794 if(block
->id
== TNG_TRAJ_POSITIONS
)
4796 /* If there is only one frame in this frame set and there might be more
4797 * do not store the algorithm as the compression algorithm, but find
4798 * the best one without storing it */
4799 if(n_frames
== 1 && tng_data
->frame_set_n_frames
> 1)
4801 nalgo
= tng_compress_nalgo();
4802 alt_algo
=malloc(nalgo
* sizeof *tng_data
->compress_algo_pos
);
4803 if(type
== TNG_FLOAT_DATA
)
4805 dest
= tng_compress_pos_float_find_algo(start_pos
, (int)n_particles
,
4814 dest
= tng_compress_pos_find_algo(start_pos
, (int)n_particles
,
4821 else if(!tng_data
->compress_algo_pos
)
4825 algo_find_n_frames
= 5;
4829 algo_find_n_frames
= n_frames
;
4832 nalgo
= tng_compress_nalgo();
4833 tng_data
->compress_algo_pos
=malloc(nalgo
*
4834 sizeof *tng_data
->compress_algo_pos
);
4835 if(type
== TNG_FLOAT_DATA
)
4837 dest
= tng_compress_pos_float_find_algo(start_pos
, (int)n_particles
,
4838 (int)algo_find_n_frames
,
4844 if(algo_find_n_frames
< n_frames
)
4846 dest
= tng_compress_pos_float(start_pos
, (int)n_particles
,
4849 0, tng_data
->compress_algo_pos
,
4855 dest
= tng_compress_pos_find_algo(start_pos
, (int)n_particles
,
4856 (int)algo_find_n_frames
,
4862 if(algo_find_n_frames
< n_frames
)
4864 dest
= tng_compress_pos(start_pos
, (int)n_particles
,
4867 tng_data
->compress_algo_pos
,
4874 if(type
== TNG_FLOAT_DATA
)
4876 dest
= tng_compress_pos_float(start_pos
, (int)n_particles
,
4879 tng_data
->compress_algo_pos
, &new_len
);
4883 dest
= tng_compress_pos(start_pos
, (int)n_particles
,
4886 tng_data
->compress_algo_pos
,
4891 else if(block
->id
== TNG_TRAJ_VELOCITIES
)
4893 /* If there is only one frame in this frame set and there might be more
4894 * do not store the algorithm as the compression algorithm, but find
4895 * the best one without storing it */
4896 if(n_frames
== 1 && tng_data
->frame_set_n_frames
> 1)
4898 nalgo
= tng_compress_nalgo();
4899 alt_algo
=malloc(nalgo
* sizeof *tng_data
->compress_algo_pos
);
4900 if(type
== TNG_FLOAT_DATA
)
4902 dest
= tng_compress_vel_float_find_algo(start_pos
, (int)n_particles
,
4911 dest
= tng_compress_vel_find_algo(start_pos
, (int)n_particles
,
4918 else if(!tng_data
->compress_algo_vel
)
4922 algo_find_n_frames
= 5;
4926 algo_find_n_frames
= n_frames
;
4929 nalgo
= tng_compress_nalgo();
4930 tng_data
->compress_algo_vel
=malloc(nalgo
*
4931 sizeof *tng_data
->compress_algo_vel
);
4933 if(type
== TNG_FLOAT_DATA
)
4935 dest
= tng_compress_vel_float_find_algo(start_pos
, (int)n_particles
,
4936 (int)algo_find_n_frames
,
4941 if(algo_find_n_frames
< n_frames
)
4943 dest
= tng_compress_vel_float(start_pos
, (int)n_particles
,
4946 0, tng_data
->compress_algo_vel
,
4952 dest
= tng_compress_vel_find_algo(start_pos
, (int)n_particles
,
4953 (int)algo_find_n_frames
,
4958 if(algo_find_n_frames
< n_frames
)
4960 dest
= tng_compress_vel(start_pos
, (int)n_particles
,
4963 0, tng_data
->compress_algo_vel
,
4970 if(type
== TNG_FLOAT_DATA
)
4972 dest
= tng_compress_vel_float(start_pos
, (int)n_particles
,
4981 dest
= tng_compress_vel(start_pos
, (int)n_particles
,
4992 fprintf(stderr
, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4993 return(TNG_FAILURE
);
4996 offset
= (unsigned long)((char *)start_pos
- block
->block_contents
);
5003 block
->block_contents_size
= new_len
+ offset
;
5005 temp
= realloc(block
->block_contents
, block
->block_contents_size
);
5008 free(block
->block_contents
);
5009 block
->block_contents
= 0;
5010 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5011 block
->block_contents_size
, __FILE__
, __LINE__
);
5012 return(TNG_CRITICAL
);
5014 block
->block_contents
= temp
;
5017 memcpy(temp
+ offset
, dest
, new_len
);
5022 fprintf(stderr
, "TNG library: Error during TNG compression. %s: %d\n", __FILE__
, __LINE__
);
5023 return(TNG_FAILURE
);
5026 return(TNG_SUCCESS
);
5029 static tng_function_status
tng_uncompress(tng_trajectory_t tng_data
,
5030 tng_gen_block_t block
,
5033 const unsigned long uncompressed_len
)
5038 unsigned long offset
;
5042 TNG_ASSERT(uncompressed_len
, "TNG library: The full length of the uncompressed data must be > 0.");
5044 if(block
->id
!= TNG_TRAJ_POSITIONS
&&
5045 block
->id
!= TNG_TRAJ_VELOCITIES
)
5047 fprintf(stderr
, "TNG library: Can only uncompress positions and velocities with the"
5049 return(TNG_FAILURE
);
5051 if(type
!= TNG_FLOAT_DATA
&& type
!= TNG_DOUBLE_DATA
)
5053 fprintf(stderr
, "TNG library: Data type not supported.\n");
5054 return(TNG_FAILURE
);
5057 if(type
== TNG_FLOAT_DATA
)
5059 f_dest
= malloc(uncompressed_len
);
5062 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5063 uncompressed_len
, __FILE__
, __LINE__
);
5064 return(TNG_CRITICAL
);
5066 result
= tng_compress_uncompress_float(start_pos
, f_dest
);
5070 d_dest
= malloc(uncompressed_len
);
5073 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5074 uncompressed_len
, __FILE__
, __LINE__
);
5075 return(TNG_CRITICAL
);
5077 result
= tng_compress_uncompress(start_pos
, d_dest
);
5082 fprintf(stderr
, "TNG library: Cannot uncompress TNG compressed block.\n");
5083 return(TNG_FAILURE
);
5086 offset
= (unsigned long)((char *)start_pos
- (char *)block
->block_contents
);
5088 block
->block_contents_size
= (int64_t)(uncompressed_len
+ offset
);
5090 temp
= realloc(block
->block_contents
, uncompressed_len
+ offset
);
5093 free(block
->block_contents
);
5094 block
->block_contents
= 0;
5103 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5104 block
->block_contents_size
, __FILE__
, __LINE__
);
5105 return(TNG_CRITICAL
);
5108 if(type
== TNG_FLOAT_DATA
)
5110 memcpy(temp
+ offset
, f_dest
, uncompressed_len
);
5114 memcpy(temp
+ offset
, d_dest
, uncompressed_len
);
5117 block
->block_contents
= temp
;
5127 return(TNG_SUCCESS
);
5131 static tng_function_status
tng_gzip_compress(tng_trajectory_t tng_data
,
5132 tng_gen_block_t block
,
5133 void *start_pos
, const int len
)
5137 unsigned long max_len
, stat
, offset
;
5140 max_len
= compressBound(len
);
5141 dest
= malloc(max_len
);
5144 fprintf(stderr
, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
5145 max_len
, __FILE__
, __LINE__
);
5146 return(TNG_CRITICAL
);
5149 stat
= compress(dest
, &max_len
, start_pos
, len
);
5150 if(stat
!= (unsigned long)Z_OK
)
5153 if(stat
== (unsigned long)Z_MEM_ERROR
)
5155 fprintf(stderr
, "TNG library: Not enough memory. ");
5157 else if(stat
== (unsigned long)Z_BUF_ERROR
)
5159 fprintf(stderr
, "TNG library: Destination buffer too small. ");
5161 fprintf(stderr
, "TNG library: Error gzipping data. %s: %d\n", __FILE__
, __LINE__
);
5162 return(TNG_FAILURE
);
5165 offset
= (char *)start_pos
- block
->block_contents
;
5167 block
->block_contents_size
= max_len
+ offset
;
5169 temp
= realloc(block
->block_contents
, block
->block_contents_size
);
5172 free(block
->block_contents
);
5174 block
->block_contents
= 0;
5175 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5176 block
->block_contents_size
, __FILE__
, __LINE__
);
5177 return(TNG_CRITICAL
);
5180 block
->block_contents
= temp
;
5182 memcpy(temp
+ offset
, dest
, max_len
);
5186 return(TNG_SUCCESS
);
5189 static tng_function_status
tng_gzip_uncompress(tng_trajectory_t tng_data
,
5190 tng_gen_block_t block
,
5192 unsigned long uncompressed_len
)
5200 offset
= (char *)start_pos
- (char *)block
->block_contents
;
5202 dest
= malloc(uncompressed_len
);
5205 fprintf(stderr
, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
5206 uncompressed_len
, __FILE__
, __LINE__
);
5207 return(TNG_CRITICAL
);
5210 stat
= uncompress(dest
, &uncompressed_len
, (Bytef
*) start_pos
,
5211 block
->block_contents_size
- offset
);
5216 if(stat
== (unsigned long)Z_MEM_ERROR
)
5218 fprintf(stderr
, "TNG library: Not enough memory. ");
5220 else if(stat
== (unsigned long)Z_BUF_ERROR
)
5222 fprintf(stderr
, "TNG library: Destination buffer too small. ");
5224 else if(stat
== (unsigned long)Z_DATA_ERROR
)
5226 fprintf(stderr
, "TNG library: Data corrupt. ");
5228 fprintf(stderr
, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__
,
5230 return(TNG_FAILURE
);
5234 block
->block_contents_size
= uncompressed_len
+ offset
;
5236 temp
= realloc(block
->block_contents
, uncompressed_len
+ offset
);
5239 free(block
->block_contents
);
5240 block
->block_contents
= 0;
5242 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5243 block
->block_contents_size
, __FILE__
, __LINE__
);
5244 return(TNG_CRITICAL
);
5247 memcpy(temp
+ offset
, dest
, uncompressed_len
);
5249 block
->block_contents
= temp
;
5252 return(TNG_SUCCESS
);
5256 /** Allocate memory for storing particle data.
5257 * The allocated block will be refered to by data->values.
5258 * @param tng_data is a trajectory data container.
5259 * @param data is the data struct, which will contain the allocated memory in
5261 * @param n_frames is the number of frames of data to store.
5262 * @param n_particles is the number of particles with data.
5263 * @param n_values_per_frame is the number of data values per particle and
5265 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5266 * error has occured.
5268 static tng_function_status tng_allocate_particle_data_mem
5269 (tng_trajectory_t tng_data
,
5270 tng_particle_data_t data
,
5272 int64_t stride_length
,
5273 const int64_t n_particles
,
5274 const int64_t n_values_per_frame
)
5277 int64_t i
, j
, k
, size
, frame_alloc
;
5280 if(n_particles
== 0 || n_values_per_frame
== 0)
5282 return(TNG_FAILURE
);
5285 if(data
->strings
&& data
->datatype
== TNG_CHAR_DATA
)
5287 for(i
= 0; i
< data
->n_frames
; i
++)
5289 for(j
= 0; j
< n_particles
; j
++)
5291 for(k
= 0; k
< data
->n_values_per_frame
; k
++)
5293 if(data
->strings
[i
][j
][k
])
5295 free(data
->strings
[i
][j
][k
]);
5298 free(data
->strings
[i
][j
]);
5300 free(data
->strings
[i
]);
5302 free(data
->strings
);
5304 data
->n_frames
= n_frames
;
5305 n_frames
= tng_max_i64(1, n_frames
);
5306 data
->stride_length
= tng_max_i64(1, stride_length
);
5307 data
->n_values_per_frame
= n_values_per_frame
;
5308 frame_alloc
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
5310 if(data
->datatype
== TNG_CHAR_DATA
)
5312 data
->strings
= malloc(sizeof(char ***) * frame_alloc
);
5313 for(i
= 0; i
< frame_alloc
; i
++)
5315 data
->strings
[i
] = malloc(sizeof(char **) *
5317 if(!data
->strings
[i
])
5319 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5320 sizeof(union data_values
*) * n_particles
,
5321 __FILE__
, __LINE__
);
5322 return(TNG_CRITICAL
);
5324 for(j
= 0; j
< n_particles
; j
++)
5326 data
->strings
[i
][j
] = malloc(sizeof(char *) *
5327 n_values_per_frame
);
5328 if(!data
->strings
[i
][j
])
5330 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5331 sizeof(union data_values
) * n_values_per_frame
,
5332 __FILE__
, __LINE__
);
5333 return(TNG_CRITICAL
);
5335 for(k
= 0; k
< n_values_per_frame
; k
++)
5337 data
->strings
[i
][j
][k
] = 0;
5344 switch(data
->datatype
)
5347 size
= sizeof(int64_t);
5349 case TNG_FLOAT_DATA
:
5350 size
= sizeof(float);
5352 case TNG_DOUBLE_DATA
:
5354 size
= sizeof(double);
5357 values
= realloc(data
->values
,
5358 size
* frame_alloc
*
5359 n_particles
* n_values_per_frame
);
5362 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
5363 size
* frame_alloc
*
5364 n_particles
* n_values_per_frame
,
5365 __FILE__
, __LINE__
);
5368 return(TNG_CRITICAL
);
5370 data
->values
= values
;
5372 return(TNG_SUCCESS
);
5375 static tng_function_status tng_particle_data_find
5376 (tng_trajectory_t tng_data
,
5378 tng_particle_data_t
*data
)
5380 int64_t block_index
, i
;
5381 tng_trajectory_frame_set_t frame_set
= &tng_data
->
5382 current_trajectory_frame_set
;
5383 char block_type_flag
;
5385 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0 ||
5386 tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
5388 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
5392 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
5396 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5398 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
5400 *data
= &frame_set
->tr_particle_data
[i
];
5401 if((*data
)->block_id
== id
)
5410 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
5412 *data
= &tng_data
->non_tr_particle_data
[i
];
5413 if((*data
)->block_id
== id
)
5420 if(block_index
== -1)
5422 return(TNG_FAILURE
);
5424 return(TNG_SUCCESS
);
5427 static tng_function_status tng_data_find
5428 (tng_trajectory_t tng_data
,
5430 tng_non_particle_data_t
*data
)
5432 int64_t block_index
, i
;
5433 tng_trajectory_frame_set_t frame_set
= &tng_data
->
5434 current_trajectory_frame_set
;
5435 char block_type_flag
;
5437 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0 ||
5438 tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
5440 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
5444 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
5448 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5450 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
5452 *data
= &frame_set
->tr_data
[i
];
5453 if((*data
)->block_id
== id
)
5459 if(block_index
== -1)
5461 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
5463 *data
= &tng_data
->non_tr_data
[i
];
5464 if((*data
)->block_id
== id
)
5474 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
5476 *data
= &tng_data
->non_tr_data
[i
];
5477 if((*data
)->block_id
== id
)
5484 if(block_index
== -1)
5486 return(TNG_FAILURE
);
5488 return(TNG_SUCCESS
);
5491 static tng_function_status tng_data_block_len_calculate
5492 (const tng_trajectory_t tng_data
,
5493 const tng_particle_data_t data
,
5494 const tng_bool is_particle_data
,
5495 const int64_t n_frames
,
5496 const int64_t frame_step
,
5497 const int64_t stride_length
,
5498 const int64_t num_first_particle
,
5499 const int64_t n_particles
,
5500 const char dependency
,
5501 int64_t *data_start_pos
,
5506 char ***first_dim_values
, **second_dim_values
;
5511 return(TNG_SUCCESS
);
5514 switch(data
->datatype
)
5520 size
= sizeof(int64_t);
5522 case TNG_FLOAT_DATA
:
5523 size
= sizeof(float);
5525 case TNG_DOUBLE_DATA
:
5527 size
= sizeof(double);
5530 *len
= sizeof(char) * 2 + sizeof(data
->n_values_per_frame
) +
5531 sizeof(data
->codec_id
);
5532 if(is_particle_data
)
5534 *len
+= sizeof(num_first_particle
) + sizeof(n_particles
);
5537 if(stride_length
> 1)
5539 *len
+= sizeof(data
->first_frame_with_data
) +
5540 sizeof(data
->stride_length
);
5543 if(data
->codec_id
!= TNG_UNCOMPRESSED
)
5545 *len
+= sizeof(data
->compression_multiplier
);
5548 if(dependency
& TNG_FRAME_DEPENDENT
)
5550 *len
+= sizeof(char);
5553 *data_start_pos
= *len
;
5555 if(data
->datatype
== TNG_CHAR_DATA
)
5557 if(is_particle_data
)
5559 for(i
= 0; i
< n_frames
; i
++)
5561 first_dim_values
= data
->strings
[i
];
5562 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
5565 second_dim_values
= first_dim_values
[j
];
5566 for(k
= 0; k
< data
->n_values_per_frame
; k
++)
5568 *len
+= strlen(second_dim_values
[k
]) + 1;
5575 for(i
= 0; i
< n_frames
; i
++)
5577 second_dim_values
= ((tng_non_particle_data_t
)data
)->strings
[i
];
5578 for(j
= 0; j
< data
->n_values_per_frame
; j
++)
5580 *len
+= strlen(second_dim_values
[j
]) + 1;
5587 *len
+= size
* frame_step
* n_particles
* data
->n_values_per_frame
;
5590 return(TNG_SUCCESS
);
5593 /** Read the values of a particle data block
5594 * @param tng_data is a trajectory data container.
5595 * @param block is the block to store the data (should already contain
5596 * the block headers and the block contents).
5597 * @param offset is the reading offset to point at the place where the actual
5598 * values are stored, starting from the beginning of the block_contents. The
5599 * offset is changed during the reading.
5600 * @param datatype is the type of data of the data block (char, int, float or
5602 * @param num_first_particle is the number of the first particle in the data
5603 * block. This should be the same as in the corresponding particle mapping
5605 * @param n_particles is the number of particles in the data block. This should
5606 * be the same as in the corresponding particle mapping block.
5607 * @param first_frame_with_data is the frame number of the first frame with data
5608 * in this data block.
5609 * @param stride_length is the number of frames between each data entry.
5610 * @param n_frames is the number of frames in this data block.
5611 * @param n_values is the number of values per particle and frame stored in this
5613 * @param codec_id is the ID of the codec to compress the data.
5614 * @param multiplier is the multiplication factor applied to each data value
5615 * before compression. This factor is applied since some compression algorithms
5616 * work only on integers.
5617 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5618 * error has occured.
5620 static tng_function_status tng_particle_data_read
5621 (tng_trajectory_t tng_data
,
5622 tng_gen_block_t block
,
5624 const char datatype
,
5625 const int64_t num_first_particle
,
5626 const int64_t n_particles
,
5627 const int64_t first_frame_with_data
,
5628 const int64_t stride_length
,
5630 const int64_t n_values
,
5631 const int64_t codec_id
,
5632 const double multiplier
)
5634 int64_t i
, j
, k
, tot_n_particles
, n_frames_div
;
5636 unsigned long data_size
;
5637 char ***first_dim_values
, **second_dim_values
;
5638 tng_particle_data_t data
;
5639 tng_trajectory_frame_set_t frame_set
=
5640 &tng_data
->current_trajectory_frame_set
;
5641 char block_type_flag
;
5643 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
5651 size
= sizeof(int64_t);
5653 case TNG_FLOAT_DATA
:
5654 size
= sizeof(float);
5656 case TNG_DOUBLE_DATA
:
5658 size
= sizeof(double);
5661 /* If the block does not exist, create it */
5662 if(tng_particle_data_find(tng_data
, block
->id
, &data
) != TNG_SUCCESS
)
5664 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
5666 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
5670 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
5673 if(tng_particle_data_block_create(tng_data
, block_type_flag
) !=
5676 fprintf(stderr
, "TNG library: Cannot create particle data block. %s: %d\n",
5677 __FILE__
, __LINE__
);
5678 return(TNG_CRITICAL
);
5680 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5682 data
= &frame_set
->tr_particle_data
[frame_set
->
5683 n_particle_data_blocks
- 1];
5687 data
= &tng_data
->non_tr_particle_data
[tng_data
->
5688 n_particle_data_blocks
- 1];
5690 data
->block_id
= block
->id
;
5692 data
->block_name
= malloc(strlen(block
->name
) + 1);
5693 if(!data
->block_name
)
5695 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5696 (int)strlen(block
->name
)+1, __FILE__
, __LINE__
);
5697 return(TNG_CRITICAL
);
5699 strcpy(data
->block_name
, block
->name
);
5701 data
->datatype
= datatype
;
5704 /* FIXME: Memory leak from strings. */
5707 data
->codec_id
= codec_id
;
5708 data
->compression_multiplier
= multiplier
;
5709 data
->last_retrieved_frame
= -1;
5712 if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
5713 tng_data
->current_trajectory_frame_set_input_file_pos
> 0 &&
5714 tng_data
->var_num_atoms_flag
)
5716 tot_n_particles
= frame_set
->n_particles
;
5720 tot_n_particles
= tng_data
->n_particles
;
5723 n_frames_div
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
5725 if(codec_id
!= TNG_UNCOMPRESSED
)
5727 data_size
= (unsigned long)(n_frames_div
* size
* n_particles
* n_values
);
5730 case TNG_XTC_COMPRESSION
:
5731 fprintf(stderr
, "TNG library: XTC compression not implemented yet.\n");
5733 case TNG_TNG_COMPRESSION
:
5734 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5735 if(tng_uncompress(tng_data
, block
, datatype
,
5736 block
->block_contents
+ *offset
,
5737 data_size
) != TNG_SUCCESS
)
5739 fprintf(stderr
, "TNG library: Could not read tng compressed block data. %s: %d\n",
5740 __FILE__
, __LINE__
);
5741 return(TNG_CRITICAL
);
5743 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5746 case TNG_GZIP_COMPRESSION
:
5747 /* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5748 if(tng_gzip_uncompress(tng_data
, block
,
5749 block
->block_contents
+ *offset
,
5750 data_size
) != TNG_SUCCESS
)
5752 fprintf(stderr
, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__
,
5754 return(TNG_CRITICAL
);
5756 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5761 /* Allocate memory */
5762 if(!data
->values
|| data
->n_frames
!= n_frames
||
5763 data
->n_values_per_frame
!= n_values
)
5765 if(tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
5767 tot_n_particles
, n_values
) !=
5770 fprintf(stderr
, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
5771 __FILE__
, __LINE__
);
5772 return(TNG_CRITICAL
);
5776 data
->first_frame_with_data
= first_frame_with_data
;
5778 if(datatype
== TNG_CHAR_DATA
)
5780 for(i
= 0; i
< n_frames_div
; i
++)
5782 first_dim_values
= data
->strings
[i
];
5783 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
5786 second_dim_values
= first_dim_values
[j
];
5787 for(k
= 0; k
< n_values
; k
++)
5789 len
= tng_min_i((int)strlen(block
->block_contents
+*offset
) + 1,
5791 if(second_dim_values
[k
])
5793 free(second_dim_values
[k
]);
5795 second_dim_values
[k
] = malloc(len
);
5796 if(!second_dim_values
[k
])
5798 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5799 len
, __FILE__
, __LINE__
);
5800 return(TNG_CRITICAL
);
5802 strncpy(second_dim_values
[k
],
5803 block
->block_contents
+*offset
, len
);
5811 memcpy((char *)data
->values
+ n_frames_div
* size
* n_values
*
5813 block
->block_contents
+ *offset
,
5814 block
->block_contents_size
- *offset
);
5817 case TNG_FLOAT_DATA
:
5818 if(tng_data
->input_endianness_swap_func_32
)
5820 for(i
= 0; i
< (block
->block_contents_size
- *offset
); i
+=size
)
5822 if(tng_data
->input_endianness_swap_func_32(tng_data
,
5823 (int32_t *)((char *)data
->values
+ i
))
5826 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
5827 __FILE__
, __LINE__
);
5833 case TNG_DOUBLE_DATA
:
5834 if(tng_data
->input_endianness_swap_func_64
)
5836 for(i
= 0; i
< (block
->block_contents_size
- *offset
); i
+=size
)
5838 if(tng_data
->input_endianness_swap_func_64(tng_data
,
5839 (int64_t *)((char *)data
->values
+ i
))
5842 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
5843 __FILE__
, __LINE__
);
5852 return(TNG_SUCCESS
);
5855 /** Write a particle data block
5856 * @param tng_data is a trajectory data container.
5857 * @param block is the block to store the data (should already contain
5858 * the block headers and the block contents).
5859 * @param block_index is the index number of the data block in the frame set.
5860 * @param mapping is the particle mapping that is relevant for the data block.
5861 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5862 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5863 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5864 * error has occured.
5866 static tng_function_status tng_particle_data_block_write
5867 (tng_trajectory_t tng_data
,
5868 tng_gen_block_t block
,
5869 const int64_t block_index
,
5870 const tng_particle_mapping_t mapping
,
5871 const char hash_mode
)
5873 int64_t n_particles
, num_first_particle
, n_frames
, stride_length
;
5874 int64_t frame_step
, data_start_pos
;
5877 size_t len
, offset
= 0;
5878 char dependency
, temp
, *temp_name
;
5880 char ***first_dim_values
, **second_dim_values
;
5881 tng_trajectory_frame_set_t frame_set
;
5882 tng_function_status stat
;
5884 tng_particle_data_t data
;
5885 char block_type_flag
;
5887 frame_set
= &tng_data
->current_trajectory_frame_set
;
5889 /* If we have already started writing frame sets it is too late to write
5890 * non-trajectory data blocks */
5891 if(tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
5893 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
5897 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
5900 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
5902 return(TNG_CRITICAL
);
5905 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5907 data
= &frame_set
->tr_particle_data
[block_index
];
5909 /* If this data block has not had any data added in this frame set
5910 * do not write it. */
5911 if(data
->first_frame_with_data
< frame_set
->first_frame
)
5913 return(TNG_SUCCESS
);
5916 stride_length
= tng_max_i64(1, data
->stride_length
);
5920 data
= &tng_data
->non_tr_particle_data
[block_index
];
5924 switch(data
->datatype
)
5930 size
= sizeof(int64_t);
5932 case TNG_FLOAT_DATA
:
5933 size
= sizeof(float);
5935 case TNG_DOUBLE_DATA
:
5937 size
= sizeof(double);
5940 len
= strlen(data
->block_name
) + 1;
5942 if(!block
->name
|| strlen(block
->name
) < len
)
5944 temp_name
= realloc(block
->name
, len
);
5947 fprintf(stderr
, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len
,
5948 __FILE__
, __LINE__
);
5951 return(TNG_CRITICAL
);
5953 block
->name
= temp_name
;
5955 strncpy(block
->name
, data
->block_name
, len
);
5956 block
->id
= data
->block_id
;
5958 /* If writing frame independent data data->n_frames is 0, but n_frames
5959 is used for the loop writing the data (and reserving memory) and needs
5961 n_frames
= tng_max_i64(1, data
->n_frames
);
5963 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
5965 /* If the frame set is finished before writing the full number of frames
5966 make sure the data block is not longer than the frame set. */
5967 n_frames
= tng_min_i64(n_frames
, frame_set
->n_frames
);
5969 n_frames
-= (data
->first_frame_with_data
- frame_set
->first_frame
);
5972 frame_step
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1:
5973 n_frames
/ stride_length
;
5975 /* TNG compression will use compression precision to get integers from
5976 * floating point data. The compression multiplier stores that information
5977 * to be able to return the precision of the compressed data. */
5978 if(data
->codec_id
== TNG_TNG_COMPRESSION
)
5980 data
->compression_multiplier
= tng_data
->compression_precision
;
5982 /* Uncompressed data blocks do not use compression multipliers at all.
5983 * GZip compression does not need it either. */
5984 else if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
->codec_id
== TNG_GZIP_COMPRESSION
)
5986 data
->compression_multiplier
= 1.0;
5989 if(mapping
&& mapping
->n_particles
!= 0)
5991 n_particles
= mapping
->n_particles
;
5992 num_first_particle
= mapping
->num_first_particle
;
5996 num_first_particle
= 0;
5997 if(tng_data
->var_num_atoms_flag
)
5999 n_particles
= frame_set
->n_particles
;
6003 n_particles
= tng_data
->n_particles
;
6007 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&& data
->n_frames
> 0)
6009 dependency
= TNG_FRAME_DEPENDENT
+ TNG_PARTICLE_DEPENDENT
;
6013 dependency
= TNG_PARTICLE_DEPENDENT
;
6016 if(tng_data_block_len_calculate(tng_data
, data
, TNG_TRUE
, n_frames
,
6017 frame_step
, stride_length
, num_first_particle
,
6018 n_particles
, dependency
, &data_start_pos
,
6019 &block
->block_contents_size
) != TNG_SUCCESS
)
6021 fprintf(stderr
, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
6022 __FILE__
, __LINE__
);
6023 return(TNG_CRITICAL
);
6026 if(block
->block_contents
)
6028 free(block
->block_contents
);
6030 block
->block_contents
= malloc(block
->block_contents_size
);
6031 if(!block
->block_contents
)
6033 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
6034 block
->block_contents_size
, __FILE__
, __LINE__
);
6035 return(TNG_CRITICAL
);
6039 memcpy(block
->block_contents
, &data
->datatype
, sizeof(char));
6040 offset
+= sizeof(char);
6042 memcpy(block
->block_contents
+offset
, &dependency
, sizeof(char));
6043 offset
+= sizeof(char);
6045 if(dependency
& TNG_FRAME_DEPENDENT
)
6047 if(stride_length
> 1)
6055 memcpy(block
->block_contents
+offset
, &temp
, sizeof(char));
6056 offset
+= sizeof(char);
6059 memcpy(block
->block_contents
+offset
, &data
->n_values_per_frame
,
6060 sizeof(data
->n_values_per_frame
));
6061 if(tng_data
->output_endianness_swap_func_64
)
6063 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6064 (int64_t *)block
->header_contents
+offset
)
6067 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6068 __FILE__
, __LINE__
);
6071 offset
+= sizeof(data
->n_values_per_frame
);
6073 memcpy(block
->block_contents
+offset
, &data
->codec_id
,
6074 sizeof(data
->codec_id
));
6075 if(tng_data
->output_endianness_swap_func_64
)
6077 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6078 (int64_t *)block
->header_contents
+offset
)
6081 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6082 __FILE__
, __LINE__
);
6085 offset
+= sizeof(data
->codec_id
);
6087 if(data
->codec_id
!= TNG_UNCOMPRESSED
)
6089 memcpy(block
->block_contents
+offset
, &data
->compression_multiplier
,
6090 sizeof(data
->compression_multiplier
));
6091 if(tng_data
->output_endianness_swap_func_64
)
6093 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6094 (int64_t *)block
->header_contents
+offset
)
6097 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6098 __FILE__
, __LINE__
);
6101 offset
+= sizeof(data
->compression_multiplier
);
6104 if(data
->n_frames
> 0 && stride_length
> 1)
6106 /* FIXME: first_frame_with_data is not reliably set */
6107 if(data
->first_frame_with_data
== 0)
6109 data
->first_frame_with_data
= frame_set
->first_frame
;
6111 memcpy(block
->block_contents
+offset
, &data
->first_frame_with_data
,
6112 sizeof(data
->first_frame_with_data
));
6113 if(tng_data
->output_endianness_swap_func_64
)
6115 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6116 (int64_t *)block
->header_contents
+offset
)
6119 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6120 __FILE__
, __LINE__
);
6123 offset
+= sizeof(data
->first_frame_with_data
);
6125 memcpy(block
->block_contents
+offset
, &stride_length
,
6126 sizeof(stride_length
));
6127 if(tng_data
->output_endianness_swap_func_64
)
6129 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6130 (int64_t *)block
->header_contents
+offset
)
6133 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6134 __FILE__
, __LINE__
);
6137 offset
+= sizeof(stride_length
);
6141 memcpy(block
->block_contents
+offset
, &num_first_particle
,
6142 sizeof(num_first_particle
));
6143 if(tng_data
->output_endianness_swap_func_64
)
6145 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6146 (int64_t *)block
->header_contents
+offset
)
6149 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6150 __FILE__
, __LINE__
);
6153 offset
+= sizeof(num_first_particle
);
6155 memcpy(block
->block_contents
+offset
, &n_particles
, sizeof(n_particles
));
6156 if(tng_data
->output_endianness_swap_func_64
)
6158 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6159 (int64_t *)block
->header_contents
+offset
)
6162 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6163 __FILE__
, __LINE__
);
6166 offset
+= sizeof(n_particles
);
6168 if(data
->datatype
== TNG_CHAR_DATA
)
6172 for(i
= 0; i
< frame_step
; i
++)
6174 first_dim_values
= data
->strings
[i
];
6175 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
6178 second_dim_values
= first_dim_values
[j
];
6179 for(k
= 0; k
< data
->n_values_per_frame
; k
++)
6181 len
= (unsigned int)strlen(second_dim_values
[k
]) + 1;
6182 strncpy(block
->block_contents
+offset
,
6183 second_dim_values
[k
], len
);
6190 else if(data
->values
)
6192 memcpy(block
->block_contents
+ offset
, data
->values
,
6193 block
->block_contents_size
- offset
);
6195 switch(data
->datatype
)
6197 case TNG_FLOAT_DATA
:
6198 if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
-> codec_id
== TNG_GZIP_COMPRESSION
||
6199 data
->codec_id
== TNG_TNG_COMPRESSION
)
6201 if(tng_data
->input_endianness_swap_func_32
)
6203 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
6205 if(tng_data
->input_endianness_swap_func_32(tng_data
,
6206 (int32_t *)(block
->block_contents
+ i
))
6209 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6210 __FILE__
, __LINE__
);
6217 multiplier
= data
->compression_multiplier
;
6218 if(fabs(multiplier
- 1.0) > 0.00001 ||
6219 tng_data
->input_endianness_swap_func_32
)
6221 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
6223 *(float *)(block
->block_contents
+ i
) *= (float)multiplier
;
6224 if(tng_data
->input_endianness_swap_func_32
&&
6225 tng_data
->input_endianness_swap_func_32(tng_data
,
6226 (int32_t *)(block
->block_contents
+ i
))
6229 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6230 __FILE__
, __LINE__
);
6237 if(tng_data
->input_endianness_swap_func_64
)
6239 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
6241 if(tng_data
->input_endianness_swap_func_64(tng_data
,
6242 (int64_t *)(block
->block_contents
+ i
))
6245 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6246 __FILE__
, __LINE__
);
6251 case TNG_DOUBLE_DATA
:
6252 if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
-> codec_id
== TNG_GZIP_COMPRESSION
||
6253 data
->codec_id
== TNG_TNG_COMPRESSION
)
6255 if(tng_data
->input_endianness_swap_func_64
)
6257 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
6259 if(tng_data
->input_endianness_swap_func_64(tng_data
,
6260 (int64_t *)(block
->block_contents
+ i
))
6263 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6264 __FILE__
, __LINE__
);
6271 multiplier
= data
->compression_multiplier
;
6272 if(fabs(multiplier
- 1.0) > 0.00001 ||
6273 tng_data
->input_endianness_swap_func_64
)
6275 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
6277 *(double *)(block
->block_contents
+ i
) *= multiplier
;
6278 if(tng_data
->input_endianness_swap_func_64
&&
6279 tng_data
->input_endianness_swap_func_64(tng_data
,
6280 (int64_t *)(block
->block_contents
+ i
))
6283 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6284 __FILE__
, __LINE__
);
6296 memset(block
->block_contents
+offset
, 0, block
->block_contents_size
- offset
);
6299 frame_set
->n_written_frames
+= frame_set
->n_unwritten_frames
;
6300 frame_set
->n_unwritten_frames
= 0;
6302 if(block_type_flag
== TNG_NON_TRAJECTORY_BLOCK
|| frame_set
->n_written_frames
> 0)
6304 switch(data
->codec_id
)
6306 case TNG_XTC_COMPRESSION
:
6307 fprintf(stderr
, "TNG library: XTC compression not implemented yet.\n");
6308 data
->codec_id
= TNG_UNCOMPRESSED
;
6310 case TNG_TNG_COMPRESSION
:
6311 stat
= tng_compress(tng_data
, block
, frame_step
,
6312 n_particles
, data
->datatype
,
6313 block
->block_contents
+ data_start_pos
);
6314 if(stat
!= TNG_SUCCESS
)
6316 fprintf(stderr
, "TNG library: Could not write tng compressed block data. %s: %d\n",
6317 __FILE__
, __LINE__
);
6318 if(stat
== TNG_CRITICAL
)
6320 return(TNG_CRITICAL
);
6322 /* Set the data again, but with no compression (to write only
6323 * the relevant data) */
6324 data
->codec_id
= TNG_UNCOMPRESSED
;
6325 stat
= tng_particle_data_block_write(tng_data
, block
,
6326 block_index
, mapping
,
6332 case TNG_GZIP_COMPRESSION
:
6333 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
6334 stat
= tng_gzip_compress(tng_data
, block
,
6335 block
->block_contents
+ data_start_pos
,
6336 block
->block_contents_size
- data_start_pos
);
6337 if(stat
!= TNG_SUCCESS
)
6339 fprintf(stderr
, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__
,
6341 if(stat
== TNG_CRITICAL
)
6343 return(TNG_CRITICAL
);
6345 /* Set the data again, but with no compression (to write only
6346 * the relevant data) */
6347 data
->codec_id
= TNG_UNCOMPRESSED
;
6348 stat
= tng_particle_data_block_write(tng_data
, block
,
6349 block_index
, mapping
,
6353 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6359 if(tng_block_header_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
6361 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
6362 tng_data
->output_file_path
, __FILE__
, __LINE__
);
6363 return(TNG_CRITICAL
);
6366 if(fwrite(block
->block_contents
, block
->block_contents_size
, 1,
6367 tng_data
->output_file
) != 1)
6369 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n", __FILE__
,
6371 return(TNG_CRITICAL
);
6374 return(TNG_SUCCESS
);
6378 /** Create a non-particle data block
6379 * @param tng_data is a trajectory data container.
6380 * @param block_type_flag specifies if this is a trajectory block or a
6381 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
6382 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6383 * error has occured.
6385 static tng_function_status tng_data_block_create
6386 (tng_trajectory_t tng_data
,
6387 const char block_type_flag
)
6389 tng_trajectory_frame_set_t frame_set
=
6390 &tng_data
->current_trajectory_frame_set
;
6392 tng_non_particle_data_t data
;
6394 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
6396 frame_set
->n_data_blocks
++;
6397 data
= realloc(frame_set
->tr_data
, sizeof(struct tng_non_particle_data
) *
6398 frame_set
->n_data_blocks
);
6401 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6402 sizeof(struct tng_non_particle_data
) * frame_set
->n_data_blocks
,
6403 __FILE__
, __LINE__
);
6404 free(frame_set
->tr_data
);
6405 frame_set
->tr_data
= 0;
6406 return(TNG_CRITICAL
);
6408 frame_set
->tr_data
= data
;
6412 tng_data
->n_data_blocks
++;
6413 data
= realloc(tng_data
->non_tr_data
, sizeof(struct tng_non_particle_data
) *
6414 tng_data
->n_data_blocks
);
6417 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
6418 sizeof(struct tng_non_particle_data
) * tng_data
->n_data_blocks
,
6419 __FILE__
, __LINE__
);
6420 free(tng_data
->non_tr_data
);
6421 tng_data
->non_tr_data
= 0;
6422 return(TNG_CRITICAL
);
6424 tng_data
->non_tr_data
= data
;
6427 return(TNG_SUCCESS
);
6431 /** Allocate memory for storing non-particle data.
6432 * The allocated block will be refered to by data->values.
6433 * @param tng_data is a trajectory data container.
6434 * @param data is the data struct, which will contain the allocated memory in
6436 * @param n_frames is the number of frames of data to store.
6437 * @param n_values_per_frame is the number of data values per frame.
6438 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6439 * error has occured.
6441 static tng_function_status tng_allocate_data_mem
6442 (tng_trajectory_t tng_data
,
6443 tng_non_particle_data_t data
,
6445 int64_t stride_length
,
6446 const int64_t n_values_per_frame
)
6449 int64_t i
, j
, size
, frame_alloc
;
6452 if(n_values_per_frame
== 0)
6454 return(TNG_FAILURE
);
6457 if(data
->strings
&& data
->datatype
== TNG_CHAR_DATA
)
6459 for(i
= 0; i
< data
->n_frames
; i
++)
6461 for(j
= 0; j
< data
->n_values_per_frame
; j
++)
6463 if(data
->strings
[i
][j
])
6465 free(data
->strings
[i
][j
]);
6466 data
->strings
[i
][j
] = 0;
6469 free(data
->strings
[i
]);
6470 data
->strings
[i
] = 0;
6472 free(data
->strings
);
6474 data
->n_frames
= n_frames
;
6475 data
->stride_length
= tng_max_i64(1, stride_length
);
6476 n_frames
= tng_max_i64(1, n_frames
);
6477 data
->n_values_per_frame
= n_values_per_frame
;
6478 frame_alloc
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
6480 if(data
->datatype
== TNG_CHAR_DATA
)
6482 data
->strings
= malloc(sizeof(char **) * frame_alloc
);
6483 for(i
= 0; i
< frame_alloc
; i
++)
6485 data
->strings
[i
] = malloc(sizeof(char *) * n_values_per_frame
);
6486 if(!data
->strings
[i
])
6488 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
6490 __FILE__
, __LINE__
);
6491 return(TNG_CRITICAL
);
6493 for(j
= 0; j
< n_values_per_frame
; j
++)
6495 data
->strings
[i
][j
] = 0;
6501 switch(data
->datatype
)
6504 size
= sizeof(int64_t);
6506 case TNG_FLOAT_DATA
:
6507 size
= sizeof(float);
6509 case TNG_DOUBLE_DATA
:
6511 size
= sizeof(double);
6514 values
= realloc(data
->values
,
6515 size
* frame_alloc
*
6516 n_values_per_frame
);
6519 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
6520 size
* frame_alloc
*
6522 __FILE__
, __LINE__
);
6525 return(TNG_CRITICAL
);
6527 data
->values
= values
;
6530 return(TNG_SUCCESS
);
6533 /** Read the values of a non-particle data block
6534 * @param tng_data is a trajectory data container.
6535 * @param block is the block to store the data (should already contain
6536 * the block headers and the block contents).
6537 * @param offset is the reading offset to point at the place where the actual
6538 * values are stored, starting from the beginning of the block_contents. The
6539 * offset is changed during the reading.
6540 * @param datatype is the type of data of the data block (char, int, float or
6542 * @param first_frame_with_data is the frame number of the first frame with data
6543 * in this data block.
6544 * @param stride_length is the number of frames between each data entry.
6545 * @param n_frames is the number of frames in this data block.
6546 * @param n_values is the number of values per frame stored in this data block.
6547 * @param codec_id is the ID of the codec to compress the data.
6548 * @param multiplier is the multiplication factor applied to each data value
6549 * before compression. This factor is applied since some compression algorithms
6550 * work only on integers.
6551 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6552 * error has occured.
6554 static tng_function_status
tng_data_read(tng_trajectory_t tng_data
,
6555 tng_gen_block_t block
,
6557 const char datatype
,
6558 const int64_t first_frame_with_data
,
6559 const int64_t stride_length
,
6561 const int64_t n_values
,
6562 const int64_t codec_id
,
6563 const double multiplier
)
6565 int64_t i
, j
, n_frames_div
;
6568 unsigned long data_size
;
6570 tng_non_particle_data_t data
;
6571 tng_trajectory_frame_set_t frame_set
=
6572 &tng_data
->current_trajectory_frame_set
;
6573 char block_type_flag
;
6575 TNG_ASSERT(offset
!= 0, "TNG library: offset must not be a NULL pointer.");
6577 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
6585 size
= sizeof(int64_t);
6587 case TNG_FLOAT_DATA
:
6588 size
= sizeof(float);
6590 case TNG_DOUBLE_DATA
:
6592 size
= sizeof(double);
6595 /* If the block does not exist, create it */
6596 if(tng_data_find(tng_data
, block
->id
, &data
) != TNG_SUCCESS
)
6598 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
6600 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
6604 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
6607 if(tng_data_block_create(tng_data
, block_type_flag
) !=
6610 fprintf(stderr
, "TNG library: Cannot create particle data block. %s: %d\n",
6611 __FILE__
, __LINE__
);
6612 return(TNG_CRITICAL
);
6614 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
6616 data
= &frame_set
->tr_data
[frame_set
->n_data_blocks
- 1];
6620 data
= &tng_data
->non_tr_data
[tng_data
->n_data_blocks
- 1];
6622 data
->block_id
= block
->id
;
6624 data
->block_name
= malloc(strlen(block
->name
) + 1);
6625 if(!data
->block_name
)
6627 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6628 (int)strlen(block
->name
)+1, __FILE__
, __LINE__
);
6629 return(TNG_CRITICAL
);
6631 strcpy(data
->block_name
, block
->name
);
6633 data
->datatype
= datatype
;
6636 /* FIXME: Memory leak from strings. */
6639 data
->codec_id
= codec_id
;
6640 data
->compression_multiplier
= multiplier
;
6641 data
->last_retrieved_frame
= -1;
6644 n_frames_div
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1 : n_frames
/ stride_length
;
6646 if(codec_id
!= TNG_UNCOMPRESSED
)
6651 case TNG_GZIP_COMPRESSION
:
6652 data_size
= n_frames_div
* size
* n_values
;
6653 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6654 if(tng_gzip_uncompress(tng_data
, block
,
6655 block
->block_contents
+ *offset
,
6656 data_size
) != TNG_SUCCESS
)
6658 fprintf(stderr
, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__
,
6660 return(TNG_CRITICAL
);
6662 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6668 /* Allocate memory */
6669 if(!data
->values
|| data
->n_frames
!= n_frames
||
6670 data
->n_values_per_frame
!= n_values
)
6672 if(tng_allocate_data_mem(tng_data
, data
, n_frames
, stride_length
,
6676 fprintf(stderr
, "TNG library: Cannot allocate memory for data. %s: %d\n",
6677 __FILE__
, __LINE__
);
6678 return(TNG_CRITICAL
);
6682 data
->first_frame_with_data
= first_frame_with_data
;
6684 if(datatype
== TNG_CHAR_DATA
)
6686 for(i
= 0; i
< n_frames_div
; i
++)
6688 for(j
= 0; j
< n_values
; j
++)
6690 len
= tng_min_i((int)strlen(block
->block_contents
+*offset
) + 1,
6692 if(data
->strings
[i
][j
])
6694 free(data
->strings
[i
][j
]);
6696 data
->strings
[i
][j
] = malloc(len
);
6697 if(!data
->strings
[i
][j
])
6699 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
6700 len
, __FILE__
, __LINE__
);
6701 return(TNG_CRITICAL
);
6703 strncpy(data
->strings
[i
][j
], block
->block_contents
+*offset
,
6711 memcpy(data
->values
, block
->block_contents
+ *offset
,
6712 block
->block_contents_size
- *offset
);
6715 case TNG_FLOAT_DATA
:
6716 if(tng_data
->input_endianness_swap_func_32
)
6718 for(i
= 0; i
< (block
->block_contents_size
- *offset
); i
+=size
)
6720 if(tng_data
->input_endianness_swap_func_32(tng_data
,
6721 (int32_t *)((char *)data
->values
+ i
))
6724 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6725 __FILE__
, __LINE__
);
6731 case TNG_DOUBLE_DATA
:
6732 if(tng_data
->input_endianness_swap_func_64
)
6734 for(i
= 0; i
< (block
->block_contents_size
- *offset
); i
+=size
)
6736 if(tng_data
->input_endianness_swap_func_64(tng_data
,
6737 (int64_t *)((char *)data
->values
+ i
))
6740 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6741 __FILE__
, __LINE__
);
6750 return(TNG_SUCCESS
);
6753 /** Write a non-particle data block
6754 * @param tng_data is a trajectory data container.
6755 * @param block is the block to store the data (should already contain
6756 * the block headers and the block contents).
6757 * @param block_index is the index number of the data block in the frame set.
6758 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6759 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
6760 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6761 * error has occured.
6763 static tng_function_status
tng_data_block_write(tng_trajectory_t tng_data
,
6764 tng_gen_block_t block
,
6765 const int64_t block_index
,
6766 const char hash_mode
)
6768 int64_t n_frames
, stride_length
, frame_step
, data_start_pos
;
6770 int offset
= 0, size
;
6773 tng_function_status stat
;
6775 char temp
, dependency
, *temp_name
;
6777 tng_trajectory_frame_set_t frame_set
=
6778 &tng_data
->current_trajectory_frame_set
;
6780 tng_non_particle_data_t data
;
6781 char block_type_flag
;
6783 /* If we have already started writing frame sets it is too late to write
6784 * non-trajectory data blocks */
6785 if(tng_data
->current_trajectory_frame_set_output_file_pos
> 0)
6787 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
6791 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
6794 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
6796 return(TNG_CRITICAL
);
6799 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
6801 data
= &frame_set
->tr_data
[block_index
];
6803 /* If this data block has not had any data added in this frame set
6804 * do not write it. */
6805 if(data
->first_frame_with_data
< frame_set
->first_frame
)
6807 return(TNG_SUCCESS
);
6810 stride_length
= tng_max_i64(1, data
->stride_length
);
6814 data
= &tng_data
->non_tr_data
[block_index
];
6818 switch(data
->datatype
)
6824 size
= sizeof(int64_t);
6826 case TNG_FLOAT_DATA
:
6827 size
= sizeof(float);
6829 case TNG_DOUBLE_DATA
:
6831 size
= sizeof(double);
6834 len
= (unsigned int)strlen(data
->block_name
) + 1;
6836 if(!block
->name
|| strlen(block
->name
) < len
)
6838 temp_name
= realloc(block
->name
, len
);
6841 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
+1,
6842 __FILE__
, __LINE__
);
6845 return(TNG_CRITICAL
);
6847 block
->name
= temp_name
;
6849 strncpy(block
->name
, data
->block_name
, len
);
6850 block
->id
= data
->block_id
;
6852 /* If writing frame independent data data->n_frames is 0, but n_frames
6853 is used for the loop writing the data (and reserving memory) and needs
6855 n_frames
= tng_max_i64(1, data
->n_frames
);
6857 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
6859 /* If the frame set is finished before writing the full number of frames
6860 make sure the data block is not longer than the frame set. */
6861 n_frames
= tng_min_i64(n_frames
, frame_set
->n_frames
);
6863 n_frames
-= (data
->first_frame_with_data
- frame_set
->first_frame
);
6866 frame_step
= (n_frames
% stride_length
) ? n_frames
/ stride_length
+ 1:
6867 n_frames
/ stride_length
;
6869 /* TNG compression will use compression precision to get integers from
6870 * floating point data. The compression multiplier stores that information
6871 * to be able to return the precision of the compressed data. */
6872 if(data
->codec_id
== TNG_TNG_COMPRESSION
)
6874 data
->compression_multiplier
= tng_data
->compression_precision
;
6876 /* Uncompressed data blocks do not use compression multipliers at all.
6877 * GZip compression does not need it either. */
6878 else if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
->codec_id
== TNG_GZIP_COMPRESSION
)
6880 data
->compression_multiplier
= 1.0;
6883 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&& data
->n_frames
> 0)
6885 dependency
= TNG_FRAME_DEPENDENT
;
6892 if(tng_data_block_len_calculate(tng_data
, (tng_particle_data_t
)data
, TNG_FALSE
, n_frames
,
6893 frame_step
, stride_length
, 0,
6894 1, dependency
, &data_start_pos
,
6895 &block
->block_contents_size
) != TNG_SUCCESS
)
6897 fprintf(stderr
, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
6898 __FILE__
, __LINE__
);
6899 return(TNG_CRITICAL
);
6902 if(block
->block_contents
)
6904 free(block
->block_contents
);
6906 block
->block_contents
= malloc(block
->block_contents_size
);
6907 if(!block
->block_contents
)
6909 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
6910 block
->block_contents_size
, __FILE__
, __LINE__
);
6911 return(TNG_CRITICAL
);
6915 memcpy(block
->block_contents
, &data
->datatype
, sizeof(char));
6916 offset
+= sizeof(char);
6918 memcpy(block
->block_contents
+offset
, &dependency
, sizeof(char));
6919 offset
+= sizeof(char);
6921 if(dependency
& TNG_FRAME_DEPENDENT
)
6923 if(stride_length
> 1)
6931 memcpy(block
->block_contents
+offset
, &temp
, sizeof(char));
6932 offset
+= sizeof(char);
6935 memcpy(block
->block_contents
+offset
, &data
->n_values_per_frame
,
6936 sizeof(data
->n_values_per_frame
));
6937 if(tng_data
->output_endianness_swap_func_64
)
6939 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6940 (int64_t *)block
->header_contents
+offset
)
6943 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6944 __FILE__
, __LINE__
);
6947 offset
+= sizeof(data
->n_values_per_frame
);
6949 memcpy(block
->block_contents
+offset
, &data
->codec_id
,
6950 sizeof(data
->codec_id
));
6951 if(tng_data
->output_endianness_swap_func_64
)
6953 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6954 (int64_t *)block
->header_contents
+offset
)
6957 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6958 __FILE__
, __LINE__
);
6961 offset
+= sizeof(data
->codec_id
);
6963 if(data
->codec_id
!= TNG_UNCOMPRESSED
)
6965 memcpy(block
->block_contents
+offset
, &data
->compression_multiplier
,
6966 sizeof(data
->compression_multiplier
));
6967 if(tng_data
->output_endianness_swap_func_64
)
6969 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6970 (int64_t *)block
->header_contents
+offset
)
6973 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6974 __FILE__
, __LINE__
);
6977 offset
+= sizeof(data
->compression_multiplier
);
6980 if(data
->n_frames
> 0 && stride_length
> 1)
6982 /* FIXME: first_frame_with_data is not reliably set */
6983 if(data
->first_frame_with_data
== 0)
6985 data
->first_frame_with_data
= frame_set
->first_frame
;
6987 memcpy(block
->block_contents
+offset
, &data
->first_frame_with_data
,
6988 sizeof(data
->first_frame_with_data
));
6989 if(tng_data
->output_endianness_swap_func_64
)
6991 if(tng_data
->output_endianness_swap_func_64(tng_data
,
6992 (int64_t *)block
->header_contents
+offset
)
6995 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
6996 __FILE__
, __LINE__
);
6999 offset
+= sizeof(data
->first_frame_with_data
);
7001 memcpy(block
->block_contents
+offset
, &stride_length
,
7002 sizeof(data
->stride_length
));
7003 if(tng_data
->output_endianness_swap_func_64
)
7005 if(tng_data
->output_endianness_swap_func_64(tng_data
,
7006 (int64_t *)block
->header_contents
+offset
)
7009 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7010 __FILE__
, __LINE__
);
7013 offset
+= sizeof(data
->stride_length
);
7016 if(data
->datatype
== TNG_CHAR_DATA
)
7020 for(i
= 0; i
< frame_step
; i
++)
7022 for(j
= 0; j
< data
->n_values_per_frame
; j
++)
7024 len
= (unsigned int)strlen(data
->strings
[i
][j
]) + 1;
7025 strncpy(block
->block_contents
+offset
, data
->strings
[i
][j
],
7032 else if(data
->values
)
7034 memcpy(block
->block_contents
+ offset
, data
->values
,
7035 block
->block_contents_size
- offset
);
7036 switch(data
->datatype
)
7038 case TNG_FLOAT_DATA
:
7039 if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
-> codec_id
== TNG_GZIP_COMPRESSION
||
7040 data
->codec_id
== TNG_TNG_COMPRESSION
)
7042 if(tng_data
->input_endianness_swap_func_32
)
7044 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
7046 if(tng_data
->input_endianness_swap_func_32(tng_data
,
7047 (int32_t *)(block
->block_contents
+ i
))
7050 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7051 __FILE__
, __LINE__
);
7058 multiplier
= data
->compression_multiplier
;
7059 if(fabs(multiplier
- 1.0) > 0.00001 ||
7060 tng_data
->input_endianness_swap_func_32
)
7062 for(i
= offset
; block
->block_contents_size
; i
+=size
)
7064 *(float *)(block
->block_contents
+ i
) *= (float)multiplier
;
7065 if(tng_data
->input_endianness_swap_func_32
&&
7066 tng_data
->input_endianness_swap_func_32(tng_data
,
7067 (int32_t *)(block
->block_contents
+ i
))
7070 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7071 __FILE__
, __LINE__
);
7078 if(tng_data
->input_endianness_swap_func_64
)
7080 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
7082 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7083 (int64_t *)(block
->block_contents
+ i
))
7086 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7087 __FILE__
, __LINE__
);
7092 case TNG_DOUBLE_DATA
:
7093 if(data
->codec_id
== TNG_UNCOMPRESSED
|| data
-> codec_id
== TNG_GZIP_COMPRESSION
||
7094 data
->codec_id
== TNG_TNG_COMPRESSION
)
7096 if(tng_data
->input_endianness_swap_func_64
)
7098 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
7100 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7101 (int64_t *)(block
->block_contents
+ i
))
7104 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7105 __FILE__
, __LINE__
);
7112 multiplier
= data
->compression_multiplier
;
7113 if(fabs(multiplier
- 1.0) > 0.00001 ||
7114 tng_data
->input_endianness_swap_func_64
)
7116 for(i
= offset
; i
< block
->block_contents_size
; i
+=size
)
7118 *(double *)(block
->block_contents
+ i
) *= multiplier
;
7119 if(tng_data
->input_endianness_swap_func_64
&&
7120 tng_data
->input_endianness_swap_func_64(tng_data
,
7121 (int64_t *)(block
->block_contents
+ i
))
7124 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7125 __FILE__
, __LINE__
);
7137 memset(block
->block_contents
+offset
, 0, block
->block_contents_size
- offset
);
7140 frame_set
->n_written_frames
+= frame_set
->n_unwritten_frames
;
7141 frame_set
->n_unwritten_frames
= 0;
7143 if(block_type_flag
== TNG_NON_TRAJECTORY_BLOCK
|| frame_set
->n_written_frames
> 0)
7145 switch(data
->codec_id
)
7148 case TNG_GZIP_COMPRESSION
:
7149 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
7150 stat
= tng_gzip_compress(tng_data
, block
,
7151 block
->block_contents
+ data_start_pos
,
7152 block
->block_contents_size
- data_start_pos
);
7153 if(stat
!= TNG_SUCCESS
)
7155 fprintf(stderr
, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__
,
7157 if(stat
== TNG_CRITICAL
)
7159 return(TNG_CRITICAL
);
7161 data
->codec_id
= TNG_UNCOMPRESSED
;
7163 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
7169 if(tng_block_header_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
7171 fprintf(stderr
, "TNG library: Cannot write header of file %s. %s: %d\n",
7172 tng_data
->output_file_path
, __FILE__
, __LINE__
);
7173 return(TNG_CRITICAL
);
7176 if(fwrite(block
->block_contents
, block
->block_contents_size
, 1,
7177 tng_data
->output_file
) != 1)
7179 fprintf(stderr
, "TNG library: Could not write all block data. %s: %d\n",
7180 __FILE__
, __LINE__
);
7181 return(TNG_CRITICAL
);
7184 return(TNG_SUCCESS
);
7187 /** Read the meta information of a data block (particle or non-particle data).
7188 * @param tng_data is a trajectory data container.
7189 * @param block is the block to store the data (should already contain
7190 * the block headers).
7191 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7192 * error has occured.
7194 static tng_function_status tng_data_block_meta_information_read
7195 (tng_trajectory_t tng_data
,
7196 tng_gen_block_t block
,
7203 int64_t *first_frame_with_data
,
7204 int64_t *stride_length
,
7206 int64_t *num_first_particle
,
7207 int64_t *block_n_particles
,
7213 if(block
->block_contents
)
7215 contents
= block
->block_contents
;
7219 meta_size
= 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7220 contents
= malloc(meta_size
);
7223 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
7224 meta_size
, __FILE__
, __LINE__
);
7227 if(fread(contents
, meta_size
, 1, tng_data
->input_file
) == 0)
7229 fprintf(stderr
, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__
, __LINE__
);
7231 return(TNG_CRITICAL
);
7235 memcpy(datatype
, contents
+*offset
,
7237 *offset
+= sizeof(*datatype
);
7239 memcpy(dependency
, contents
+*offset
,
7240 sizeof(*dependency
));
7241 *offset
+= sizeof(*dependency
);
7243 if(*dependency
& TNG_FRAME_DEPENDENT
)
7245 memcpy(sparse_data
, contents
+*offset
,
7246 sizeof(*sparse_data
));
7247 *offset
+= sizeof(*sparse_data
);
7250 memcpy(n_values
, contents
+*offset
,
7252 if(tng_data
->input_endianness_swap_func_64
)
7254 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7258 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7259 __FILE__
, __LINE__
);
7262 *offset
+= sizeof(*n_values
);
7264 memcpy(codec_id
, contents
+*offset
,
7266 if(tng_data
->input_endianness_swap_func_64
)
7268 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7272 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7273 __FILE__
, __LINE__
);
7276 *offset
+= sizeof(*codec_id
);
7278 if(*codec_id
!= TNG_UNCOMPRESSED
)
7280 memcpy(multiplier
, contents
+*offset
,
7281 sizeof(*multiplier
));
7282 if(tng_data
->input_endianness_swap_func_64
)
7284 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7285 (int64_t *) multiplier
)
7288 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7289 __FILE__
, __LINE__
);
7292 *offset
+= sizeof(*multiplier
);
7299 if(*dependency
& TNG_FRAME_DEPENDENT
)
7303 memcpy(first_frame_with_data
, contents
+*offset
,
7304 sizeof(*first_frame_with_data
));
7305 if(tng_data
->input_endianness_swap_func_64
)
7307 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7308 first_frame_with_data
)
7311 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7312 __FILE__
, __LINE__
);
7315 *offset
+= sizeof(*first_frame_with_data
);
7317 memcpy(stride_length
, contents
+*offset
,
7318 sizeof(*stride_length
));
7319 if(tng_data
->input_endianness_swap_func_64
)
7321 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7325 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7326 __FILE__
, __LINE__
);
7329 *offset
+= sizeof(*stride_length
);
7330 *n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
-
7331 (*first_frame_with_data
-
7332 tng_data
->current_trajectory_frame_set
.first_frame
);
7336 *first_frame_with_data
= 0;
7338 *n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
;
7343 *first_frame_with_data
= 0;
7348 if (*dependency
& TNG_PARTICLE_DEPENDENT
)
7350 memcpy(num_first_particle
, contents
+*offset
,
7351 sizeof(*num_first_particle
));
7352 if(tng_data
->input_endianness_swap_func_64
)
7354 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7358 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7359 __FILE__
, __LINE__
);
7362 *offset
+= sizeof(*num_first_particle
);
7364 memcpy(block_n_particles
, contents
+*offset
,
7365 sizeof(*block_n_particles
));
7366 if(tng_data
->input_endianness_swap_func_64
)
7368 if(tng_data
->input_endianness_swap_func_64(tng_data
,
7372 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
7373 __FILE__
, __LINE__
);
7376 *offset
+= sizeof(*block_n_particles
);
7379 if(!block
->block_contents
)
7383 return(TNG_SUCCESS
);
7386 /** Read the contents of a data block (particle or non-particle data).
7387 * @param tng_data is a trajectory data container.
7388 * @param block is the block to store the data (should already contain
7389 * the block headers).
7390 * @param hash_mode is an option to decide whether to use the md5 hash or not.
7391 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
7392 * compared to the md5 hash of the read contents to ensure valid data.
7393 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7394 * error has occured.
7396 static tng_function_status tng_data_block_contents_read
7397 (tng_trajectory_t tng_data
,
7398 tng_gen_block_t block
,
7399 const char hash_mode
)
7401 int64_t n_values
, codec_id
, n_frames
, first_frame_with_data
;
7402 int64_t stride_length
, block_n_particles
, num_first_particle
;
7404 char datatype
, dependency
, sparse_data
;
7408 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
7410 return(TNG_CRITICAL
);
7413 if(block
->block_contents
)
7415 free(block
->block_contents
);
7418 block
->block_contents
= malloc(block
->block_contents_size
);
7419 if(!block
->block_contents
)
7421 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
7422 block
->block_contents_size
, __FILE__
, __LINE__
);
7423 return(TNG_CRITICAL
);
7426 /* Read the whole block into block_contents to be able to write it to
7427 * disk even if it cannot be interpreted. */
7428 if(fread(block
->block_contents
, block
->block_contents_size
, 1,
7429 tng_data
->input_file
) == 0)
7431 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
7432 return(TNG_CRITICAL
);
7435 /* FIXME: Does not check if the size of the contents matches the expected
7436 * size or if the contents can be read. */
7438 if(hash_mode
== TNG_USE_HASH
)
7440 tng_md5_hash_match_verify(block
, &same_hash
);
7441 if(same_hash
!= TNG_TRUE
)
7443 fprintf(stderr
, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
7444 block
->name
, __FILE__
, __LINE__
);
7445 /* return(TNG_FAILURE); */
7449 if(tng_data_block_meta_information_read(tng_data
, block
,
7451 &dependency
, &sparse_data
,
7452 &n_values
, &codec_id
,
7453 &first_frame_with_data
,
7454 &stride_length
, &n_frames
,
7455 &num_first_particle
,
7457 &multiplier
) == TNG_CRITICAL
)
7459 fprintf(stderr
, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
7460 block
->name
, __FILE__
, __LINE__
);
7461 return(TNG_CRITICAL
);
7464 if (dependency
& TNG_PARTICLE_DEPENDENT
)
7466 return(tng_particle_data_read(tng_data
, block
,
7470 first_frame_with_data
,
7473 codec_id
, multiplier
));
7477 return(tng_data_read(tng_data
, block
,
7479 first_frame_with_data
,
7482 codec_id
, multiplier
));
7487 // ** Move the blocks in a frame set so that there is no unused space between
7488 // * them. This can only be done on the last frame set in the file and should
7489 // * be done e.g. if the last frame set in the file has fewer frames than
7490 // * default or after compressing data blocks in a frame set.
7491 // * @param tng_data is a trajectory data container.
7492 // * @details the current_trajectory_frame_set is the one that will be modified.
7493 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
7494 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
7495 // * FIXME: This function is not finished!!!
7497 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7499 // tng_gen_block_t block;
7500 // tng_trajectory_frame_set_t frame_set;
7501 // FILE *temp = tng_data->input_file;
7502 // int64_t pos, contents_start_pos, output_file_len;
7504 // frame_set = &tng_data->current_trajectory_frame_set;
7506 // if(frame_set->n_written_frames == frame_set->n_frames)
7508 // return(TNG_SUCCESS);
7511 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7512 // tng_data->last_trajectory_frame_set_output_file_pos)
7516 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7518 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7519 // __FILE__, __LINE__);
7520 // return(TNG_CRITICAL);
7523 // tng_block_init(&block);
7524 // // output_file_pos = ftell(tng_data->output_file);
7526 // tng_data->input_file = tng_data->output_file;
7528 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
7530 // fseek(tng_data->output_file, pos, SEEK_SET);
7531 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7533 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
7534 // __FILE__, __LINE__);
7535 // tng_data->input_file = temp;
7536 // tng_block_destroy(&block);
7537 // return(TNG_CRITICAL);
7540 // contents_start_pos = ftell(tng_data->output_file);
7542 // fseek(tng_data->output_file, 0, SEEK_END);
7543 // output_file_len = ftell(tng_data->output_file);
7544 // pos = contents_start_pos + block->block_contents_size;
7545 // fseek(tng_data->output_file, pos,
7548 // while(pos < output_file_len)
7550 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7552 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
7553 // __FILE__, __LINE__);
7554 // tng_data->input_file = temp;
7555 // tng_block_destroy(&block);
7556 // return(TNG_CRITICAL);
7558 // pos += block->header_contents_size + block->block_contents_size;
7559 // fseek(tng_data->output_file, pos, SEEK_SET);
7562 // return(TNG_SUCCESS);
7565 /** Finish writing the current frame set. Update the number of frames
7566 * and the hashes of the frame set and all its data blocks (if hash_mode
7568 * @param tng_data is a trajectory data container.
7569 * @param hash_mode specifies whether to update the block md5 hash when
7570 * updating the pointers.
7571 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7572 * error has occured.
7574 static tng_function_status tng_frame_set_finalize
7575 (tng_trajectory_t tng_data
, const char hash_mode
)
7577 tng_gen_block_t block
;
7578 tng_trajectory_frame_set_t frame_set
;
7579 FILE *temp
= tng_data
->input_file
;
7580 int64_t pos
, contents_start_pos
, output_file_len
;
7582 frame_set
= &tng_data
->current_trajectory_frame_set
;
7584 if(frame_set
->n_written_frames
== frame_set
->n_frames
)
7586 return(TNG_SUCCESS
);
7589 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
7591 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
7592 __FILE__
, __LINE__
);
7593 return(TNG_CRITICAL
);
7596 tng_block_init(&block
);
7597 /* output_file_pos = ftell(tng_data->output_file); */
7599 tng_data
->input_file
= tng_data
->output_file
;
7601 pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
7603 fseek(tng_data
->output_file
, (long)pos
, SEEK_SET
);
7605 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
7607 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
7608 __FILE__
, __LINE__
);
7609 tng_data
->input_file
= temp
;
7610 tng_block_destroy(&block
);
7611 return(TNG_CRITICAL
);
7614 contents_start_pos
= ftell(tng_data
->output_file
);
7616 fseek(tng_data
->output_file
, sizeof(frame_set
->first_frame
), SEEK_CUR
);
7617 if(fwrite(&frame_set
->n_written_frames
, sizeof(frame_set
->n_frames
),
7618 1, tng_data
->output_file
) != 1)
7620 tng_data
->input_file
= temp
;
7621 tng_block_destroy(&block
);
7622 return(TNG_CRITICAL
);
7626 if(hash_mode
== TNG_USE_HASH
)
7628 tng_md5_hash_update(tng_data
, block
, pos
,
7629 pos
+ block
->header_contents_size
);
7632 fseek(tng_data
->output_file
, 0, SEEK_END
);
7633 output_file_len
= ftell(tng_data
->output_file
);
7634 pos
= contents_start_pos
+ block
->block_contents_size
;
7635 fseek(tng_data
->output_file
, (long)pos
, SEEK_SET
);
7637 while(pos
< output_file_len
)
7639 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
7641 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n", pos
,
7642 __FILE__
, __LINE__
);
7643 tng_data
->input_file
= temp
;
7644 tng_block_destroy(&block
);
7645 return(TNG_CRITICAL
);
7648 if(hash_mode
== TNG_USE_HASH
)
7650 tng_md5_hash_update(tng_data
, block
, pos
,
7651 pos
+ block
->header_contents_size
);
7653 pos
+= block
->header_contents_size
+ block
->block_contents_size
;
7654 fseek(tng_data
->output_file
, (long)pos
, SEEK_SET
);
7657 tng_data
->input_file
= temp
;
7658 tng_block_destroy(&block
);
7659 return(TNG_SUCCESS
);
7663 // ** Sets the name of a file contents block
7664 // * @param tng_data is a trajectory data container.
7665 // * @param block is the block, of which to change names.
7666 // * @param new_name is the new name of the block.
7667 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
7668 // * error has occured.
7670 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
7671 // tng_gen_block_t block,
7672 // const char *new_name)
7676 // len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
7678 // * If the currently stored string length is not enough to store the new
7679 // * string it is freed and reallocated. *
7680 // if(block->name && strlen(block->name) < len)
7682 // free(block->name);
7687 // block->name = malloc(len);
7690 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7691 // __FILE__, __LINE__);
7692 // return(TNG_CRITICAL);
7696 // strncpy(block->name, new_name, len);
7698 // return(TNG_SUCCESS);
7702 tng_function_status
tng_atom_residue_get(const tng_trajectory_t tng_data
,
7703 const tng_atom_t atom
,
7704 tng_residue_t
*residue
)
7708 TNG_ASSERT(atom
, "TNG library: atom must not be NULL");
7710 *residue
= atom
->residue
;
7712 return(TNG_SUCCESS
);
7715 tng_function_status
tng_atom_name_get(const tng_trajectory_t tng_data
,
7716 const tng_atom_t atom
,
7721 TNG_ASSERT(atom
, "TNG library: atom must not be NULL");
7722 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
7724 strncpy(name
, atom
->name
, max_len
- 1);
7725 name
[max_len
- 1] = 0;
7727 if(strlen(atom
->name
) > (unsigned int)max_len
- 1)
7729 return(TNG_FAILURE
);
7731 return(TNG_SUCCESS
);
7734 tng_function_status
tng_atom_name_set(tng_trajectory_t tng_data
,
7736 const char *new_name
)
7741 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7742 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer.");
7744 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
7746 /* If the currently stored string length is not enough to store the new
7747 * string it is freed and reallocated. */
7748 if(atom
->name
&& strlen(atom
->name
) < len
)
7755 atom
->name
= malloc(len
);
7758 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
7759 __FILE__
, __LINE__
);
7760 return(TNG_CRITICAL
);
7764 strncpy(atom
->name
, new_name
, len
);
7766 return(TNG_SUCCESS
);
7769 tng_function_status
tng_atom_type_get(const tng_trajectory_t tng_data
,
7770 const tng_atom_t atom
,
7775 TNG_ASSERT(atom
, "TNG library: atom must not be NULL");
7776 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer");
7778 strncpy(type
, atom
->atom_type
, max_len
- 1);
7779 type
[max_len
- 1] = 0;
7781 if(strlen(atom
->atom_type
) > (unsigned int)max_len
- 1)
7783 return(TNG_FAILURE
);
7785 return(TNG_SUCCESS
);
7788 tng_function_status
tng_atom_type_set(tng_trajectory_t tng_data
,
7790 const char *new_type
)
7795 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7796 TNG_ASSERT(new_type
, "TNG library: new_type must not be a NULL pointer.");
7798 len
= tng_min_i((int)strlen(new_type
) + 1, TNG_MAX_STR_LEN
);
7800 /* If the currently stored string length is not enough to store the new
7801 * string it is freed and reallocated. */
7802 if(atom
->atom_type
&& strlen(atom
->atom_type
) < len
)
7804 free(atom
->atom_type
);
7805 atom
->atom_type
= 0;
7807 if(!atom
->atom_type
)
7809 atom
->atom_type
= malloc(len
);
7810 if(!atom
->atom_type
)
7812 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
7813 __FILE__
, __LINE__
);
7814 return(TNG_CRITICAL
);
7818 strncpy(atom
->atom_type
, new_type
, len
);
7820 return(TNG_SUCCESS
);
7823 /** Initialise an atom struct
7824 * @param atom is the atom to initialise.
7825 * @return TNG_SUCCESS (0) if successful.
7827 static tng_function_status
tng_atom_init(tng_atom_t atom
)
7830 atom
->atom_type
= 0;
7832 return(TNG_SUCCESS
);
7835 /** Free the memory in an atom struct
7836 * @param atom is the atom to destroy.
7837 * @return TNG_SUCCESS (0) if successful.
7839 static tng_function_status
tng_atom_destroy(tng_atom_t atom
)
7848 free(atom
->atom_type
);
7849 atom
->atom_type
= 0;
7852 return(TNG_SUCCESS
);
7855 tng_function_status DECLSPECDLLEXPORT tng_version_major
7856 (const tng_trajectory_t tng_data
,
7861 *version
= TNG_VERSION_MAJOR
;
7863 return(TNG_SUCCESS
);
7866 tng_function_status DECLSPECDLLEXPORT tng_version_minor
7867 (const tng_trajectory_t tng_data
,
7872 *version
= TNG_VERSION_MINOR
;
7874 return(TNG_SUCCESS
);
7877 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
7878 (const tng_trajectory_t tng_data
,
7883 *patch_level
= TNG_VERSION_PATCHLEVEL
;
7885 return(TNG_SUCCESS
);
7888 tng_function_status DECLSPECDLLEXPORT tng_version
7889 (const tng_trajectory_t tng_data
,
7894 TNG_ASSERT(version
, "TNG library: version must not be a NULL pointer");
7896 TNG_SNPRINTF(version
, max_len
, "%s", TNG_VERSION
);
7898 return(TNG_SUCCESS
);
7901 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
7902 (tng_trajectory_t tng_data
,
7904 tng_molecule_t
*molecule
)
7908 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7909 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7911 /* Set ID to the ID of the last molecule + 1 */
7912 if(tng_data
->n_molecules
)
7914 id
= tng_data
->molecules
[tng_data
->n_molecules
-1].id
+ 1;
7921 return(tng_molecule_w_id_add(tng_data
, name
, id
, molecule
));
7924 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
7925 (tng_trajectory_t tng_data
,
7928 tng_molecule_t
*molecule
)
7930 tng_molecule_t new_molecules
;
7931 int64_t *new_molecule_cnt_list
;
7932 tng_function_status stat
= TNG_SUCCESS
;
7934 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7935 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
7937 new_molecules
= realloc(tng_data
->molecules
,
7938 sizeof(struct tng_molecule
) *
7939 (tng_data
->n_molecules
+ 1));
7943 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
7944 sizeof(struct tng_molecule
) * (tng_data
->n_molecules
+ 1),
7945 __FILE__
, __LINE__
);
7946 free(tng_data
->molecules
);
7947 tng_data
->molecules
= 0;
7948 return(TNG_CRITICAL
);
7951 new_molecule_cnt_list
= realloc(tng_data
->molecule_cnt_list
,
7953 (tng_data
->n_molecules
+ 1));
7955 if(!new_molecule_cnt_list
)
7957 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
7958 sizeof(int64_t) * (tng_data
->n_molecules
+ 1),
7959 __FILE__
, __LINE__
);
7960 free(tng_data
->molecule_cnt_list
);
7961 tng_data
->molecule_cnt_list
= 0;
7962 free(new_molecules
);
7963 return(TNG_CRITICAL
);
7966 tng_data
->molecules
= new_molecules
;
7967 tng_data
->molecule_cnt_list
= new_molecule_cnt_list
;
7969 *molecule
= &new_molecules
[tng_data
->n_molecules
];
7971 tng_molecule_init(tng_data
, *molecule
);
7972 tng_molecule_name_set(tng_data
, *molecule
, name
);
7974 /* FIXME: Should this be a function argument instead? */
7975 tng_data
->molecule_cnt_list
[tng_data
->n_molecules
] = 0;
7977 (*molecule
)->id
= id
;
7979 tng_data
->n_molecules
++;
7984 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
7985 (tng_trajectory_t tng_data
,
7986 tng_molecule_t
*molecule_p
)
7988 int64_t *new_molecule_cnt_list
, id
;
7989 tng_molecule_t new_molecules
, molecule
;
7991 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
7993 /* Set ID to the ID of the last molecule + 1 */
7994 if(tng_data
->n_molecules
)
7996 id
= tng_data
->molecules
[tng_data
->n_molecules
-1].id
+ 1;
8003 new_molecules
= realloc(tng_data
->molecules
,
8004 sizeof(struct tng_molecule
) *
8005 (tng_data
->n_molecules
+ 1));
8009 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8010 sizeof(struct tng_molecule
) * (tng_data
->n_molecules
+ 1),
8011 __FILE__
, __LINE__
);
8012 free(tng_data
->molecules
);
8013 tng_data
->molecules
= 0;
8014 return(TNG_CRITICAL
);
8017 new_molecule_cnt_list
= realloc(tng_data
->molecule_cnt_list
,
8019 (tng_data
->n_molecules
+ 1));
8021 if(!new_molecule_cnt_list
)
8023 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8024 sizeof(int64_t) * (tng_data
->n_molecules
+ 1),
8025 __FILE__
, __LINE__
);
8026 free(tng_data
->molecule_cnt_list
);
8027 tng_data
->molecule_cnt_list
= 0;
8028 free(new_molecules
);
8029 return(TNG_CRITICAL
);
8032 molecule
= *molecule_p
;
8034 tng_data
->molecules
= new_molecules
;
8035 tng_data
->molecule_cnt_list
= new_molecule_cnt_list
;
8037 new_molecules
[tng_data
->n_molecules
] = *molecule
;
8039 tng_data
->molecule_cnt_list
[tng_data
->n_molecules
] = 0;
8043 molecule
= &new_molecules
[tng_data
->n_molecules
];
8045 *molecule_p
= molecule
;
8049 tng_data
->n_molecules
++;
8051 return(TNG_SUCCESS
);
8054 tng_function_status
tng_molecule_name_get(const tng_trajectory_t tng_data
,
8055 const tng_molecule_t molecule
,
8060 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
8061 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
8063 strncpy(name
, molecule
->name
, max_len
- 1);
8064 name
[max_len
- 1] = 0;
8066 if(strlen(molecule
->name
) > (unsigned int)max_len
- 1)
8068 return(TNG_FAILURE
);
8070 return(TNG_SUCCESS
);
8073 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
8074 (tng_trajectory_t tng_data
,
8075 tng_molecule_t molecule
,
8076 const char *new_name
)
8081 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8082 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer.");
8084 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
8086 /* If the currently stored string length is not enough to store the new
8087 * string it is freed and reallocated. */
8088 if(molecule
->name
&& strlen(molecule
->name
) < len
)
8090 free(molecule
->name
);
8095 molecule
->name
= malloc(len
);
8098 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
8099 __FILE__
, __LINE__
);
8100 return(TNG_CRITICAL
);
8104 strncpy(molecule
->name
, new_name
, len
);
8106 return(TNG_SUCCESS
);
8109 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
8110 (const tng_trajectory_t tng_data
,
8111 const tng_molecule_t molecule
,
8114 int64_t i
, index
= -1;
8116 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8117 TNG_ASSERT(cnt
, "TNG library: cnt must not be a NULL pointer.");
8119 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8121 if(&tng_data
->molecules
[i
] == molecule
)
8129 return(TNG_FAILURE
);
8131 *cnt
= tng_data
->molecule_cnt_list
[index
];
8133 return(TNG_SUCCESS
);
8136 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
8137 (tng_trajectory_t tng_data
,
8138 tng_molecule_t molecule
,
8141 int64_t i
, old_cnt
, index
= -1;
8143 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8145 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
8147 if(&tng_data
->molecules
[i
] == molecule
)
8155 fprintf(stderr
, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
8156 __FILE__
, __LINE__
);
8157 return(TNG_FAILURE
);
8159 if(tng_data
->var_num_atoms_flag
== TNG_CONSTANT_N_ATOMS
)
8161 old_cnt
= tng_data
->molecule_cnt_list
[index
];
8162 tng_data
->molecule_cnt_list
[index
] = cnt
;
8164 tng_data
->n_particles
+= (cnt
-old_cnt
) *
8165 tng_data
->molecules
[index
].n_atoms
;
8169 old_cnt
= tng_data
->current_trajectory_frame_set
.molecule_cnt_list
[index
];
8170 tng_data
->current_trajectory_frame_set
.molecule_cnt_list
[index
] = cnt
;
8172 tng_data
->current_trajectory_frame_set
.n_particles
+= (cnt
-old_cnt
) *
8173 tng_data
->molecules
[index
].n_atoms
;
8176 return(TNG_SUCCESS
);
8179 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
8180 (tng_trajectory_t tng_data
,
8183 tng_molecule_t
*molecule
)
8185 int64_t i
, n_molecules
;
8187 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8188 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8189 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
8191 n_molecules
= tng_data
->n_molecules
;
8193 for(i
= n_molecules
- 1; i
>= 0; i
--)
8195 *molecule
= &tng_data
->molecules
[i
];
8196 if(name
[0] == 0 || strcmp(name
, (*molecule
)->name
) == 0)
8198 if(nr
== -1 || nr
== (*molecule
)->id
)
8200 return(TNG_SUCCESS
);
8207 return(TNG_FAILURE
);
8210 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8211 (tng_trajectory_t tng_data
,
8213 tng_molecule_t
*molecule
)
8215 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8216 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
8218 if(index
>= tng_data
->n_molecules
)
8221 return(TNG_FAILURE
);
8223 *molecule
= &tng_data
->molecules
[index
];
8224 return(TNG_SUCCESS
);
8227 tng_function_status DECLSPECDLLEXPORT
tng_molecule_system_copy(tng_trajectory_t tng_data_src
,
8228 tng_trajectory_t tng_data_dest
)
8230 tng_molecule_t molecule
, molecule_temp
;
8231 tng_chain_t chain
, chain_temp
;
8232 tng_residue_t residue
, residue_temp
;
8233 tng_atom_t atom
, atom_temp
;
8234 tng_bond_t bond_temp
;
8235 tng_function_status stat
;
8236 int64_t i
, j
, k
, l
, *list_temp
;
8238 TNG_ASSERT(tng_data_src
, "TNG library: Trajectory container not properly setup.");
8239 TNG_ASSERT(tng_data_dest
, "TNG library: Trajectory container not properly setup.");
8241 for(i
= 0; i
< tng_data_dest
->n_molecules
; i
++)
8243 molecule
= &tng_data_dest
->molecules
[i
];
8244 tng_molecule_destroy(tng_data_dest
, molecule
);
8247 tng_data_dest
->n_molecules
= 0;
8248 tng_data_dest
->n_particles
= 0;
8250 molecule_temp
= realloc(tng_data_dest
->molecules
,
8251 sizeof(struct tng_molecule
) * tng_data_src
->n_molecules
);
8254 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8255 sizeof(struct tng_molecule
) * tng_data_src
->n_molecules
,
8256 __FILE__
, __LINE__
);
8257 free(tng_data_dest
->molecules
);
8258 tng_data_dest
->molecules
= 0;
8259 return(TNG_CRITICAL
);
8261 list_temp
= realloc(tng_data_dest
->molecule_cnt_list
,
8262 sizeof(int64_t) * tng_data_src
->n_molecules
);
8265 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8266 sizeof(int64_t) * tng_data_src
->n_molecules
,
8267 __FILE__
, __LINE__
);
8268 free(tng_data_dest
->molecule_cnt_list
);
8269 tng_data_dest
->molecule_cnt_list
= 0;
8270 free(molecule_temp
);
8271 return(TNG_CRITICAL
);
8274 tng_data_dest
->molecules
= molecule_temp
;
8275 tng_data_dest
->molecule_cnt_list
= list_temp
;
8277 for(i
= 0; i
< tng_data_src
->n_molecules
; i
++)
8279 molecule
= &tng_data_src
->molecules
[i
];
8280 stat
= tng_molecule_w_id_add(tng_data_dest
, molecule
->name
, molecule
->id
,
8282 if(stat
!= TNG_SUCCESS
)
8284 fprintf(stderr
, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8285 __FILE__
, __LINE__
);
8288 molecule_temp
->quaternary_str
= molecule
->quaternary_str
;
8289 for(j
= 0; j
< molecule
->n_chains
; j
++)
8291 chain
= &molecule
->chains
[j
];
8292 stat
= tng_molecule_chain_w_id_add(tng_data_dest
, molecule_temp
,
8293 chain
->name
, chain
->id
,
8295 if(stat
!= TNG_SUCCESS
)
8297 fprintf(stderr
, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8298 __FILE__
, __LINE__
);
8301 for(k
= 0; k
< chain
->n_residues
; k
++)
8303 residue
= &chain
->residues
[k
];
8304 stat
= tng_chain_residue_w_id_add(tng_data_dest
, chain_temp
,
8305 residue
->name
, residue
->id
,
8307 if(stat
!= TNG_SUCCESS
)
8309 fprintf(stderr
, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8310 __FILE__
, __LINE__
);
8313 for(l
= 0; l
< residue
->n_atoms
; l
++)
8315 atom
= &molecule
->atoms
[residue
->atoms_offset
+ l
];
8316 stat
= tng_residue_atom_w_id_add(tng_data_dest
, residue_temp
,
8317 atom
->name
, atom
->atom_type
,
8318 atom
->id
, &atom_temp
);
8319 if(stat
!= TNG_SUCCESS
)
8321 fprintf(stderr
, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
8322 __FILE__
, __LINE__
);
8328 molecule_temp
->n_bonds
= molecule
->n_bonds
;
8329 bond_temp
= realloc(molecule_temp
->bonds
, sizeof(struct tng_bond
) *
8333 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8334 sizeof(struct tng_bond
) * molecule
->n_bonds
,
8335 __FILE__
, __LINE__
);
8336 free(molecule_temp
->bonds
);
8337 molecule_temp
->n_bonds
= 0;
8338 return(TNG_CRITICAL
);
8340 molecule_temp
->bonds
= bond_temp
;
8341 for(j
= 0; j
< molecule
->n_bonds
; j
++)
8343 molecule_temp
->bonds
[j
] = molecule
->bonds
[j
];
8345 stat
= tng_molecule_cnt_set(tng_data_dest
, molecule_temp
,
8346 tng_data_src
->molecule_cnt_list
[i
]);
8347 if(stat
!= TNG_SUCCESS
)
8349 fprintf(stderr
, "TNG library: Cannot set molecule count. %s: %d.\n",
8350 __FILE__
, __LINE__
);
8354 return(TNG_SUCCESS
);
8357 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
8358 (const tng_trajectory_t tng_data
,
8359 const tng_molecule_t molecule
,
8363 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
8364 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
8366 *n
= molecule
->n_chains
;
8368 return(TNG_SUCCESS
);
8371 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
8372 (tng_trajectory_t tng_data
,
8373 tng_molecule_t molecule
,
8378 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
8379 TNG_ASSERT(chain
, "TNG library: chain must not be a NULL pointer.");
8381 if(index
>= molecule
->n_chains
)
8384 return(TNG_FAILURE
);
8386 *chain
= &molecule
->chains
[index
];
8387 return(TNG_SUCCESS
);
8390 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
8391 (const tng_trajectory_t tng_data
,
8392 const tng_molecule_t molecule
,
8396 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
8397 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
8399 *n
= molecule
->n_residues
;
8401 return(TNG_SUCCESS
);
8404 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
8405 (const tng_trajectory_t tng_data
,
8406 const tng_molecule_t molecule
,
8407 const int64_t index
,
8408 tng_residue_t
*residue
)
8411 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
8412 TNG_ASSERT(residue
, "TNG library: residue must not be a NULL pointer.");
8414 if(index
>= molecule
->n_residues
)
8417 return(TNG_FAILURE
);
8419 *residue
= &molecule
->residues
[index
];
8420 return(TNG_SUCCESS
);
8423 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
8424 (const tng_trajectory_t tng_data
,
8425 const tng_molecule_t molecule
,
8429 TNG_ASSERT(molecule
, "TNG library: molecule must not be NULL");
8430 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
8432 *n
= molecule
->n_atoms
;
8434 return(TNG_SUCCESS
);
8437 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
8438 (const tng_trajectory_t tng_data
,
8439 const tng_molecule_t molecule
,
8440 const int64_t index
,
8444 TNG_ASSERT(molecule
, "TNG library: molecule must not be a NULL pointer.");
8445 TNG_ASSERT(atom
, "TNG library: atom must not be a NULL pointer.");
8447 if(index
>= molecule
->n_atoms
)
8450 return(TNG_FAILURE
);
8452 *atom
= &molecule
->atoms
[index
];
8453 return(TNG_SUCCESS
);
8456 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
8457 (tng_trajectory_t tng_data
,
8458 tng_molecule_t molecule
,
8463 int64_t i
, n_chains
;
8466 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8467 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8469 n_chains
= molecule
->n_chains
;
8471 for(i
= n_chains
- 1; i
>= 0; i
--)
8473 *chain
= &molecule
->chains
[i
];
8474 if(name
[0] == 0 || strcmp(name
, (*chain
)->name
) == 0)
8476 if(nr
== -1 || nr
== (*chain
)->id
)
8478 return(TNG_SUCCESS
);
8485 return(TNG_FAILURE
);
8488 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8489 (tng_trajectory_t tng_data
,
8490 tng_molecule_t molecule
,
8496 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8497 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8499 /* Set ID to the ID of the last chain + 1 */
8500 if(molecule
->n_chains
)
8502 id
= molecule
->chains
[molecule
->n_chains
-1].id
+ 1;
8509 return(tng_molecule_chain_w_id_add(tng_data
, molecule
, name
,
8513 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8514 (tng_trajectory_t tng_data
,
8515 tng_molecule_t molecule
,
8520 tng_chain_t new_chains
;
8521 tng_function_status stat
= TNG_SUCCESS
;
8523 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8524 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8526 new_chains
= realloc(molecule
->chains
,
8527 sizeof(struct tng_chain
) *
8528 (molecule
->n_chains
+ 1));
8532 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8533 sizeof(struct tng_chain
) * (molecule
->n_chains
+ 1),
8534 __FILE__
, __LINE__
);
8535 free(molecule
->chains
);
8536 molecule
->chains
= 0;
8537 return(TNG_CRITICAL
);
8540 molecule
->chains
= new_chains
;
8542 *chain
= &new_chains
[molecule
->n_chains
];
8545 tng_chain_name_set(tng_data
, *chain
, name
);
8547 (*chain
)->molecule
= molecule
;
8548 (*chain
)->n_residues
= 0;
8550 molecule
->n_chains
++;
8557 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
8558 (const tng_trajectory_t tng_data
,
8559 tng_molecule_t molecule
,
8560 const int64_t from_atom_id
,
8561 const int64_t to_atom_id
,
8564 tng_bond_t new_bonds
;
8567 new_bonds
= realloc(molecule
->bonds
,
8568 sizeof(struct tng_bond
) *
8569 (molecule
->n_bonds
+ 1));
8573 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8574 sizeof(struct tng_bond
) * (molecule
->n_bonds
+ 1),
8575 __FILE__
, __LINE__
);
8577 free(molecule
->bonds
);
8578 molecule
->bonds
= 0;
8579 return(TNG_CRITICAL
);
8582 molecule
->bonds
= new_bonds
;
8584 *bond
= &new_bonds
[molecule
->n_bonds
];
8586 (*bond
)->from_atom_id
= from_atom_id
;
8587 (*bond
)->to_atom_id
= to_atom_id
;
8589 molecule
->n_bonds
++;
8591 return(TNG_SUCCESS
);
8594 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
8595 (tng_trajectory_t tng_data
,
8596 tng_molecule_t molecule
,
8604 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8606 n_atoms
= molecule
->n_atoms
;
8608 for(i
= n_atoms
- 1; i
>= 0; i
--)
8610 *atom
= &molecule
->atoms
[i
];
8611 if(name
[0] == 0 || strcmp(name
, (*atom
)->name
) == 0)
8613 if(id
== -1 || id
== (*atom
)->id
)
8615 return(TNG_SUCCESS
);
8622 return(TNG_FAILURE
);
8625 tng_function_status
tng_chain_name_get(const tng_trajectory_t tng_data
,
8626 const tng_chain_t chain
,
8631 TNG_ASSERT(chain
, "TNG library: chain must not be NULL");
8632 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
8634 strncpy(name
, chain
->name
, max_len
- 1);
8635 name
[max_len
- 1] = 0;
8637 if(strlen(chain
->name
) > (unsigned int)max_len
- 1)
8639 return(TNG_FAILURE
);
8641 return(TNG_SUCCESS
);
8644 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
8645 (tng_trajectory_t tng_data
,
8647 const char *new_name
)
8652 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer.");
8654 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
8656 /* If the currently stored string length is not enough to store the new
8657 * string it is freed and reallocated. */
8658 if(chain
->name
&& strlen(chain
->name
) < len
)
8665 chain
->name
= malloc(len
);
8668 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
8669 __FILE__
, __LINE__
);
8670 return(TNG_CRITICAL
);
8674 strncpy(chain
->name
, new_name
, len
);
8676 return(TNG_SUCCESS
);
8679 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
8680 (const tng_trajectory_t tng_data
,
8681 const tng_chain_t chain
,
8685 TNG_ASSERT(chain
, "TNG library: chain must not be NULL");
8686 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
8688 *n
= chain
->n_residues
;
8690 return(TNG_SUCCESS
);
8693 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
8694 (const tng_trajectory_t tng_data
,
8695 const tng_chain_t chain
,
8696 const int64_t index
,
8697 tng_residue_t
*residue
)
8700 TNG_ASSERT(chain
, "TNG library: chain must not be a NULL pointer.");
8701 TNG_ASSERT(residue
, "TNG library: residue must not be a NULL pointer.");
8703 if(index
>= chain
->n_residues
)
8706 return(TNG_FAILURE
);
8708 *residue
= &chain
->residues
[index
];
8709 return(TNG_SUCCESS
);
8712 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
8713 (tng_trajectory_t tng_data
,
8717 tng_residue_t
*residue
)
8719 int64_t i
, n_residues
;
8722 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8724 n_residues
= chain
->n_residues
;
8726 for(i
= n_residues
- 1; i
>= 0; i
--)
8728 *residue
= &chain
->residues
[i
];
8729 if(name
[0] == 0 || strcmp(name
, (*residue
)->name
) == 0)
8731 if(id
== -1 || id
== (*residue
)->id
)
8733 return(TNG_SUCCESS
);
8740 return(TNG_FAILURE
);
8743 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8744 (tng_trajectory_t tng_data
,
8747 tng_residue_t
*residue
)
8751 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8752 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8754 /* Set ID to the ID of the last residue + 1 */
8755 if(chain
->n_residues
)
8757 id
= chain
->residues
[chain
->n_residues
-1].id
+ 1;
8764 return(tng_chain_residue_w_id_add(tng_data
, chain
, name
,
8768 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8769 (tng_trajectory_t tng_data
,
8773 tng_residue_t
*residue
)
8776 tng_residue_t new_residues
, temp_residue
, last_residue
;
8777 tng_molecule_t molecule
= chain
->molecule
;
8778 tng_function_status stat
= TNG_SUCCESS
;
8780 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8781 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
8783 if(chain
->n_residues
)
8785 curr_index
= chain
->residues
- molecule
->residues
;
8792 new_residues
= realloc(molecule
->residues
,
8793 sizeof(struct tng_residue
) *
8794 (molecule
->n_residues
+ 1));
8798 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
8799 sizeof(struct tng_residue
) * (molecule
->n_residues
+ 1),
8800 __FILE__
, __LINE__
);
8801 free(molecule
->residues
);
8802 molecule
->residues
= 0;
8803 return(TNG_CRITICAL
);
8806 molecule
->residues
= new_residues
;
8808 if(curr_index
!= -1)
8810 chain
->residues
= new_residues
+ curr_index
;
8811 if(molecule
->n_residues
)
8813 last_residue
= &new_residues
[molecule
->n_residues
- 1];
8815 temp_residue
= chain
->residues
+ (chain
->n_residues
- 1);
8816 /* Make space in list of residues to add the new residues together with the other
8817 * residues of this chain */
8818 if(temp_residue
!= last_residue
)
8821 memmove(temp_residue
+ 1, temp_residue
,
8822 last_residue
- temp_residue
);
8828 curr_index
= molecule
->n_residues
;
8831 *residue
= &molecule
->residues
[curr_index
+ chain
->n_residues
];
8833 if(!chain
->n_residues
)
8835 chain
->residues
= *residue
;
8839 chain
->residues
= &molecule
->residues
[curr_index
];
8842 (*residue
)->name
= 0;
8843 tng_residue_name_set(tng_data
, *residue
, name
);
8845 (*residue
)->chain
= chain
;
8846 (*residue
)->n_atoms
= 0;
8847 (*residue
)->atoms_offset
= 0;
8849 chain
->n_residues
++;
8850 molecule
->n_residues
++;
8852 (*residue
)->id
= id
;
8857 tng_function_status
tng_residue_name_get(const tng_trajectory_t tng_data
,
8858 const tng_residue_t residue
,
8863 TNG_ASSERT(residue
, "TNG library: residue must not be NULL");
8864 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
8866 strncpy(name
, residue
->name
, max_len
- 1);
8867 name
[max_len
- 1] = 0;
8869 if(strlen(residue
->name
) > (unsigned int)max_len
- 1)
8871 return(TNG_FAILURE
);
8873 return(TNG_SUCCESS
);
8876 tng_function_status DECLSPECDLLEXPORT
tng_residue_name_set(tng_trajectory_t tng_data
,
8877 tng_residue_t residue
,
8878 const char *new_name
)
8883 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8884 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
8886 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
8888 /* If the currently stored string length is not enough to store the new
8889 * string it is freed and reallocated. */
8890 if(residue
->name
&& strlen(residue
->name
) < len
)
8892 free(residue
->name
);
8897 residue
->name
= malloc(len
);
8900 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
8901 __FILE__
, __LINE__
);
8902 return(TNG_CRITICAL
);
8906 strncpy(residue
->name
, new_name
, len
);
8908 return(TNG_SUCCESS
);
8911 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
8912 (const tng_trajectory_t tng_data
,
8913 const tng_residue_t residue
,
8917 TNG_ASSERT(residue
, "TNG library: residue must not be NULL");
8918 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
8920 *n
= residue
->n_atoms
;
8922 return(TNG_SUCCESS
);
8925 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
8926 (const tng_trajectory_t tng_data
,
8927 const tng_residue_t residue
,
8928 const int64_t index
,
8932 tng_molecule_t molecule
;
8935 TNG_ASSERT(residue
, "TNG library: residue must not be a NULL pointer.");
8936 TNG_ASSERT(atom
, "TNG library: atom must not be a NULL pointer.");
8938 if(index
>= residue
->n_atoms
)
8941 return(TNG_FAILURE
);
8943 chain
= residue
->chain
;
8944 molecule
= chain
->molecule
;
8946 if(index
+ residue
->atoms_offset
>= molecule
->n_atoms
)
8949 return(TNG_FAILURE
);
8952 *atom
= &molecule
->atoms
[residue
->atoms_offset
+ index
];
8953 return(TNG_SUCCESS
);
8956 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
8957 (tng_trajectory_t tng_data
,
8958 tng_residue_t residue
,
8959 const char *atom_name
,
8960 const char *atom_type
,
8965 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8966 TNG_ASSERT(atom_name
, "TNG library: atom_name must not be a NULL pointer.");
8967 TNG_ASSERT(atom_type
, "TNG library: atom_type must not be a NULL pointer.");
8969 /* Set ID to the ID of the last atom + 1 */
8970 if(residue
->chain
->molecule
->n_atoms
)
8972 id
= residue
->chain
->molecule
->atoms
[residue
->chain
->molecule
->n_atoms
-1].id
+ 1;
8979 return(tng_residue_atom_w_id_add(tng_data
, residue
, atom_name
, atom_type
,
8983 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
8984 (tng_trajectory_t tng_data
,
8985 tng_residue_t residue
,
8986 const char *atom_name
,
8987 const char *atom_type
,
8991 tng_atom_t new_atoms
;
8992 tng_molecule_t molecule
= residue
->chain
->molecule
;
8993 tng_function_status stat
= TNG_SUCCESS
;
8995 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
8996 TNG_ASSERT(atom_name
, "TNG library: atom_name must not be a NULL pointer.");
8997 TNG_ASSERT(atom_type
, "TNG library: atom_type must not be a NULL pointer.");
8999 if(!residue
->n_atoms
)
9001 residue
->atoms_offset
= molecule
->n_atoms
;
9004 new_atoms
= realloc(molecule
->atoms
,
9005 sizeof(struct tng_atom
) *
9006 (molecule
->n_atoms
+ 1));
9010 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
9011 sizeof(struct tng_atom
) * (molecule
->n_atoms
+ 1),
9012 __FILE__
, __LINE__
);
9013 free(molecule
->atoms
);
9014 molecule
->atoms
= 0;
9015 return(TNG_CRITICAL
);
9018 molecule
->atoms
= new_atoms
;
9020 *atom
= &new_atoms
[molecule
->n_atoms
];
9022 tng_atom_init(*atom
);
9023 tng_atom_name_set(tng_data
, *atom
, atom_name
);
9024 tng_atom_type_set(tng_data
, *atom
, atom_type
);
9026 (*atom
)->residue
= residue
;
9029 molecule
->n_atoms
++;
9036 tng_function_status DECLSPECDLLEXPORT
tng_molecule_alloc(const tng_trajectory_t tng_data
,
9037 tng_molecule_t
*molecule_p
)
9039 *molecule_p
= malloc(sizeof(struct tng_molecule
));
9042 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9043 sizeof(struct tng_molecule
), __FILE__
, __LINE__
);
9044 return(TNG_CRITICAL
);
9047 tng_molecule_init(tng_data
, *molecule_p
);
9049 return(TNG_SUCCESS
);
9052 tng_function_status DECLSPECDLLEXPORT
tng_molecule_free(const tng_trajectory_t tng_data
,
9053 tng_molecule_t
*molecule_p
)
9057 return(TNG_SUCCESS
);
9060 tng_molecule_destroy(tng_data
, *molecule_p
);
9065 return(TNG_SUCCESS
);
9068 tng_function_status DECLSPECDLLEXPORT
tng_molecule_init(const tng_trajectory_t tng_data
,
9069 tng_molecule_t molecule
)
9072 molecule
->quaternary_str
= 1;
9074 molecule
->n_chains
= 0;
9075 molecule
->chains
= 0;
9076 molecule
->n_residues
= 0;
9077 molecule
->residues
= 0;
9078 molecule
->n_atoms
= 0;
9079 molecule
->atoms
= 0;
9080 molecule
->n_bonds
= 0;
9081 molecule
->bonds
= 0;
9083 return(TNG_SUCCESS
);
9086 tng_function_status DECLSPECDLLEXPORT
tng_molecule_destroy(const tng_trajectory_t tng_data
,
9087 tng_molecule_t molecule
)
9094 free(molecule
->name
);
9098 if(molecule
->chains
)
9100 for(i
= 0; i
< molecule
->n_chains
; i
++)
9102 if(molecule
->chains
[i
].name
)
9104 free(molecule
->chains
[i
].name
);
9105 molecule
->chains
[i
].name
= 0;
9108 free(molecule
->chains
);
9109 molecule
->chains
= 0;
9111 molecule
->n_chains
= 0;
9113 if(molecule
->residues
)
9115 for(i
= 0; i
< molecule
->n_residues
; i
++)
9117 if(molecule
->residues
[i
].name
)
9119 free(molecule
->residues
[i
].name
);
9120 molecule
->residues
[i
].name
= 0;
9123 free(molecule
->residues
);
9124 molecule
->residues
= 0;
9126 molecule
->n_residues
= 0;
9130 for(i
= 0; i
< molecule
->n_atoms
; i
++)
9132 tng_atom_destroy(&molecule
->atoms
[i
]);
9134 free(molecule
->atoms
);
9135 molecule
->atoms
= 0;
9137 molecule
->n_atoms
= 0;
9141 free(molecule
->bonds
);
9142 molecule
->bonds
= 0;
9144 molecule
->n_bonds
= 0;
9146 return(TNG_SUCCESS
);
9149 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
9150 (const tng_trajectory_t tng_data
,
9155 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9157 tng_bool found
= TNG_FALSE
;
9159 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9160 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
9162 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9164 if(!molecule_cnt_list
)
9166 return(TNG_FAILURE
);
9169 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9171 mol
= &tng_data
->molecules
[i
];
9172 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9174 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9182 return(TNG_FAILURE
);
9185 strncpy(name
, mol
->name
, max_len
- 1);
9186 name
[max_len
- 1] = 0;
9188 if(strlen(mol
->name
) > (unsigned int)max_len
- 1)
9190 return(TNG_FAILURE
);
9192 return(TNG_SUCCESS
);
9195 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
9196 (const tng_trajectory_t tng_data
,
9200 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9202 tng_bool found
= TNG_FALSE
;
9204 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9205 TNG_ASSERT(id
, "TNG library: id must not be a NULL pointer.");
9207 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9209 if(!molecule_cnt_list
)
9211 return(TNG_FAILURE
);
9214 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9216 mol
= &tng_data
->molecules
[i
];
9217 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9219 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9227 return(TNG_FAILURE
);
9232 return(TNG_SUCCESS
);
9235 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9236 (const tng_trajectory_t tng_data
,
9238 int64_t **from_atoms
,
9241 int64_t atom_cnt
= 0, cnt
, mol_cnt
, i
, j
, k
;
9242 int64_t from_atom
, to_atom
, *molecule_cnt_list
= 0;
9246 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9247 TNG_ASSERT(n_bonds
, "TNG library: n_bonds must not be a NULL pointer.");
9248 TNG_ASSERT(from_atoms
, "TNG library: from_atoms must not be a NULL pointer.");
9249 TNG_ASSERT(to_atoms
, "TNG library: to_atoms must not be a NULL pointer.");
9251 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9253 if(!molecule_cnt_list
)
9255 return(TNG_FAILURE
);
9259 /* First count the total number of bonds to allocate memory */
9260 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9262 mol
= &tng_data
->molecules
[i
];
9263 mol_cnt
= molecule_cnt_list
[i
];
9264 *n_bonds
+= mol_cnt
* mol
->n_bonds
;
9268 return(TNG_SUCCESS
);
9271 *from_atoms
= malloc(sizeof(int64_t) * (*n_bonds
));
9274 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
9275 sizeof(int64_t) * (*n_bonds
), __FILE__
, __LINE__
);
9276 return(TNG_CRITICAL
);
9278 *to_atoms
= malloc(sizeof(int64_t) * (*n_bonds
));
9281 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
9282 sizeof(int64_t) * (*n_bonds
), __FILE__
, __LINE__
);
9285 return(TNG_CRITICAL
);
9289 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9291 mol
= &tng_data
->molecules
[i
];
9292 mol_cnt
= molecule_cnt_list
[i
];
9293 for(j
= 0; j
< mol_cnt
; j
++)
9295 for(k
= 0; k
< mol
->n_bonds
; k
++)
9297 bond
= &mol
->bonds
[k
];
9298 from_atom
= atom_cnt
+ bond
->from_atom_id
;
9299 to_atom
= atom_cnt
+ bond
->to_atom_id
;
9300 (*from_atoms
)[cnt
] = from_atom
;
9301 (*to_atoms
)[cnt
++] = to_atom
;
9303 atom_cnt
+= mol
->n_atoms
;
9307 return(TNG_SUCCESS
);
9310 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
9311 (const tng_trajectory_t tng_data
,
9316 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9319 tng_bool found
= TNG_FALSE
;
9321 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9322 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
9324 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9326 if(!molecule_cnt_list
)
9328 return(TNG_FAILURE
);
9331 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9333 mol
= &tng_data
->molecules
[i
];
9334 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9336 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9339 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
9345 return(TNG_FAILURE
);
9347 if(!atom
->residue
|| !atom
->residue
->chain
)
9349 return(TNG_FAILURE
);
9352 strncpy(name
, atom
->residue
->chain
->name
, max_len
- 1);
9353 name
[max_len
- 1] = 0;
9355 if(strlen(atom
->residue
->chain
->name
) > (unsigned int)max_len
- 1)
9357 return(TNG_FAILURE
);
9359 return(TNG_SUCCESS
);
9362 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
9363 (const tng_trajectory_t tng_data
,
9368 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9371 tng_bool found
= TNG_FALSE
;
9373 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9374 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
9376 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9378 if(!molecule_cnt_list
)
9380 return(TNG_FAILURE
);
9383 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9385 mol
= &tng_data
->molecules
[i
];
9386 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9388 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9391 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
9397 return(TNG_FAILURE
);
9401 return(TNG_FAILURE
);
9404 strncpy(name
, atom
->residue
->name
, max_len
- 1);
9405 name
[max_len
- 1] = 0;
9407 if(strlen(atom
->residue
->name
) > (unsigned int)max_len
- 1)
9409 return(TNG_FAILURE
);
9411 return(TNG_SUCCESS
);
9414 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
9415 (const tng_trajectory_t tng_data
,
9419 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9422 tng_bool found
= TNG_FALSE
;
9424 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9425 TNG_ASSERT(id
, "TNG library: id must not be a NULL pointer.");
9427 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9429 if(!molecule_cnt_list
)
9431 return(TNG_FAILURE
);
9434 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9436 mol
= &tng_data
->molecules
[i
];
9437 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9439 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9442 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
9448 return(TNG_FAILURE
);
9452 return(TNG_FAILURE
);
9455 *id
= atom
->residue
->id
;
9457 return(TNG_SUCCESS
);
9460 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
9461 (const tng_trajectory_t tng_data
,
9465 int64_t cnt
= 0, i
, offset
= 0, *molecule_cnt_list
= 0;
9468 tng_bool found
= TNG_FALSE
;
9470 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9471 TNG_ASSERT(id
, "TNG library: id must not be a NULL pointer.");
9473 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9475 if(!molecule_cnt_list
)
9477 return(TNG_FAILURE
);
9480 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9482 mol
= &tng_data
->molecules
[i
];
9483 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9485 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9486 offset
+= mol
->n_residues
* molecule_cnt_list
[i
];
9489 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
9495 return(TNG_FAILURE
);
9499 return(TNG_FAILURE
);
9502 offset
+= mol
->n_residues
* ((nr
- cnt
) / mol
->n_atoms
);
9504 *id
= atom
->residue
->id
+ offset
;
9506 return(TNG_SUCCESS
);
9509 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
9510 (const tng_trajectory_t tng_data
,
9515 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9518 tng_bool found
= TNG_FALSE
;
9520 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9521 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
9523 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9525 if(!molecule_cnt_list
)
9527 return(TNG_FAILURE
);
9530 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9532 mol
= &tng_data
->molecules
[i
];
9533 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9535 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9538 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
9544 return(TNG_FAILURE
);
9547 strncpy(name
, atom
->name
, max_len
- 1);
9548 name
[max_len
- 1] = 0;
9550 if(strlen(atom
->name
) > (unsigned int)max_len
- 1)
9552 return(TNG_FAILURE
);
9554 return(TNG_SUCCESS
);
9557 tng_function_status tng_atom_type_of_particle_nr_get
9558 (const tng_trajectory_t tng_data
,
9563 int64_t cnt
= 0, i
, *molecule_cnt_list
= 0;
9566 tng_bool found
= TNG_FALSE
;
9568 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9569 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
9571 tng_molecule_cnt_list_get(tng_data
, &molecule_cnt_list
);
9573 if(!molecule_cnt_list
)
9575 return(TNG_FAILURE
);
9578 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
9580 mol
= &tng_data
->molecules
[i
];
9581 if(cnt
+ mol
->n_atoms
* molecule_cnt_list
[i
] - 1 < nr
)
9583 cnt
+= mol
->n_atoms
* molecule_cnt_list
[i
];
9586 atom
= &mol
->atoms
[nr
% mol
->n_atoms
];
9592 return(TNG_FAILURE
);
9595 strncpy(type
, atom
->atom_type
, max_len
- 1);
9596 type
[max_len
- 1] = 0;
9598 if(strlen(atom
->atom_type
) > (unsigned int)max_len
- 1)
9600 return(TNG_FAILURE
);
9602 return(TNG_SUCCESS
);
9605 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
9606 (tng_trajectory_t tng_data
,
9607 const int64_t num_first_particle
,
9608 const int64_t n_particles
,
9609 const int64_t *mapping_table
)
9612 tng_particle_mapping_t mapping
;
9613 tng_trajectory_frame_set_t frame_set
;
9615 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9617 frame_set
= &tng_data
->current_trajectory_frame_set
;
9619 /* Sanity check of the particle ranges. Split into multiple if
9620 * statements for improved readability */
9621 for(i
= 0; i
< frame_set
->n_mapping_blocks
; i
++)
9623 mapping
= &frame_set
->mappings
[i
];
9624 if(num_first_particle
>= mapping
->num_first_particle
&&
9625 num_first_particle
< mapping
->num_first_particle
+
9626 mapping
->n_particles
)
9628 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
9629 return(TNG_FAILURE
);
9631 if(num_first_particle
+ n_particles
>=
9632 mapping
->num_first_particle
&&
9633 num_first_particle
+ n_particles
<
9634 mapping
->num_first_particle
+ mapping
->n_particles
)
9636 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
9637 return(TNG_FAILURE
);
9639 if(mapping
->num_first_particle
>= num_first_particle
&&
9640 mapping
->num_first_particle
< num_first_particle
+
9643 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
9644 return(TNG_FAILURE
);
9646 if(mapping
->num_first_particle
+ mapping
->n_particles
>
9647 num_first_particle
&&
9648 mapping
->num_first_particle
+ mapping
->n_particles
<
9649 num_first_particle
+ n_particles
)
9651 fprintf(stderr
, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__
, __LINE__
);
9652 return(TNG_FAILURE
);
9656 frame_set
->n_mapping_blocks
++;
9658 mapping
= realloc(frame_set
->mappings
, sizeof(struct tng_particle_mapping
) *
9659 frame_set
->n_mapping_blocks
);
9663 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
9664 sizeof(struct tng_particle_mapping
)*frame_set
->n_mapping_blocks
,
9665 __FILE__
, __LINE__
);
9666 free(frame_set
->mappings
);
9667 frame_set
->mappings
= 0;
9668 return(TNG_CRITICAL
);
9670 frame_set
->mappings
= mapping
;
9672 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].num_first_particle
= num_first_particle
;
9673 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].n_particles
= n_particles
;
9675 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].real_particle_numbers
= malloc(sizeof(int64_t) * n_particles
);
9676 if(!frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].real_particle_numbers
)
9678 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
9679 sizeof(int64_t) * n_particles
, __FILE__
, __LINE__
);
9680 return(TNG_CRITICAL
);
9683 for(i
=0; i
<n_particles
; i
++)
9685 frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1].real_particle_numbers
[i
] = mapping_table
[i
];
9688 return(TNG_SUCCESS
);
9691 tng_function_status DECLSPECDLLEXPORT
tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data
)
9693 tng_trajectory_frame_set_t frame_set
;
9694 tng_particle_mapping_t mapping
;
9697 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
9699 frame_set
= &tng_data
->current_trajectory_frame_set
;
9701 if(frame_set
->n_mapping_blocks
&& frame_set
->mappings
)
9703 for(i
= 0; i
< frame_set
->n_mapping_blocks
; i
++)
9705 mapping
= &frame_set
->mappings
[i
];
9706 if(mapping
->real_particle_numbers
)
9708 free(mapping
->real_particle_numbers
);
9709 mapping
->real_particle_numbers
= 0;
9712 free(frame_set
->mappings
);
9713 frame_set
->mappings
= 0;
9714 frame_set
->n_mapping_blocks
= 0;
9717 return(TNG_SUCCESS
);
9720 tng_function_status DECLSPECDLLEXPORT
tng_trajectory_init(tng_trajectory_t
*tng_data_p
)
9723 tng_trajectory_frame_set_t frame_set
;
9724 tng_trajectory_t tng_data
;
9726 *tng_data_p
= malloc(sizeof(struct tng_trajectory
));
9729 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9730 sizeof(struct tng_trajectory
), __FILE__
, __LINE__
);
9731 return(TNG_CRITICAL
);
9734 tng_data
= *tng_data_p
;
9736 frame_set
= &tng_data
->current_trajectory_frame_set
;
9738 tng_data
->input_file_path
= 0;
9739 tng_data
->input_file
= 0;
9740 tng_data
->input_file_len
= 0;
9741 tng_data
->output_file_path
= 0;
9742 tng_data
->output_file
= 0;
9744 tng_data
->first_program_name
= 0;
9745 tng_data
->first_user_name
= 0;
9746 tng_data
->first_computer_name
= 0;
9747 tng_data
->first_pgp_signature
= 0;
9748 tng_data
->last_program_name
= 0;
9749 tng_data
->last_user_name
= 0;
9750 tng_data
->last_computer_name
= 0;
9751 tng_data
->last_pgp_signature
= 0;
9752 tng_data
->forcefield_name
= 0;
9757 fprintf(stderr
, "TNG library: Cannot get time. %s: %d\n", __FILE__
, __LINE__
);
9761 tng_data
->time
= seconds
;
9764 tng_data
->var_num_atoms_flag
= TNG_CONSTANT_N_ATOMS
;
9765 tng_data
->first_trajectory_frame_set_input_file_pos
= -1;
9766 tng_data
->last_trajectory_frame_set_input_file_pos
= -1;
9767 tng_data
->current_trajectory_frame_set_input_file_pos
= -1;
9768 tng_data
->first_trajectory_frame_set_output_file_pos
= -1;
9769 tng_data
->last_trajectory_frame_set_output_file_pos
= -1;
9770 tng_data
->current_trajectory_frame_set_output_file_pos
= -1;
9771 tng_data
->frame_set_n_frames
= 100;
9772 tng_data
->n_trajectory_frame_sets
= 0;
9773 tng_data
->medium_stride_length
= 100;
9774 tng_data
->long_stride_length
= 10000;
9776 tng_data
->time_per_frame
= -1;
9778 tng_data
->n_particle_data_blocks
= 0;
9779 tng_data
->n_data_blocks
= 0;
9781 tng_data
->non_tr_particle_data
= 0;
9782 tng_data
->non_tr_data
= 0;
9784 tng_data
->compress_algo_pos
= 0;
9785 tng_data
->compress_algo_vel
= 0;
9786 tng_data
->compression_precision
= 1000;
9787 tng_data
->distance_unit_exponential
= -9;
9789 frame_set
->first_frame
= -1;
9790 frame_set
->n_mapping_blocks
= 0;
9791 frame_set
->mappings
= 0;
9792 frame_set
->molecule_cnt_list
= 0;
9794 frame_set
->n_particle_data_blocks
= 0;
9795 frame_set
->n_data_blocks
= 0;
9797 frame_set
->tr_particle_data
= 0;
9798 frame_set
->tr_data
= 0;
9800 frame_set
->n_written_frames
= 0;
9801 frame_set
->n_unwritten_frames
= 0;
9803 frame_set
->next_frame_set_file_pos
= -1;
9804 frame_set
->prev_frame_set_file_pos
= -1;
9805 frame_set
->medium_stride_next_frame_set_file_pos
= -1;
9806 frame_set
->medium_stride_prev_frame_set_file_pos
= -1;
9807 frame_set
->long_stride_next_frame_set_file_pos
= -1;
9808 frame_set
->long_stride_prev_frame_set_file_pos
= -1;
9810 frame_set
->first_frame_time
= -1;
9812 tng_data
->n_molecules
= 0;
9813 tng_data
->molecules
= 0;
9814 tng_data
->molecule_cnt_list
= 0;
9815 tng_data
->n_particles
= 0;
9818 /* Check the endianness of the computer */
9819 static int32_t endianness_32
= 0x01234567;
9821 if ( *(const unsigned char*)&endianness_32
== 0x01 )
9823 tng_data
->endianness_32
= TNG_BIG_ENDIAN_32
;
9827 else if( *(const unsigned char*)&endianness_32
== 0x67 )
9829 tng_data
->endianness_32
= TNG_LITTLE_ENDIAN_32
;
9834 else if ( *(const unsigned char*)&endianness_32
== 0x45 )
9836 tng_data
->endianness_32
= TNG_BYTE_PAIR_SWAP_32
;
9840 static int64_t endianness_64
= 0x0123456789ABCDEFLL
;
9841 /* 0x0123456789ABCDEF */
9842 if ( *(const unsigned char*)&endianness_64
== 0x01 )
9844 tng_data
->endianness_64
= TNG_BIG_ENDIAN_64
;
9847 /* 0xEFCDAB8967452301 */
9848 else if ( *(const unsigned char*)&endianness_64
== 0xEF )
9850 tng_data
->endianness_64
= TNG_LITTLE_ENDIAN_64
;
9853 /* 0x89ABCDEF01234567 */
9854 else if ( *(const unsigned char*)&endianness_64
== 0x89 )
9856 tng_data
->endianness_64
= TNG_QUAD_SWAP_64
;
9859 /* 0x45670123CDEF89AB */
9860 else if ( *(const unsigned char*)&endianness_64
== 0x45 )
9862 tng_data
->endianness_64
= TNG_BYTE_PAIR_SWAP_64
;
9865 /* 0x23016745AB89EFCD */
9866 else if ( *(const unsigned char*)&endianness_64
== 0x23 )
9868 tng_data
->endianness_64
= TNG_BYTE_SWAP_64
;
9872 /* By default do not swap the byte order, i.e. keep the byte order of the
9873 * architecture. The input file endianness will be set when reading the
9874 * header. The output endianness can be changed - before the file is
9876 tng_data
->input_endianness_swap_func_32
= 0;
9877 tng_data
->input_endianness_swap_func_64
= 0;
9878 tng_data
->output_endianness_swap_func_32
= 0;
9879 tng_data
->output_endianness_swap_func_64
= 0;
9881 tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
= -1;
9882 tng_data
->current_trajectory_frame_set
.prev_frame_set_file_pos
= -1;
9883 tng_data
->current_trajectory_frame_set
.n_frames
= 0;
9885 return(TNG_SUCCESS
);
9888 tng_function_status DECLSPECDLLEXPORT
tng_trajectory_destroy(tng_trajectory_t
*tng_data_p
)
9891 int64_t n_particles
, n_values_per_frame
;
9892 tng_trajectory_t tng_data
= *tng_data_p
;
9893 tng_trajectory_frame_set_t frame_set
;
9897 return(TNG_SUCCESS
);
9900 frame_set
= &tng_data
->current_trajectory_frame_set
;
9902 if(tng_data
->input_file_path
)
9904 free(tng_data
->input_file_path
);
9905 tng_data
->input_file_path
= 0;
9908 if(tng_data
->input_file
)
9910 if(tng_data
->output_file
== tng_data
->input_file
)
9912 tng_frame_set_finalize(tng_data
, TNG_USE_HASH
);
9913 tng_data
->output_file
= 0;
9915 fclose(tng_data
->input_file
);
9916 tng_data
->input_file
= 0;
9919 if(tng_data
->output_file_path
)
9921 free(tng_data
->output_file_path
);
9922 tng_data
->output_file_path
= 0;
9925 if(tng_data
->output_file
)
9927 /* FIXME: Do not always write the hash */
9928 tng_frame_set_finalize(tng_data
, TNG_USE_HASH
);
9929 fclose(tng_data
->output_file
);
9930 tng_data
->output_file
= 0;
9933 if(tng_data
->first_program_name
)
9935 free(tng_data
->first_program_name
);
9936 tng_data
->first_program_name
= 0;
9939 if(tng_data
->last_program_name
)
9941 free(tng_data
->last_program_name
);
9942 tng_data
->last_program_name
= 0;
9945 if(tng_data
->first_user_name
)
9947 free(tng_data
->first_user_name
);
9948 tng_data
->first_user_name
= 0;
9951 if(tng_data
->last_user_name
)
9953 free(tng_data
->last_user_name
);
9954 tng_data
->last_user_name
= 0;
9957 if(tng_data
->first_computer_name
)
9959 free(tng_data
->first_computer_name
);
9960 tng_data
->first_computer_name
= 0;
9963 if(tng_data
->last_computer_name
)
9965 free(tng_data
->last_computer_name
);
9966 tng_data
->last_computer_name
= 0;
9969 if(tng_data
->first_pgp_signature
)
9971 free(tng_data
->first_pgp_signature
);
9972 tng_data
->first_pgp_signature
= 0;
9975 if(tng_data
->last_pgp_signature
)
9977 free(tng_data
->last_pgp_signature
);
9978 tng_data
->last_pgp_signature
= 0;
9981 if(tng_data
->forcefield_name
)
9983 free(tng_data
->forcefield_name
);
9984 tng_data
->forcefield_name
= 0;
9987 tng_frame_set_particle_mapping_free(tng_data
);
9989 if(frame_set
->molecule_cnt_list
)
9991 free(frame_set
->molecule_cnt_list
);
9992 frame_set
->molecule_cnt_list
= 0;
9995 if(tng_data
->var_num_atoms_flag
)
9997 n_particles
= frame_set
->n_particles
;
10001 n_particles
= tng_data
->n_particles
;
10004 if(tng_data
->non_tr_particle_data
)
10006 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
10008 if(tng_data
->non_tr_particle_data
[i
].values
)
10010 free(tng_data
->non_tr_particle_data
[i
].values
);
10011 tng_data
->non_tr_particle_data
[i
].values
= 0;
10014 if(tng_data
->non_tr_particle_data
[i
].strings
)
10016 n_values_per_frame
= tng_data
->non_tr_particle_data
[i
].
10017 n_values_per_frame
;
10018 if(tng_data
->non_tr_particle_data
[i
].strings
[0])
10020 for(j
= 0; j
< n_particles
; j
++)
10022 if(tng_data
->non_tr_particle_data
[i
].strings
[0][j
])
10024 for(k
= 0; k
< n_values_per_frame
; k
++)
10026 if(tng_data
->non_tr_particle_data
[i
].
10029 free(tng_data
->non_tr_particle_data
[i
].
10031 tng_data
->non_tr_particle_data
[i
].
10032 strings
[0][j
][k
] = 0;
10035 free(tng_data
->non_tr_particle_data
[i
].
10037 tng_data
->non_tr_particle_data
[i
].strings
[0][j
] = 0;
10040 free(tng_data
->non_tr_particle_data
[i
].strings
[0]);
10041 tng_data
->non_tr_particle_data
[i
].strings
[0] = 0;
10043 free(tng_data
->non_tr_particle_data
[i
].strings
);
10044 tng_data
->non_tr_particle_data
[i
].strings
= 0;
10047 if(tng_data
->non_tr_particle_data
[i
].block_name
)
10049 free(tng_data
->non_tr_particle_data
[i
].block_name
);
10050 tng_data
->non_tr_particle_data
[i
].block_name
= 0;
10053 free(tng_data
->non_tr_particle_data
);
10054 tng_data
->non_tr_particle_data
= 0;
10057 if(tng_data
->non_tr_data
)
10059 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
10061 if(tng_data
->non_tr_data
[i
].values
)
10063 free(tng_data
->non_tr_data
[i
].values
);
10064 tng_data
->non_tr_data
[i
].values
= 0;
10067 if(tng_data
->non_tr_data
[i
].strings
)
10069 n_values_per_frame
= tng_data
->non_tr_data
[i
].
10070 n_values_per_frame
;
10071 if(tng_data
->non_tr_data
[i
].strings
[0])
10073 for(j
= 0; j
< n_values_per_frame
; j
++)
10075 if(tng_data
->non_tr_data
[i
].strings
[0][j
])
10077 free(tng_data
->non_tr_data
[i
].strings
[0][j
]);
10078 tng_data
->non_tr_data
[i
].strings
[0][j
] = 0;
10081 free(tng_data
->non_tr_data
[i
].strings
[0]);
10082 tng_data
->non_tr_data
[i
].strings
[0] = 0;
10084 free(tng_data
->non_tr_data
[i
].strings
);
10085 tng_data
->non_tr_data
[i
].strings
= 0;
10088 if(tng_data
->non_tr_data
[i
].block_name
)
10090 free(tng_data
->non_tr_data
[i
].block_name
);
10091 tng_data
->non_tr_data
[i
].block_name
= 0;
10094 free(tng_data
->non_tr_data
);
10095 tng_data
->non_tr_data
= 0;
10098 tng_data
->n_particle_data_blocks
= 0;
10099 tng_data
->n_data_blocks
= 0;
10101 if(tng_data
->compress_algo_pos
)
10103 free(tng_data
->compress_algo_pos
);
10104 tng_data
->compress_algo_pos
= 0;
10106 if(tng_data
->compress_algo_vel
)
10108 free(tng_data
->compress_algo_vel
);
10109 tng_data
->compress_algo_vel
= 0;
10112 if(frame_set
->tr_particle_data
)
10114 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
10116 if(frame_set
->tr_particle_data
[i
].values
)
10118 free(frame_set
->tr_particle_data
[i
].values
);
10119 frame_set
->tr_particle_data
[i
].values
= 0;
10122 if(frame_set
->tr_particle_data
[i
].strings
)
10124 n_values_per_frame
= frame_set
->tr_particle_data
[i
].
10125 n_values_per_frame
;
10126 for(j
= 0; j
< frame_set
->tr_particle_data
[i
].n_frames
; j
++)
10128 if(frame_set
->tr_particle_data
[i
].strings
[j
])
10130 for(k
= 0; k
< n_particles
; k
++)
10132 if(frame_set
->tr_particle_data
[i
].
10135 for(l
= 0; l
< n_values_per_frame
; l
++)
10137 if(frame_set
->tr_particle_data
[i
].
10140 free(frame_set
->tr_particle_data
[i
].
10142 frame_set
->tr_particle_data
[i
].
10143 strings
[j
][k
][l
] = 0;
10146 free(frame_set
->tr_particle_data
[i
].
10148 frame_set
->tr_particle_data
[i
].
10152 free(frame_set
->tr_particle_data
[i
].strings
[j
]);
10153 frame_set
->tr_particle_data
[i
].strings
[j
] = 0;
10156 free(frame_set
->tr_particle_data
[i
].strings
);
10157 frame_set
->tr_particle_data
[i
].strings
= 0;
10160 if(frame_set
->tr_particle_data
[i
].block_name
)
10162 free(frame_set
->tr_particle_data
[i
].block_name
);
10163 frame_set
->tr_particle_data
[i
].block_name
= 0;
10166 free(frame_set
->tr_particle_data
);
10167 frame_set
->tr_particle_data
= 0;
10170 if(frame_set
->tr_data
)
10172 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
10174 if(frame_set
->tr_data
[i
].values
)
10176 free(frame_set
->tr_data
[i
].values
);
10177 frame_set
->tr_data
[i
].values
= 0;
10180 if(frame_set
->tr_data
[i
].strings
)
10182 n_values_per_frame
= frame_set
->tr_data
[i
].
10183 n_values_per_frame
;
10184 for(j
= 0; j
< frame_set
->tr_data
[i
].n_frames
; j
++)
10186 if(frame_set
->tr_data
[i
].strings
[j
])
10188 for(k
= 0; k
< n_values_per_frame
; k
++)
10190 if(frame_set
->tr_data
[i
].strings
[j
][k
])
10192 free(frame_set
->tr_data
[i
].strings
[j
][k
]);
10193 frame_set
->tr_data
[i
].strings
[j
][k
] = 0;
10196 free(frame_set
->tr_data
[i
].strings
[j
]);
10197 frame_set
->tr_data
[i
].strings
[j
] = 0;
10200 free(frame_set
->tr_data
[i
].strings
);
10201 frame_set
->tr_data
[i
].strings
= 0;
10204 if(frame_set
->tr_data
[i
].block_name
)
10206 free(frame_set
->tr_data
[i
].block_name
);
10207 frame_set
->tr_data
[i
].block_name
= 0;
10210 free(frame_set
->tr_data
);
10211 frame_set
->tr_data
= 0;
10214 frame_set
->n_particle_data_blocks
= 0;
10215 frame_set
->n_data_blocks
= 0;
10217 if(tng_data
->molecules
)
10219 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
10221 tng_molecule_destroy(tng_data
, &tng_data
->molecules
[i
]);
10223 free(tng_data
->molecules
);
10224 tng_data
->molecules
= 0;
10225 tng_data
->n_molecules
= 0;
10227 if(tng_data
->molecule_cnt_list
)
10229 free(tng_data
->molecule_cnt_list
);
10230 tng_data
->molecule_cnt_list
= 0;
10236 return(TNG_SUCCESS
);
10239 tng_function_status DECLSPECDLLEXPORT
tng_trajectory_init_from_src(tng_trajectory_t src
,
10240 tng_trajectory_t
*dest_p
)
10242 tng_trajectory_frame_set_t frame_set
;
10243 tng_trajectory_t dest
;
10245 TNG_ASSERT(src
!= 0, "TNG library: Source trajectory must not be NULL.");
10247 *dest_p
= malloc(sizeof(struct tng_trajectory
));
10250 fprintf(stderr
, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10251 sizeof(struct tng_trajectory
), __FILE__
, __LINE__
);
10252 return(TNG_CRITICAL
);
10257 frame_set
= &dest
->current_trajectory_frame_set
;
10259 dest
->input_file_path
= malloc(strlen(src
->input_file_path
) + 1);
10260 if(!dest
->input_file_path
)
10262 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10263 (int)strlen(src
->input_file_path
) + 1, __FILE__
, __LINE__
);
10264 return(TNG_CRITICAL
);
10266 strcpy(dest
->input_file_path
, src
->input_file_path
);
10267 dest
->input_file
= 0;
10268 dest
->input_file_len
= src
->input_file_len
;
10269 dest
->output_file_path
= malloc(strlen(src
->output_file_path
) + 1);
10270 if(!dest
->output_file_path
)
10272 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
10273 (int)strlen(src
->output_file_path
) + 1, __FILE__
, __LINE__
);
10274 return(TNG_CRITICAL
);
10276 strcpy(dest
->output_file_path
, src
->output_file_path
);
10277 dest
->output_file
= 0;
10279 dest
->first_program_name
= 0;
10280 dest
->first_user_name
= 0;
10281 dest
->first_computer_name
= 0;
10282 dest
->first_pgp_signature
= 0;
10283 dest
->last_program_name
= 0;
10284 dest
->last_user_name
= 0;
10285 dest
->last_computer_name
= 0;
10286 dest
->last_pgp_signature
= 0;
10287 dest
->forcefield_name
= 0;
10289 dest
->var_num_atoms_flag
= src
->var_num_atoms_flag
;
10290 dest
->first_trajectory_frame_set_input_file_pos
=
10291 src
->first_trajectory_frame_set_input_file_pos
;
10292 dest
->last_trajectory_frame_set_input_file_pos
=
10293 src
->last_trajectory_frame_set_input_file_pos
;
10294 dest
->current_trajectory_frame_set_input_file_pos
=
10295 src
->current_trajectory_frame_set_input_file_pos
;
10296 dest
->first_trajectory_frame_set_output_file_pos
=
10297 src
->first_trajectory_frame_set_output_file_pos
;
10298 dest
->last_trajectory_frame_set_output_file_pos
=
10299 src
->last_trajectory_frame_set_output_file_pos
;
10300 dest
->current_trajectory_frame_set_output_file_pos
=
10301 src
->current_trajectory_frame_set_output_file_pos
;
10302 dest
->frame_set_n_frames
= src
->frame_set_n_frames
;
10303 dest
->n_trajectory_frame_sets
= src
->n_trajectory_frame_sets
;
10304 dest
->medium_stride_length
= src
->medium_stride_length
;
10305 dest
->long_stride_length
= src
->long_stride_length
;
10307 dest
->time_per_frame
= src
->time_per_frame
;
10309 /* Currently the non trajectory data blocks are not copied since it
10310 * can lead to problems when freeing memory in a parallel block. */
10311 dest
->n_particle_data_blocks
= 0;
10312 dest
->n_data_blocks
= 0;
10313 dest
->non_tr_particle_data
= 0;
10314 dest
->non_tr_data
= 0;
10316 dest
->compress_algo_pos
= 0;
10317 dest
->compress_algo_vel
= 0;
10318 dest
->distance_unit_exponential
= -9;
10319 dest
->compression_precision
= 1000;
10321 frame_set
->n_mapping_blocks
= 0;
10322 frame_set
->mappings
= 0;
10323 frame_set
->molecule_cnt_list
= 0;
10325 frame_set
->n_particle_data_blocks
= 0;
10326 frame_set
->n_data_blocks
= 0;
10328 frame_set
->tr_particle_data
= 0;
10329 frame_set
->tr_data
= 0;
10331 frame_set
->next_frame_set_file_pos
= -1;
10332 frame_set
->prev_frame_set_file_pos
= -1;
10333 frame_set
->medium_stride_next_frame_set_file_pos
= -1;
10334 frame_set
->medium_stride_prev_frame_set_file_pos
= -1;
10335 frame_set
->long_stride_next_frame_set_file_pos
= -1;
10336 frame_set
->long_stride_prev_frame_set_file_pos
= -1;
10337 frame_set
->first_frame
= -1;
10339 dest
->n_molecules
= 0;
10340 dest
->molecules
= 0;
10341 dest
->molecule_cnt_list
= 0;
10342 dest
->n_particles
= src
->n_particles
;
10344 dest
->endianness_32
= src
->endianness_32
;
10345 dest
->endianness_64
= src
->endianness_64
;
10346 dest
->input_endianness_swap_func_32
= src
->input_endianness_swap_func_32
;
10347 dest
->input_endianness_swap_func_64
= src
->input_endianness_swap_func_64
;
10348 dest
->output_endianness_swap_func_32
= src
->output_endianness_swap_func_32
;
10349 dest
->output_endianness_swap_func_64
= src
->output_endianness_swap_func_64
;
10351 dest
->current_trajectory_frame_set
.next_frame_set_file_pos
= -1;
10352 dest
->current_trajectory_frame_set
.prev_frame_set_file_pos
= -1;
10353 dest
->current_trajectory_frame_set
.n_frames
= 0;
10355 return(TNG_SUCCESS
);
10358 tng_function_status DECLSPECDLLEXPORT
tng_input_file_get(const tng_trajectory_t tng_data
,
10359 char *file_name
, const int max_len
)
10361 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10362 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
10364 strncpy(file_name
, tng_data
->input_file_path
, max_len
- 1);
10365 file_name
[max_len
- 1] = 0;
10367 if(strlen(tng_data
->input_file_path
) > (unsigned int)max_len
- 1)
10369 return(TNG_FAILURE
);
10371 return(TNG_SUCCESS
);
10374 tng_function_status DECLSPECDLLEXPORT
tng_input_file_set(tng_trajectory_t tng_data
,
10375 const char *file_name
)
10380 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10381 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
10384 if(tng_data
->input_file_path
&& strcmp(tng_data
->input_file_path
,
10387 return(TNG_SUCCESS
);
10390 if(tng_data
->input_file
)
10392 fclose(tng_data
->input_file
);
10395 len
= tng_min_i((int)strlen(file_name
) + 1, TNG_MAX_STR_LEN
);
10396 temp
= realloc(tng_data
->input_file_path
, len
);
10399 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10400 __FILE__
, __LINE__
);
10401 free(tng_data
->input_file_path
);
10402 tng_data
->input_file_path
= 0;
10403 return(TNG_CRITICAL
);
10405 tng_data
->input_file_path
= temp
;
10407 strncpy(tng_data
->input_file_path
, file_name
, len
);
10409 return(tng_input_file_init(tng_data
));
10412 tng_function_status
tng_output_file_get(const tng_trajectory_t tng_data
,
10413 char *file_name
, const int max_len
)
10415 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10416 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
10418 strncpy(file_name
, tng_data
->output_file_path
, max_len
- 1);
10419 file_name
[max_len
- 1] = 0;
10421 if(strlen(tng_data
->output_file_path
) > (unsigned int)max_len
- 1)
10423 return(TNG_FAILURE
);
10425 return(TNG_SUCCESS
);
10428 tng_function_status DECLSPECDLLEXPORT
tng_output_file_set(tng_trajectory_t tng_data
,
10429 const char *file_name
)
10434 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10435 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
10437 if(tng_data
->output_file_path
&&
10438 strcmp(tng_data
->output_file_path
, file_name
) == 0)
10440 return(TNG_SUCCESS
);
10443 if(tng_data
->output_file
)
10445 fclose(tng_data
->output_file
);
10448 len
= tng_min_i((int)strlen(file_name
) + 1, TNG_MAX_STR_LEN
);
10449 temp
= realloc(tng_data
->output_file_path
, len
);
10452 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
10453 __FILE__
, __LINE__
);
10454 free(tng_data
->output_file_path
);
10455 tng_data
->output_file_path
= 0;
10456 return(TNG_CRITICAL
);
10458 tng_data
->output_file_path
= temp
;
10460 strncpy(tng_data
->output_file_path
, file_name
, len
);
10462 return(tng_output_file_init(tng_data
));
10465 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
10466 (tng_trajectory_t tng_data
,
10467 const char *file_name
)
10472 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10473 TNG_ASSERT(file_name
, "TNG library: file_name must not be a NULL pointer");
10475 if(tng_data
->output_file_path
&&
10476 strcmp(tng_data
->output_file_path
, file_name
) == 0)
10478 return(TNG_SUCCESS
);
10481 if(tng_data
->output_file
)
10483 fclose(tng_data
->output_file
);
10486 len
= tng_min_i((int)strlen(file_name
) + 1, TNG_MAX_STR_LEN
);
10487 temp
= realloc(tng_data
->output_file_path
, len
);
10490 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len
,
10491 __FILE__
, __LINE__
);
10492 free(tng_data
->output_file_path
);
10493 tng_data
->output_file_path
= 0;
10494 return(TNG_CRITICAL
);
10496 tng_data
->output_file_path
= temp
;
10498 strncpy(tng_data
->output_file_path
, file_name
, len
);
10500 tng_data
->output_file
= fopen(tng_data
->output_file_path
, "rb+");
10501 if(!tng_data
->output_file
)
10503 fprintf(stderr
, "TNG library: Cannot open file %s. %s: %d\n",
10504 tng_data
->output_file_path
, __FILE__
, __LINE__
);
10505 return(TNG_CRITICAL
);
10507 tng_data
->input_file
= tng_data
->output_file
;
10509 return(TNG_SUCCESS
);
10512 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
10513 (const tng_trajectory_t tng_data
, tng_file_endianness
*endianness
)
10515 tng_endianness_32 end_32
;
10516 tng_endianness_64 end_64
;
10518 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10519 TNG_ASSERT(endianness
, "TNG library: endianness must not be a NULL pointer");
10521 if(tng_data
->output_endianness_swap_func_32
)
10523 /* If other endianness variants are added they must be added here as well */
10524 if(tng_data
->output_endianness_swap_func_32
==
10525 &tng_swap_byte_order_big_endian_32
)
10527 end_32
= TNG_BIG_ENDIAN_32
;
10529 else if(tng_data
->output_endianness_swap_func_32
==
10530 &tng_swap_byte_order_little_endian_32
)
10532 end_32
= TNG_LITTLE_ENDIAN_32
;
10536 return(TNG_FAILURE
);
10541 end_32
= (tng_endianness_32
)tng_data
->endianness_32
;
10544 if(tng_data
->output_endianness_swap_func_64
)
10546 /* If other endianness variants are added they must be added here as well */
10547 if(tng_data
->output_endianness_swap_func_64
==
10548 &tng_swap_byte_order_big_endian_64
)
10550 end_64
= TNG_BIG_ENDIAN_64
;
10552 else if(tng_data
->output_endianness_swap_func_64
==
10553 &tng_swap_byte_order_little_endian_64
)
10555 end_64
= TNG_LITTLE_ENDIAN_64
;
10559 return(TNG_FAILURE
);
10564 end_64
= (tng_endianness_64
)tng_data
->endianness_64
;
10567 if((int)end_32
!= (int)end_64
)
10569 return(TNG_FAILURE
);
10572 if(end_32
== TNG_LITTLE_ENDIAN_32
)
10574 *endianness
= TNG_LITTLE_ENDIAN
;
10577 else if(end_32
== TNG_BIG_ENDIAN_32
)
10579 *endianness
= TNG_BIG_ENDIAN
;
10583 return(TNG_FAILURE
);
10586 return(TNG_SUCCESS
);
10589 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
10590 (tng_trajectory_t tng_data
,
10591 const tng_file_endianness endianness
)
10593 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10595 /* Tne endianness cannot be changed if the data has already been written
10596 * to the output file. */
10597 if(ftell(tng_data
->output_file
) > 0)
10599 return(TNG_FAILURE
);
10602 if(endianness
== TNG_BIG_ENDIAN
)
10604 if(tng_data
->endianness_32
== TNG_BIG_ENDIAN_32
)
10606 tng_data
->output_endianness_swap_func_32
= 0;
10610 tng_data
->output_endianness_swap_func_32
=
10611 &tng_swap_byte_order_big_endian_32
;
10613 if(tng_data
->endianness_64
== TNG_BIG_ENDIAN_64
)
10615 tng_data
->output_endianness_swap_func_64
= 0;
10619 tng_data
->output_endianness_swap_func_64
=
10620 &tng_swap_byte_order_big_endian_64
;
10622 return(TNG_SUCCESS
);
10624 else if(endianness
== TNG_LITTLE_ENDIAN
)
10626 if(tng_data
->endianness_32
== TNG_LITTLE_ENDIAN_32
)
10628 tng_data
->output_endianness_swap_func_32
= 0;
10632 tng_data
->output_endianness_swap_func_32
=
10633 &tng_swap_byte_order_little_endian_32
;
10635 if(tng_data
->endianness_64
== TNG_LITTLE_ENDIAN_64
)
10637 tng_data
->output_endianness_swap_func_64
= 0;
10641 tng_data
->output_endianness_swap_func_64
=
10642 &tng_swap_byte_order_little_endian_64
;
10644 return(TNG_SUCCESS
);
10647 /* If the specified endianness is neither big nor little endian return a
10649 return(TNG_FAILURE
);
10652 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
10653 (const tng_trajectory_t tng_data
,
10654 char *name
, const int max_len
)
10656 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10657 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10659 strncpy(name
, tng_data
->first_program_name
, max_len
- 1);
10660 name
[max_len
- 1] = 0;
10662 if(strlen(tng_data
->first_program_name
) > (unsigned int)max_len
- 1)
10664 return(TNG_FAILURE
);
10666 return(TNG_SUCCESS
);
10669 tng_function_status DECLSPECDLLEXPORT
tng_first_program_name_set(tng_trajectory_t tng_data
,
10670 const char *new_name
)
10674 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10675 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10677 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10679 if(tng_data
->first_program_name
&& strlen(tng_data
->first_program_name
) < len
)
10681 free(tng_data
->first_program_name
);
10682 tng_data
->first_program_name
= 0;
10684 if(!tng_data
->first_program_name
)
10686 tng_data
->first_program_name
= malloc(len
);
10687 if(!tng_data
->first_program_name
)
10689 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10690 __FILE__
, __LINE__
);
10691 return(TNG_CRITICAL
);
10695 strncpy(tng_data
->first_program_name
, new_name
, len
);
10697 return(TNG_SUCCESS
);
10700 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
10701 (const tng_trajectory_t tng_data
,
10702 char *name
, const int max_len
)
10704 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10705 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10707 strncpy(name
, tng_data
->last_program_name
, max_len
- 1);
10708 name
[max_len
- 1] = 0;
10710 if(strlen(tng_data
->last_program_name
) > (unsigned int)max_len
- 1)
10712 return(TNG_FAILURE
);
10714 return(TNG_SUCCESS
);
10717 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
10718 (tng_trajectory_t tng_data
,
10719 const char *new_name
)
10723 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10724 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10726 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10728 if(tng_data
->last_program_name
&& strlen(tng_data
->last_program_name
) < len
)
10730 free(tng_data
->last_program_name
);
10731 tng_data
->last_program_name
= 0;
10733 if(!tng_data
->last_program_name
)
10735 tng_data
->last_program_name
= malloc(len
);
10736 if(!tng_data
->last_program_name
)
10738 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10739 __FILE__
, __LINE__
);
10740 return(TNG_CRITICAL
);
10744 strncpy(tng_data
->last_program_name
, new_name
, len
);
10746 return(TNG_SUCCESS
);
10749 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
10750 (const tng_trajectory_t tng_data
,
10751 char *name
, const int max_len
)
10753 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10754 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10756 strncpy(name
, tng_data
->first_user_name
, max_len
- 1);
10757 name
[max_len
- 1] = 0;
10759 if(strlen(tng_data
->first_user_name
) > (unsigned int)max_len
- 1)
10761 return(TNG_FAILURE
);
10763 return(TNG_SUCCESS
);
10766 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
10767 (tng_trajectory_t tng_data
,
10768 const char *new_name
)
10772 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10773 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10775 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10777 /* If the currently stored string length is not enough to store the new
10778 * string it is freed and reallocated. */
10779 if(tng_data
->first_user_name
&& strlen(tng_data
->first_user_name
) < len
)
10781 free(tng_data
->first_user_name
);
10782 tng_data
->first_user_name
= 0;
10784 if(!tng_data
->first_user_name
)
10786 tng_data
->first_user_name
= malloc(len
);
10787 if(!tng_data
->first_user_name
)
10789 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10790 __FILE__
, __LINE__
);
10791 return(TNG_CRITICAL
);
10795 strncpy(tng_data
->first_user_name
, new_name
, len
);
10797 return(TNG_SUCCESS
);
10800 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
10801 (const tng_trajectory_t tng_data
,
10802 char *name
, const int max_len
)
10804 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10805 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10807 strncpy(name
, tng_data
->last_user_name
, max_len
- 1);
10808 name
[max_len
- 1] = 0;
10810 if(strlen(tng_data
->last_user_name
) > (unsigned int)max_len
- 1)
10812 return(TNG_FAILURE
);
10814 return(TNG_SUCCESS
);
10817 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
10818 (tng_trajectory_t tng_data
,
10819 const char *new_name
)
10823 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10824 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10826 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10828 /* If the currently stored string length is not enough to store the new
10829 * string it is freed and reallocated. */
10830 if(tng_data
->last_user_name
&& strlen(tng_data
->last_user_name
) < len
)
10832 free(tng_data
->last_user_name
);
10833 tng_data
->last_user_name
= 0;
10835 if(!tng_data
->last_user_name
)
10837 tng_data
->last_user_name
= malloc(len
);
10838 if(!tng_data
->last_user_name
)
10840 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10841 __FILE__
, __LINE__
);
10842 return(TNG_CRITICAL
);
10846 strncpy(tng_data
->last_user_name
, new_name
, len
);
10848 return(TNG_SUCCESS
);
10851 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
10852 (const tng_trajectory_t tng_data
,
10853 char *name
, const int max_len
)
10855 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10856 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10858 strncpy(name
, tng_data
->first_computer_name
, max_len
- 1);
10859 name
[max_len
- 1] = 0;
10861 if(strlen(tng_data
->first_computer_name
) > (unsigned int)max_len
- 1)
10863 return(TNG_FAILURE
);
10865 return(TNG_SUCCESS
);
10868 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
10869 (tng_trajectory_t tng_data
,
10870 const char *new_name
)
10874 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10875 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10877 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10879 /* If the currently stored string length is not enough to store the new
10880 * string it is freed and reallocated. */
10881 if(tng_data
->first_computer_name
&& strlen(tng_data
->first_computer_name
) < len
)
10883 free(tng_data
->first_computer_name
);
10884 tng_data
->first_computer_name
= 0;
10886 if(!tng_data
->first_computer_name
)
10888 tng_data
->first_computer_name
= malloc(len
);
10889 if(!tng_data
->first_computer_name
)
10891 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10892 __FILE__
, __LINE__
);
10893 return(TNG_CRITICAL
);
10897 strncpy(tng_data
->first_computer_name
, new_name
, len
);
10899 return(TNG_SUCCESS
);
10902 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
10903 (const tng_trajectory_t tng_data
,
10904 char *name
, const int max_len
)
10906 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10907 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
10909 strncpy(name
, tng_data
->last_computer_name
, max_len
- 1);
10910 name
[max_len
- 1] = 0;
10912 if(strlen(tng_data
->last_computer_name
) > (unsigned int)max_len
- 1)
10914 return(TNG_FAILURE
);
10916 return(TNG_SUCCESS
);
10919 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
10920 (tng_trajectory_t tng_data
,
10921 const char *new_name
)
10925 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10926 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
10928 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
10930 /* If the currently stored string length is not enough to store the new
10931 * string it is freed and reallocated. */
10932 if(tng_data
->last_computer_name
&& strlen(tng_data
->last_computer_name
) <
10935 free(tng_data
->last_computer_name
);
10936 tng_data
->last_computer_name
= 0;
10938 if(!tng_data
->last_computer_name
)
10940 tng_data
->last_computer_name
= malloc(len
);
10941 if(!tng_data
->last_computer_name
)
10943 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10944 __FILE__
, __LINE__
);
10945 return(TNG_CRITICAL
);
10949 strncpy(tng_data
->last_computer_name
, new_name
, len
);
10951 return(TNG_SUCCESS
);
10954 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
10955 (const tng_trajectory_t tng_data
,
10956 char *signature
, const int max_len
)
10958 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10959 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
10961 strncpy(signature
, tng_data
->first_pgp_signature
, max_len
- 1);
10962 signature
[max_len
- 1] = 0;
10964 if(strlen(tng_data
->first_pgp_signature
) > (unsigned int)max_len
- 1)
10966 return(TNG_FAILURE
);
10968 return(TNG_SUCCESS
);
10971 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10972 (tng_trajectory_t tng_data
,
10973 const char *signature
)
10977 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
10978 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
10980 len
= tng_min_i((int)strlen(signature
) + 1, TNG_MAX_STR_LEN
);
10982 /* If the currently stored string length is not enough to store the new
10983 * string it is freed and reallocated. */
10984 if(tng_data
->first_pgp_signature
&& strlen(tng_data
->first_pgp_signature
) <
10987 free(tng_data
->first_pgp_signature
);
10988 tng_data
->first_pgp_signature
= 0;
10990 if(!tng_data
->first_pgp_signature
)
10992 tng_data
->first_pgp_signature
= malloc(len
);
10993 if(!tng_data
->first_pgp_signature
)
10995 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
10996 __FILE__
, __LINE__
);
10997 return(TNG_CRITICAL
);
11001 strncpy(tng_data
->first_pgp_signature
, signature
, len
);
11003 return(TNG_SUCCESS
);
11006 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
11007 (const tng_trajectory_t tng_data
,
11008 char *signature
, const int max_len
)
11010 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11011 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
11013 strncpy(signature
, tng_data
->last_pgp_signature
, max_len
- 1);
11014 signature
[max_len
- 1] = 0;
11016 if(strlen(tng_data
->last_pgp_signature
) > (unsigned int)max_len
- 1)
11018 return(TNG_FAILURE
);
11020 return(TNG_SUCCESS
);
11023 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
11024 (tng_trajectory_t tng_data
,
11025 const char *signature
)
11029 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11030 TNG_ASSERT(signature
, "TNG library: signature must not be a NULL pointer");
11032 len
= tng_min_i((int)strlen(signature
) + 1, TNG_MAX_STR_LEN
);
11034 /* If the currently stored string length is not enough to store the new
11035 * string it is freed and reallocated. */
11036 if(tng_data
->last_pgp_signature
&& strlen(tng_data
->last_pgp_signature
) <
11039 free(tng_data
->last_pgp_signature
);
11040 tng_data
->last_pgp_signature
= 0;
11042 if(!tng_data
->last_pgp_signature
)
11044 tng_data
->last_pgp_signature
= malloc(len
);
11045 if(!tng_data
->last_pgp_signature
)
11047 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
11048 __FILE__
, __LINE__
);
11049 return(TNG_CRITICAL
);
11053 strncpy(tng_data
->last_pgp_signature
, signature
, len
);
11055 return(TNG_SUCCESS
);
11058 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
11059 (const tng_trajectory_t tng_data
,
11060 char *name
, const int max_len
)
11062 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11063 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer");
11065 strncpy(name
, tng_data
->forcefield_name
, max_len
- 1);
11066 name
[max_len
- 1] = 0;
11068 if(strlen(tng_data
->forcefield_name
) > (unsigned int)max_len
- 1)
11070 return(TNG_FAILURE
);
11072 return(TNG_SUCCESS
);
11075 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
11076 (tng_trajectory_t tng_data
,
11077 const char *new_name
)
11081 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11082 TNG_ASSERT(new_name
, "TNG library: new_name must not be a NULL pointer");
11084 len
= tng_min_i((int)strlen(new_name
) + 1, TNG_MAX_STR_LEN
);
11086 /* If the currently stored string length is not enough to store the new
11087 * string it is freed and reallocated. */
11088 if(tng_data
->forcefield_name
&& strlen(tng_data
->forcefield_name
) < len
)
11090 free(tng_data
->forcefield_name
);
11091 tng_data
->forcefield_name
= 0;
11093 if(!tng_data
->forcefield_name
)
11095 tng_data
->forcefield_name
= malloc(len
);
11096 if(!tng_data
->forcefield_name
)
11098 fprintf(stderr
, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len
,
11099 __FILE__
, __LINE__
);
11100 return(TNG_CRITICAL
);
11104 strncpy(tng_data
->forcefield_name
, new_name
, len
);
11106 return(TNG_SUCCESS
);
11109 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
11110 (const tng_trajectory_t tng_data
,
11113 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11114 TNG_ASSERT(len
, "TNG library: len must not be a NULL pointer");
11116 *len
= tng_data
->medium_stride_length
;
11118 return(TNG_SUCCESS
);
11121 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
11122 (tng_trajectory_t tng_data
,
11125 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11127 if(len
>= tng_data
->long_stride_length
)
11129 return(TNG_FAILURE
);
11131 tng_data
->medium_stride_length
= len
;
11133 return(TNG_SUCCESS
);
11136 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
11137 (const tng_trajectory_t tng_data
,
11140 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11141 TNG_ASSERT(len
, "TNG library: len must not be a NULL pointer");
11143 *len
= tng_data
->long_stride_length
;
11145 return(TNG_SUCCESS
);
11148 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
11149 (tng_trajectory_t tng_data
,
11152 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11154 if(len
<= tng_data
->medium_stride_length
)
11156 return(TNG_FAILURE
);
11158 tng_data
->long_stride_length
= len
;
11160 return(TNG_SUCCESS
);
11163 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
11164 (const tng_trajectory_t tng_data
,
11167 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11168 TNG_ASSERT(time
, "TNG library: time must not be a NULL pointer");
11170 *time
= tng_data
->time_per_frame
;
11172 return(TNG_SUCCESS
);
11175 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
11176 (tng_trajectory_t tng_data
,
11179 tng_trajectory_frame_set_t frame_set
;
11181 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11182 TNG_ASSERT(time
>= 0, "TNG library: The time per frame must be >= 0.");
11184 if(fabs(time
- tng_data
->time_per_frame
) < 0.00001)
11186 return(TNG_SUCCESS
);
11189 frame_set
= &tng_data
->current_trajectory_frame_set
;
11191 /* If the current frame set is not finished write it to disk before
11192 changing time per frame. */
11193 if(tng_data
->time_per_frame
> 0 && frame_set
->n_unwritten_frames
> 0)
11195 frame_set
->n_frames
= frame_set
->n_unwritten_frames
;
11196 tng_frame_set_write(tng_data
, TNG_USE_HASH
);
11198 tng_data
->time_per_frame
= time
;
11200 return(TNG_SUCCESS
);
11203 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
11204 (const tng_trajectory_t tng_data
,
11207 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11208 TNG_ASSERT(len
, "TNG library: len must not be a NULL pointer");
11210 *len
= tng_data
->input_file_len
;
11212 return(TNG_SUCCESS
);
11215 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
11216 (const tng_trajectory_t tng_data
,
11219 tng_gen_block_t block
;
11220 tng_function_status stat
;
11222 int64_t last_file_pos
, first_frame
, n_frames
;
11224 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11225 TNG_ASSERT(tng_data
->input_file
, "TNG library: An input file must be open to find the next frame set");
11226 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
11228 file_pos
= ftell(tng_data
->input_file
);
11229 last_file_pos
= tng_data
->last_trajectory_frame_set_input_file_pos
;
11231 if(last_file_pos
<= 0)
11233 return(TNG_FAILURE
);
11236 tng_block_init(&block
);
11237 fseek(tng_data
->input_file
,
11238 (long)last_file_pos
,
11240 /* Read block headers first to see that a frame set block is found. */
11241 stat
= tng_block_header_read(tng_data
, block
);
11242 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11244 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n", last_file_pos
,
11245 __FILE__
, __LINE__
);
11246 tng_block_destroy(&block
);
11247 return(TNG_FAILURE
);
11249 tng_block_destroy(&block
);
11251 if(fread(&first_frame
, sizeof(int64_t), 1, tng_data
->input_file
) == 0)
11253 fprintf(stderr
, "TNG library: Cannot read first frame of frame set. %s: %d\n",
11254 __FILE__
, __LINE__
);
11255 return(TNG_CRITICAL
);
11257 if(fread(&n_frames
, sizeof(int64_t), 1, tng_data
->input_file
) == 0)
11259 fprintf(stderr
, "TNG library: Cannot read n frames of frame set. %s: %d\n",
11260 __FILE__
, __LINE__
);
11261 return(TNG_CRITICAL
);
11263 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
11265 *n
= first_frame
+ n_frames
;
11267 return(TNG_SUCCESS
);
11270 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
11271 (const tng_trajectory_t tng_data
,
11274 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11276 *precision
= tng_data
->compression_precision
;
11278 return(TNG_SUCCESS
);
11281 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
11282 (tng_trajectory_t tng_data
,
11283 const double precision
)
11285 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11287 tng_data
->compression_precision
= precision
;
11289 return(TNG_SUCCESS
);
11292 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
11293 (tng_trajectory_t tng_data
,
11296 tng_molecule_t mol
;
11300 tng_function_status stat
;
11301 int64_t diff
, n_mod
, n_impl
;
11303 TNG_ASSERT(n
>= 0, "TNG library: The number of molecules must be >= 0");
11305 diff
= n
- tng_data
->n_particles
;
11307 stat
= tng_molecule_find(tng_data
, "TNG_IMPLICIT_MOL", -1, &mol
);
11308 if(stat
== TNG_SUCCESS
)
11310 if(tng_molecule_cnt_get(tng_data
, mol
, &n_impl
) != TNG_SUCCESS
)
11312 fprintf(stderr
, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
11313 __FILE__
, __LINE__
);
11314 return(TNG_FAILURE
);
11316 diff
-= n_impl
* mol
->n_atoms
;
11321 if(stat
== TNG_SUCCESS
)
11323 stat
= tng_molecule_cnt_set(tng_data
, mol
, 0);
11326 return(TNG_SUCCESS
);
11330 fprintf(stderr
, "TNG library: Already more actual particles than requested implicit ");
11331 fprintf(stderr
, "particle count.\n");
11332 fprintf(stderr
, "TNG library: Cannot set implicit particle count. %s: %d\n",
11333 __FILE__
, __LINE__
);
11334 /* FIXME: Should we set the count of all other molecules to 0 and add
11335 * implicit molecules? */
11336 return(TNG_FAILURE
);
11338 if(stat
!= TNG_SUCCESS
)
11340 stat
= tng_molecule_add(tng_data
,
11341 "TNG_IMPLICIT_MOL",
11343 if(stat
!= TNG_SUCCESS
)
11347 stat
= tng_molecule_chain_add(tng_data
, mol
, "", &chain
);
11348 if(stat
!= TNG_SUCCESS
)
11352 stat
= tng_chain_residue_add(tng_data
, chain
, "", &res
);
11353 if(stat
!= TNG_SUCCESS
)
11357 stat
= tng_residue_atom_add(tng_data
, res
, "", "", &atom
);
11358 if(stat
!= TNG_SUCCESS
)
11365 if(mol
->n_atoms
> 1)
11367 n_mod
= diff
% mol
->n_atoms
;
11370 fprintf(stderr
, "TNG library: Number of atoms in implicit molecule ");
11371 fprintf(stderr
, "not compatible with requested implicit particle cnt.\n");
11372 fprintf(stderr
, "TNG library: Cannot set implicit particle count. %s: %d\n",
11373 __FILE__
, __LINE__
);
11374 return(TNG_FAILURE
);
11376 diff
/= mol
->n_atoms
;
11379 stat
= tng_molecule_cnt_set(tng_data
, mol
, diff
);
11384 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11385 (const tng_trajectory_t tng_data
,
11388 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11389 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
11391 if(tng_data
->var_num_atoms_flag
== TNG_CONSTANT_N_ATOMS
)
11393 *n
= tng_data
->n_particles
;
11397 *n
= tng_data
->current_trajectory_frame_set
.n_particles
;
11400 return(TNG_SUCCESS
);
11403 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
11404 (const tng_trajectory_t tng_data
,
11407 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11408 TNG_ASSERT(variable
, "TNG library: variable must not be a NULL pointer");
11410 *variable
= tng_data
->var_num_atoms_flag
;
11412 return(TNG_SUCCESS
);
11415 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
11416 (const tng_trajectory_t tng_data
,
11419 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11420 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
11422 *n
= tng_data
->n_molecules
;
11424 return(TNG_SUCCESS
);
11427 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
11428 (const tng_trajectory_t tng_data
,
11431 int64_t *cnt_list
= 0, cnt
= 0, i
;
11433 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11434 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
11436 tng_molecule_cnt_list_get(tng_data
, &cnt_list
);
11440 return(TNG_FAILURE
);
11443 for(i
= 0; i
< tng_data
->n_molecules
; i
++)
11445 cnt
+= cnt_list
[i
];
11450 return(TNG_SUCCESS
);
11453 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
11454 (const tng_trajectory_t tng_data
,
11455 int64_t **mol_cnt_list
)
11457 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11459 if(tng_data
->var_num_atoms_flag
)
11461 *mol_cnt_list
= tng_data
->current_trajectory_frame_set
.
11466 *mol_cnt_list
= tng_data
->molecule_cnt_list
;
11468 if(*mol_cnt_list
== 0)
11470 return(TNG_FAILURE
);
11472 return(TNG_SUCCESS
);
11475 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
11476 (const tng_trajectory_t tng_data
,
11479 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11480 TNG_ASSERT(exp
, "TNG library: exp must not be a NULL pointer");
11482 *exp
= tng_data
->distance_unit_exponential
;
11484 return(TNG_SUCCESS
);
11487 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
11488 (const tng_trajectory_t tng_data
,
11491 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11493 tng_data
->distance_unit_exponential
= exp
;
11495 return(TNG_SUCCESS
);
11498 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
11499 (const tng_trajectory_t tng_data
,
11502 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11503 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
11505 *n
= tng_data
->frame_set_n_frames
;
11507 return(TNG_SUCCESS
);
11510 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
11511 (const tng_trajectory_t tng_data
,
11514 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11516 tng_data
->frame_set_n_frames
= n
;
11518 return(TNG_SUCCESS
);
11521 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
11522 (const tng_trajectory_t tng_data
,
11525 int64_t long_stride_length
, medium_stride_length
;
11526 long file_pos
, orig_frame_set_file_pos
;
11527 tng_trajectory_frame_set_t frame_set
;
11528 struct tng_trajectory_frame_set orig_frame_set
;
11529 tng_gen_block_t block
;
11530 tng_function_status stat
;
11533 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11534 TNG_ASSERT(n
, "TNG library: n must not be a NULL pointer");
11536 orig_frame_set
= tng_data
->current_trajectory_frame_set
;
11538 frame_set
= &tng_data
->current_trajectory_frame_set
;
11540 orig_frame_set_file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
11541 file_pos
= (long)tng_data
->first_trajectory_frame_set_input_file_pos
;
11545 *n
= tng_data
->n_trajectory_frame_sets
= cnt
;
11546 return(TNG_SUCCESS
);
11549 tng_block_init(&block
);
11550 fseek(tng_data
->input_file
,
11553 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
11554 /* Read block headers first to see what block is found. */
11555 stat
= tng_block_header_read(tng_data
, block
);
11556 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11558 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n", file_pos
,
11559 __FILE__
, __LINE__
);
11560 tng_block_destroy(&block
);
11561 return(TNG_CRITICAL
);
11564 if(tng_block_read_next(tng_data
, block
,
11565 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11567 tng_block_destroy(&block
);
11568 return(TNG_CRITICAL
);
11573 long_stride_length
= tng_data
->long_stride_length
;
11574 medium_stride_length
= tng_data
->medium_stride_length
;
11576 /* Take long steps forward until a long step forward would be too long or
11577 * the last frame set is found */
11578 file_pos
= (long)frame_set
->long_stride_next_frame_set_file_pos
;
11579 while(file_pos
> 0)
11583 cnt
+= long_stride_length
;
11584 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
11585 /* Read block headers first to see what block is found. */
11586 stat
= tng_block_header_read(tng_data
, block
);
11587 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11589 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11590 file_pos
, __FILE__
, __LINE__
);
11591 tng_block_destroy(&block
);
11592 return(TNG_CRITICAL
);
11595 if(tng_block_read_next(tng_data
, block
,
11596 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11598 tng_block_destroy(&block
);
11599 return(TNG_CRITICAL
);
11602 file_pos
= (long)frame_set
->long_stride_next_frame_set_file_pos
;
11605 /* Take medium steps forward until a medium step forward would be too long
11606 * or the last frame set is found */
11607 file_pos
= (long)frame_set
->medium_stride_next_frame_set_file_pos
;
11608 while(file_pos
> 0)
11612 cnt
+= medium_stride_length
;
11613 fseek(tng_data
->input_file
,
11616 /* Read block headers first to see what block is found. */
11617 stat
= tng_block_header_read(tng_data
, block
);
11618 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11620 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11621 file_pos
, __FILE__
, __LINE__
);
11622 tng_block_destroy(&block
);
11623 return(TNG_CRITICAL
);
11626 if(tng_block_read_next(tng_data
, block
,
11627 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11629 tng_block_destroy(&block
);
11630 return(TNG_CRITICAL
);
11633 file_pos
= (long)frame_set
->medium_stride_next_frame_set_file_pos
;
11636 /* Take one step forward until the last frame set is found */
11637 file_pos
= (long)frame_set
->next_frame_set_file_pos
;
11638 while(file_pos
> 0)
11643 fseek(tng_data
->input_file
,
11646 /* Read block headers first to see what block is found. */
11647 stat
= tng_block_header_read(tng_data
, block
);
11648 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11650 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
11651 file_pos
, __FILE__
, __LINE__
);
11652 tng_block_destroy(&block
);
11653 return(TNG_CRITICAL
);
11656 if(tng_block_read_next(tng_data
, block
,
11657 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11659 tng_block_destroy(&block
);
11660 return(TNG_CRITICAL
);
11663 file_pos
= (long)frame_set
->next_frame_set_file_pos
;
11666 tng_block_destroy(&block
);
11668 *n
= tng_data
->n_trajectory_frame_sets
= cnt
;
11670 *frame_set
= orig_frame_set
;
11672 fseek(tng_data
->input_file
,
11673 (long)tng_data
->first_trajectory_frame_set_input_file_pos
,
11676 tng_data
->current_trajectory_frame_set_input_file_pos
= orig_frame_set_file_pos
;
11678 return(TNG_SUCCESS
);
11681 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
11682 (const tng_trajectory_t tng_data
,
11683 tng_trajectory_frame_set_t
*frame_set_p
)
11685 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11687 *frame_set_p
= &tng_data
->current_trajectory_frame_set
;
11689 return(TNG_SUCCESS
);
11692 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
11693 (tng_trajectory_t tng_data
,
11696 int64_t long_stride_length
, medium_stride_length
;
11697 int64_t file_pos
, curr_nr
= 0, n_frame_sets
;
11698 tng_trajectory_frame_set_t frame_set
;
11699 tng_gen_block_t block
;
11700 tng_function_status stat
;
11702 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
11703 TNG_ASSERT(nr
>= 0, "The frame set number (nr) must be >= 0");
11705 frame_set
= &tng_data
->current_trajectory_frame_set
;
11707 stat
= tng_num_frame_sets_get(tng_data
, &n_frame_sets
);
11709 if(stat
!= TNG_SUCCESS
)
11714 if(nr
>= n_frame_sets
)
11716 return(TNG_FAILURE
);
11719 long_stride_length
= tng_data
->long_stride_length
;
11720 medium_stride_length
= tng_data
->medium_stride_length
;
11722 /* FIXME: The frame set number of the current frame set is not stored */
11724 if(nr
< n_frame_sets
- 1 - nr
)
11726 /* Start from the beginning */
11727 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
11731 /* Start from the end */
11732 file_pos
= tng_data
->last_trajectory_frame_set_input_file_pos
;
11733 curr_nr
= n_frame_sets
- 1;
11737 return(TNG_FAILURE
);
11740 tng_block_init(&block
);
11741 fseek(tng_data
->input_file
,
11744 tng_data
->current_trajectory_frame_set_input_file_pos
= (long)file_pos
;
11745 /* Read block headers first to see what block is found. */
11746 stat
= tng_block_header_read(tng_data
, block
);
11747 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11749 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n", file_pos
,
11750 __FILE__
, __LINE__
);
11751 tng_block_destroy(&block
);
11752 return(TNG_CRITICAL
);
11755 if(tng_block_read_next(tng_data
, block
,
11756 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11758 tng_block_destroy(&block
);
11759 return(TNG_CRITICAL
);
11764 tng_block_destroy(&block
);
11765 return(TNG_SUCCESS
);
11768 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
11770 /* Take long steps forward until a long step forward would be too long or
11771 * the right frame set is found */
11772 while(file_pos
> 0 && curr_nr
+ long_stride_length
<= nr
)
11774 file_pos
= frame_set
->long_stride_next_frame_set_file_pos
;
11777 curr_nr
+= long_stride_length
;
11778 fseek(tng_data
->input_file
, (long)file_pos
, SEEK_SET
);
11779 /* Read block headers first to see what block is found. */
11780 stat
= tng_block_header_read(tng_data
, block
);
11781 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11783 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11784 file_pos
, __FILE__
, __LINE__
);
11785 tng_block_destroy(&block
);
11786 return(TNG_CRITICAL
);
11789 if(tng_block_read_next(tng_data
, block
,
11790 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11792 tng_block_destroy(&block
);
11793 return(TNG_CRITICAL
);
11797 tng_block_destroy(&block
);
11798 return(TNG_SUCCESS
);
11803 /* Take medium steps forward until a medium step forward would be too long
11804 * or the right frame set is found */
11805 while(file_pos
> 0 && curr_nr
+ medium_stride_length
<= nr
)
11807 file_pos
= frame_set
->medium_stride_next_frame_set_file_pos
;
11810 curr_nr
+= medium_stride_length
;
11811 fseek(tng_data
->input_file
,
11814 /* Read block headers first to see what block is found. */
11815 stat
= tng_block_header_read(tng_data
, block
);
11816 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11818 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11819 file_pos
, __FILE__
, __LINE__
);
11820 tng_block_destroy(&block
);
11821 return(TNG_CRITICAL
);
11824 if(tng_block_read_next(tng_data
, block
,
11825 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11827 tng_block_destroy(&block
);
11828 return(TNG_CRITICAL
);
11832 tng_block_destroy(&block
);
11833 return(TNG_SUCCESS
);
11838 /* Take one step forward until the right frame set is found */
11839 while(file_pos
> 0 && curr_nr
< nr
)
11841 file_pos
= frame_set
->next_frame_set_file_pos
;
11846 fseek(tng_data
->input_file
,
11849 /* Read block headers first to see what block is found. */
11850 stat
= tng_block_header_read(tng_data
, block
);
11851 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11853 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11854 file_pos
, __FILE__
, __LINE__
);
11855 tng_block_destroy(&block
);
11856 return(TNG_CRITICAL
);
11859 if(tng_block_read_next(tng_data
, block
,
11860 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11862 tng_block_destroy(&block
);
11863 return(TNG_CRITICAL
);
11867 tng_block_destroy(&block
);
11868 return(TNG_SUCCESS
);
11873 /* Take long steps backward until a long step backward would be too long
11874 * or the right frame set is found */
11875 while(file_pos
> 0 && curr_nr
- long_stride_length
>= nr
)
11877 file_pos
= frame_set
->long_stride_prev_frame_set_file_pos
;
11880 curr_nr
-= long_stride_length
;
11881 fseek(tng_data
->input_file
,
11884 /* Read block headers first to see what block is found. */
11885 stat
= tng_block_header_read(tng_data
, block
);
11886 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11888 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11889 file_pos
, __FILE__
, __LINE__
);
11890 tng_block_destroy(&block
);
11891 return(TNG_CRITICAL
);
11894 if(tng_block_read_next(tng_data
, block
,
11895 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11897 tng_block_destroy(&block
);
11898 return(TNG_CRITICAL
);
11902 tng_block_destroy(&block
);
11903 return(TNG_SUCCESS
);
11908 /* Take medium steps backward until a medium step backward would be too long
11909 * or the right frame set is found */
11910 while(file_pos
> 0 && curr_nr
- medium_stride_length
>= nr
)
11912 file_pos
= frame_set
->medium_stride_prev_frame_set_file_pos
;
11915 curr_nr
-= medium_stride_length
;
11916 fseek(tng_data
->input_file
,
11919 /* Read block headers first to see what block is found. */
11920 stat
= tng_block_header_read(tng_data
, block
);
11921 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11923 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11924 file_pos
, __FILE__
, __LINE__
);
11925 tng_block_destroy(&block
);
11926 return(TNG_CRITICAL
);
11929 if(tng_block_read_next(tng_data
, block
,
11930 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11932 tng_block_destroy(&block
);
11933 return(TNG_CRITICAL
);
11937 tng_block_destroy(&block
);
11938 return(TNG_SUCCESS
);
11943 /* Take one step backward until the right frame set is found */
11944 while(file_pos
> 0 && curr_nr
> nr
)
11946 file_pos
= frame_set
->prev_frame_set_file_pos
;
11950 fseek(tng_data
->input_file
,
11953 /* Read block headers first to see what block is found. */
11954 stat
= tng_block_header_read(tng_data
, block
);
11955 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11957 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11958 file_pos
, __FILE__
, __LINE__
);
11959 tng_block_destroy(&block
);
11960 return(TNG_CRITICAL
);
11963 if(tng_block_read_next(tng_data
, block
,
11964 TNG_SKIP_HASH
) != TNG_SUCCESS
)
11966 tng_block_destroy(&block
);
11967 return(TNG_CRITICAL
);
11971 tng_block_destroy(&block
);
11972 return(TNG_SUCCESS
);
11977 /* If for some reason the current frame set is not yet found,
11978 * take one step forward until the right frame set is found */
11979 while(file_pos
> 0 && curr_nr
< nr
)
11981 file_pos
= frame_set
->next_frame_set_file_pos
;
11985 fseek(tng_data
->input_file
,
11988 /* Read block headers first to see what block is found. */
11989 stat
= tng_block_header_read(tng_data
, block
);
11990 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
11992 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
11993 file_pos
, __FILE__
, __LINE__
);
11994 tng_block_destroy(&block
);
11995 return(TNG_CRITICAL
);
11998 if(tng_block_read_next(tng_data
, block
,
11999 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12001 tng_block_destroy(&block
);
12002 return(TNG_CRITICAL
);
12006 tng_block_destroy(&block
);
12007 return(TNG_SUCCESS
);
12012 tng_block_destroy(&block
);
12013 return(TNG_FAILURE
);
12016 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
12017 (tng_trajectory_t tng_data
,
12018 const int64_t frame
)
12020 int64_t first_frame
, last_frame
, n_frames_per_frame_set
;
12021 int64_t long_stride_length
, medium_stride_length
;
12022 int64_t file_pos
, temp_frame
, n_frames
;
12023 tng_trajectory_frame_set_t frame_set
;
12024 tng_gen_block_t block
;
12025 tng_function_status stat
;
12027 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12028 TNG_ASSERT(frame
>= 0, "TNG library: frame must be >= 0.");
12030 frame_set
= &tng_data
->current_trajectory_frame_set
;
12032 tng_block_init(&block
);
12034 if(tng_data
->current_trajectory_frame_set_input_file_pos
< 0)
12036 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
12037 fseek(tng_data
->input_file
,
12040 tng_data
->current_trajectory_frame_set_input_file_pos
= (long)file_pos
;
12041 /* Read block headers first to see what block is found. */
12042 stat
= tng_block_header_read(tng_data
, block
);
12043 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12045 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12046 file_pos
, __FILE__
, __LINE__
);
12047 tng_block_destroy(&block
);
12048 return(TNG_CRITICAL
);
12051 if(tng_block_read_next(tng_data
, block
,
12052 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12054 tng_block_destroy(&block
);
12055 return(TNG_CRITICAL
);
12059 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12060 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12061 /* Is this the right frame set? */
12062 if(first_frame
<= frame
&& frame
<= last_frame
)
12064 tng_block_destroy(&block
);
12065 return(TNG_SUCCESS
);
12068 n_frames_per_frame_set
= tng_data
->frame_set_n_frames
;
12069 long_stride_length
= tng_data
->long_stride_length
;
12070 medium_stride_length
= tng_data
->medium_stride_length
;
12072 if(tng_first_frame_nr_of_next_frame_set_get(tng_data
, &temp_frame
) ==
12075 if(temp_frame
- first_frame
> n_frames_per_frame_set
)
12077 n_frames_per_frame_set
= temp_frame
- first_frame
;
12081 tng_num_frames_get(tng_data
, &n_frames
);
12083 if(frame
>= n_frames
)
12085 tng_block_destroy(&block
);
12086 return(TNG_FAILURE
);
12089 if(first_frame
- frame
>= frame
||
12090 frame
- last_frame
>
12091 tng_data
->n_trajectory_frame_sets
* n_frames_per_frame_set
- frame
)
12093 /* Start from the beginning */
12094 if(first_frame
- frame
>= frame
)
12096 file_pos
= tng_data
->first_trajectory_frame_set_input_file_pos
;
12100 tng_block_destroy(&block
);
12101 return(TNG_FAILURE
);
12104 /* Start from the end */
12105 else if(frame
- first_frame
> (n_frames
- 1) - frame
)
12107 file_pos
= tng_data
->last_trajectory_frame_set_input_file_pos
;
12109 /* If the last frame set position is not set start from the current
12110 * frame set, since it will be closer than the first frame set. */
12112 /* Start from current */
12115 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
12120 fseek(tng_data
->input_file
,
12123 tng_data
->current_trajectory_frame_set_input_file_pos
= (long)file_pos
;
12124 /* Read block headers first to see what block is found. */
12125 stat
= tng_block_header_read(tng_data
, block
);
12126 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12128 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12129 file_pos
, __FILE__
, __LINE__
);
12130 tng_block_destroy(&block
);
12131 return(TNG_CRITICAL
);
12134 if(tng_block_read_next(tng_data
, block
,
12135 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12137 tng_block_destroy(&block
);
12138 return(TNG_CRITICAL
);
12143 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12144 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12146 if(frame
>= first_frame
&& frame
<= last_frame
)
12148 tng_block_destroy(&block
);
12149 return(TNG_SUCCESS
);
12152 file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
12154 /* Take long steps forward until a long step forward would be too long or
12155 * the right frame set is found */
12156 while(file_pos
> 0 && first_frame
+ long_stride_length
*
12157 n_frames_per_frame_set
<= frame
)
12159 file_pos
= frame_set
->long_stride_next_frame_set_file_pos
;
12162 fseek(tng_data
->input_file
, (long)file_pos
, SEEK_SET
);
12163 /* Read block headers first to see what block is found. */
12164 stat
= tng_block_header_read(tng_data
, block
);
12165 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12167 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12168 file_pos
, __FILE__
, __LINE__
);
12169 tng_block_destroy(&block
);
12170 return(TNG_CRITICAL
);
12173 if(tng_block_read_next(tng_data
, block
,
12174 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12176 tng_block_destroy(&block
);
12177 return(TNG_CRITICAL
);
12180 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12181 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12182 if(frame
>= first_frame
&& frame
<= last_frame
)
12184 tng_block_destroy(&block
);
12185 return(TNG_SUCCESS
);
12189 /* Take medium steps forward until a medium step forward would be too long
12190 * or the right frame set is found */
12191 while(file_pos
> 0 && first_frame
+ medium_stride_length
*
12192 n_frames_per_frame_set
<= frame
)
12194 file_pos
= frame_set
->medium_stride_next_frame_set_file_pos
;
12197 fseek(tng_data
->input_file
,
12200 /* Read block headers first to see what block is found. */
12201 stat
= tng_block_header_read(tng_data
, block
);
12202 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12204 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12205 file_pos
, __FILE__
, __LINE__
);
12206 tng_block_destroy(&block
);
12207 return(TNG_CRITICAL
);
12210 if(tng_block_read_next(tng_data
, block
,
12211 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12213 tng_block_destroy(&block
);
12214 return(TNG_CRITICAL
);
12217 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12218 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12219 if(frame
>= first_frame
&& frame
<= last_frame
)
12221 tng_block_destroy(&block
);
12222 return(TNG_SUCCESS
);
12226 /* Take one step forward until the right frame set is found */
12227 while(file_pos
> 0 && first_frame
< frame
&& last_frame
< frame
)
12229 file_pos
= frame_set
->next_frame_set_file_pos
;
12232 fseek(tng_data
->input_file
,
12235 /* Read block headers first to see what block is found. */
12236 stat
= tng_block_header_read(tng_data
, block
);
12237 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12239 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12240 file_pos
, __FILE__
, __LINE__
);
12241 tng_block_destroy(&block
);
12242 return(TNG_CRITICAL
);
12245 if(tng_block_read_next(tng_data
, block
,
12246 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12248 tng_block_destroy(&block
);
12249 return(TNG_CRITICAL
);
12252 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12253 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12254 if(frame
>= first_frame
&& frame
<= last_frame
)
12256 tng_block_destroy(&block
);
12257 return(TNG_SUCCESS
);
12261 /* Take long steps backward until a long step backward would be too long
12262 * or the right frame set is found */
12263 while(file_pos
> 0 && first_frame
- long_stride_length
*
12264 n_frames_per_frame_set
>= frame
)
12266 file_pos
= frame_set
->long_stride_prev_frame_set_file_pos
;
12269 fseek(tng_data
->input_file
,
12272 /* Read block headers first to see what block is found. */
12273 stat
= tng_block_header_read(tng_data
, block
);
12274 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12276 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12277 file_pos
, __FILE__
, __LINE__
);
12278 tng_block_destroy(&block
);
12279 return(TNG_CRITICAL
);
12282 if(tng_block_read_next(tng_data
, block
,
12283 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12285 tng_block_destroy(&block
);
12286 return(TNG_CRITICAL
);
12289 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12290 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12291 if(frame
>= first_frame
&& frame
<= last_frame
)
12293 tng_block_destroy(&block
);
12294 return(TNG_SUCCESS
);
12298 /* Take medium steps backward until a medium step backward would be too long
12299 * or the right frame set is found */
12300 while(file_pos
> 0 && first_frame
- medium_stride_length
*
12301 n_frames_per_frame_set
>= frame
)
12303 file_pos
= frame_set
->medium_stride_prev_frame_set_file_pos
;
12306 fseek(tng_data
->input_file
,
12309 /* Read block headers first to see what block is found. */
12310 stat
= tng_block_header_read(tng_data
, block
);
12311 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12313 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12314 file_pos
, __FILE__
, __LINE__
);
12315 tng_block_destroy(&block
);
12316 return(TNG_CRITICAL
);
12319 if(tng_block_read_next(tng_data
, block
,
12320 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12322 tng_block_destroy(&block
);
12323 return(TNG_CRITICAL
);
12326 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12327 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12328 if(frame
>= first_frame
&& frame
<= last_frame
)
12330 tng_block_destroy(&block
);
12331 return(TNG_SUCCESS
);
12335 /* Take one step backward until the right frame set is found */
12336 while(file_pos
> 0 && first_frame
> frame
&& last_frame
> frame
)
12338 file_pos
= frame_set
->prev_frame_set_file_pos
;
12341 fseek(tng_data
->input_file
,
12344 /* Read block headers first to see what block is found. */
12345 stat
= tng_block_header_read(tng_data
, block
);
12346 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12348 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12349 file_pos
, __FILE__
, __LINE__
);
12350 tng_block_destroy(&block
);
12351 return(TNG_CRITICAL
);
12354 if(tng_block_read_next(tng_data
, block
,
12355 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12357 tng_block_destroy(&block
);
12358 return(TNG_CRITICAL
);
12361 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12362 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12363 if(frame
>= first_frame
&& frame
<= last_frame
)
12365 tng_block_destroy(&block
);
12366 return(TNG_SUCCESS
);
12370 /* If for some reason the current frame set is not yet found,
12371 * take one step forward until the right frame set is found */
12372 while(file_pos
> 0 && first_frame
< frame
&& last_frame
< frame
)
12374 file_pos
= frame_set
->next_frame_set_file_pos
;
12377 fseek(tng_data
->input_file
,
12380 /* Read block headers first to see what block is found. */
12381 stat
= tng_block_header_read(tng_data
, block
);
12382 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12384 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
12385 file_pos
, __FILE__
, __LINE__
);
12386 tng_block_destroy(&block
);
12387 return(TNG_CRITICAL
);
12390 if(tng_block_read_next(tng_data
, block
,
12391 TNG_SKIP_HASH
) != TNG_SUCCESS
)
12393 tng_block_destroy(&block
);
12394 return(TNG_CRITICAL
);
12397 first_frame
= tng_max_i64(frame_set
->first_frame
, 0);
12398 last_frame
= first_frame
+ frame_set
->n_frames
- 1;
12399 if(frame
>= first_frame
&& frame
<= last_frame
)
12401 tng_block_destroy(&block
);
12402 return(TNG_SUCCESS
);
12406 tng_block_destroy(&block
);
12407 return(TNG_FAILURE
);
12410 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
12411 (const tng_trajectory_t tng_data
,
12412 const tng_trajectory_frame_set_t frame_set
,
12417 TNG_ASSERT(frame_set
, "TNG library: frame_set not initialised before accessing data.");
12418 TNG_ASSERT(pos
, "TNG library: pos must not be a NULL pointer");
12420 *pos
= frame_set
->next_frame_set_file_pos
;
12422 return(TNG_SUCCESS
);
12425 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
12426 (const tng_trajectory_t tng_data
,
12427 const tng_trajectory_frame_set_t frame_set
,
12432 TNG_ASSERT(frame_set
, "TNG library: frame_set not initialised before accessing data.");
12433 TNG_ASSERT(pos
, "TNG library: pos must not be a NULL pointer");
12435 *pos
= frame_set
->prev_frame_set_file_pos
;
12437 return(TNG_SUCCESS
);
12440 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
12441 (const tng_trajectory_t tng_data
,
12442 const tng_trajectory_frame_set_t frame_set
,
12443 int64_t *first_frame
,
12444 int64_t *last_frame
)
12448 TNG_ASSERT(first_frame
, "TNG library: first_frame must not be a NULL pointer");
12449 TNG_ASSERT(last_frame
, "TNG library: last_frame must not be a NULL pointer");
12450 TNG_ASSERT(frame_set
, "TNG library: frame_set must not be a NULL pointer");
12452 *first_frame
= frame_set
->first_frame
;
12453 *last_frame
= *first_frame
+ frame_set
->n_frames
- 1;
12455 return(TNG_SUCCESS
);
12458 /** Translate from the particle numbering used in a frame set to the real
12459 * particle numbering - used in the molecule description.
12460 * @param frame_set is the frame_set containing the mappings to use.
12461 * @param local is the index number of the atom in this frame set
12462 * @param real is set to the index of the atom in the molecular system.
12463 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12466 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
12467 (const tng_trajectory_frame_set_t frame_set
,
12468 const int64_t local
,
12471 int64_t i
, n_blocks
= frame_set
->n_mapping_blocks
, first
;
12472 tng_particle_mapping_t mapping
;
12476 return(TNG_SUCCESS
);
12478 for(i
= 0; i
< n_blocks
; i
++)
12480 mapping
= &frame_set
->mappings
[i
];
12481 first
= mapping
->num_first_particle
;
12482 if(local
< first
||
12483 local
>= first
+ mapping
->n_particles
)
12487 *real
= mapping
->real_particle_numbers
[local
-first
];
12488 return(TNG_SUCCESS
);
12491 return(TNG_FAILURE
);
12494 /** Translate from the real particle numbering to the particle numbering
12495 * used in a frame set.
12496 * @param frame_set is the frame_set containing the mappings to use.
12497 * @param real is the index number of the atom in the molecular system.
12498 * @param local is set to the index of the atom in this frame set.
12499 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
12502 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
12503 (const tng_trajectory_frame_set_t frame_set,
12504 const int64_t real,
12507 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12508 tng_particle_mapping_t mapping;
12512 return(TNG_SUCCESS);
12514 for(i = 0; i < n_blocks; i++)
12516 mapping = &frame_set->mappings[i];
12517 for(j = mapping->n_particles; j--;)
12519 if(mapping->real_particle_numbers[j] == real)
12522 return(TNG_SUCCESS);
12526 return(TNG_FAILURE);
12530 static tng_function_status tng_file_headers_len_get
12531 (tng_trajectory_t tng_data
,
12535 tng_gen_block_t block
;
12537 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12539 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12541 return(TNG_CRITICAL
);
12546 orig_pos
= ftell(tng_data
->input_file
);
12548 if(!tng_data
->input_file_len
)
12550 fseek(tng_data
->input_file
, 0, SEEK_END
);
12551 tng_data
->input_file_len
= ftell(tng_data
->input_file
);
12553 fseek(tng_data
->input_file
, 0, SEEK_SET
);
12555 tng_block_init(&block
);
12556 /* Read through the headers of non-trajectory blocks (they come before the
12557 * trajectory blocks in the file) */
12558 while (*len
< tng_data
->input_file_len
&&
12559 tng_block_header_read(tng_data
, block
) != TNG_CRITICAL
&&
12561 block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12563 *len
+= block
->header_contents_size
+ block
->block_contents_size
;
12564 fseek(tng_data
->input_file
, block
->block_contents_size
, SEEK_CUR
);
12567 fseek(tng_data
->input_file
, orig_pos
, SEEK_SET
);
12569 tng_block_destroy(&block
);
12571 return(TNG_SUCCESS
);
12574 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
12575 (tng_trajectory_t tng_data
,
12576 const char hash_mode
)
12578 int64_t prev_pos
= 0;
12579 tng_gen_block_t block
;
12581 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12583 tng_data
->n_trajectory_frame_sets
= 0;
12585 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12587 return(TNG_CRITICAL
);
12590 if(!tng_data
->input_file_len
)
12592 fseek(tng_data
->input_file
, 0, SEEK_END
);
12593 tng_data
->input_file_len
= ftell(tng_data
->input_file
);
12595 fseek(tng_data
->input_file
, 0, SEEK_SET
);
12597 tng_block_init(&block
);
12598 /* Non trajectory blocks (they come before the trajectory
12599 * blocks in the file) */
12600 while (prev_pos
< tng_data
->input_file_len
&&
12601 tng_block_header_read(tng_data
, block
) != TNG_CRITICAL
&&
12603 block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12605 tng_block_read_next(tng_data
, block
, hash_mode
);
12606 prev_pos
= ftell(tng_data
->input_file
);
12609 /* Go back if a trajectory block was encountered */
12610 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
12612 fseek(tng_data
->input_file
, prev_pos
, SEEK_SET
);
12615 tng_block_destroy(&block
);
12617 return(TNG_SUCCESS
);
12620 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
12621 (tng_trajectory_t tng_data
,
12622 const char hash_mode
)
12625 int64_t len
, orig_len
, tot_len
= 0, data_start_pos
;
12626 tng_function_status stat
;
12627 tng_gen_block_t block
;
12629 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12631 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
12633 return(TNG_CRITICAL
);
12636 if(tng_data
->n_trajectory_frame_sets
> 0)
12638 stat
= tng_file_headers_len_get(tng_data
, &orig_len
);
12639 if(stat
!= TNG_SUCCESS
)
12644 tng_block_init(&block
);
12645 block
->name
= malloc(TNG_MAX_STR_LEN
);
12648 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12649 TNG_MAX_STR_LEN
, __FILE__
, __LINE__
);
12650 tng_block_destroy(&block
);
12651 return(TNG_CRITICAL
);
12653 strcpy(block
->name
, "GENERAL INFO");
12654 tng_block_header_len_calculate(tng_data
, block
, &len
);
12656 tng_general_info_block_len_calculate(tng_data
, &len
);
12658 strcpy(block
->name
, "MOLECULES");
12659 tng_block_header_len_calculate(tng_data
, block
, &len
);
12661 tng_molecules_block_len_calculate(tng_data
, &len
);
12664 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
12666 strcpy(block
->name
, tng_data
->non_tr_data
[i
].block_name
);
12667 tng_block_header_len_calculate(tng_data
, block
, &len
);
12669 tng_data_block_len_calculate(tng_data
,
12670 (tng_particle_data_t
)&tng_data
->non_tr_data
[i
],
12671 TNG_FALSE
, 1, 1, 1, 0,
12672 1, 0, &data_start_pos
,
12676 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
12678 strcpy(block
->name
, tng_data
->non_tr_particle_data
[i
].block_name
);
12679 tng_block_header_len_calculate(tng_data
, block
, &len
);
12681 tng_data_block_len_calculate(tng_data
,
12682 &tng_data
->non_tr_particle_data
[i
],
12683 TNG_TRUE
, 1, 1, 1, 0,
12684 tng_data
->n_particles
, TNG_PARTICLE_DEPENDENT
,
12689 tng_block_destroy(&block
);
12691 if(tot_len
> orig_len
)
12693 tng_migrate_data_in_file(tng_data
, orig_len
+1, tot_len
- orig_len
);
12696 tng_data
->current_trajectory_frame_set_output_file_pos
= -1;
12699 /* TODO: If there is already frame set data written to this file (e.g. when
12700 * appending to an already existing file we might need to move frame sets to
12701 * the end of the file. */
12703 if(tng_general_info_block_write(tng_data
, hash_mode
)
12706 fprintf(stderr
, "TNG library: Error writing general info block of file %s. %s: %d\n",
12707 tng_data
->input_file_path
, __FILE__
, __LINE__
);
12708 return(TNG_CRITICAL
);
12711 if(tng_molecules_block_write(tng_data
, hash_mode
)
12714 fprintf(stderr
, "TNG library: Error writing atom names block of file %s. %s: %d\n",
12715 tng_data
->input_file_path
, __FILE__
, __LINE__
);
12716 return(TNG_CRITICAL
);
12719 /* FIXME: Currently writing non-trajectory data blocks here.
12720 * Should perhaps be moved. */
12721 tng_block_init(&block
);
12722 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
12724 block
->id
= tng_data
->non_tr_data
[i
].block_id
;
12725 tng_data_block_write(tng_data
, block
,
12729 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
12731 block
->id
= tng_data
->non_tr_particle_data
[i
].block_id
;
12732 tng_particle_data_block_write(tng_data
, block
,
12736 tng_block_destroy(&block
);
12738 return(TNG_SUCCESS
);
12741 tng_function_status DECLSPECDLLEXPORT
tng_block_read_next(tng_trajectory_t tng_data
,
12742 tng_gen_block_t block
,
12743 const char hash_mode
)
12745 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12746 TNG_ASSERT(block
, "TNG library: block must be initialised and must not be a NULL pointer.");
12750 case TNG_TRAJECTORY_FRAME_SET
:
12751 return(tng_frame_set_block_read(tng_data
, block
, hash_mode
));
12752 case TNG_PARTICLE_MAPPING
:
12753 return(tng_trajectory_mapping_block_read(tng_data
, block
, hash_mode
));
12754 case TNG_GENERAL_INFO
:
12755 return(tng_general_info_block_read(tng_data
, block
, hash_mode
));
12756 case TNG_MOLECULES
:
12757 return(tng_molecules_block_read(tng_data
, block
, hash_mode
));
12759 if(block
->id
>= TNG_TRAJ_BOX_SHAPE
)
12761 return(tng_data_block_contents_read(tng_data
, block
, hash_mode
));
12765 /* Skip to the next block */
12766 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
12767 return(TNG_FAILURE
);
12772 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
12773 (tng_trajectory_t tng_data
,
12774 const char hash_mode
)
12777 tng_gen_block_t block
;
12778 tng_function_status stat
;
12780 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12782 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12784 return(TNG_CRITICAL
);
12787 file_pos
= ftell(tng_data
->input_file
);
12789 tng_block_init(&block
);
12791 if(!tng_data
->input_file_len
)
12793 fseek(tng_data
->input_file
, 0, SEEK_END
);
12794 tng_data
->input_file_len
= ftell(tng_data
->input_file
);
12795 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
12798 /* Read block headers first to see what block is found. */
12799 stat
= tng_block_header_read(tng_data
, block
);
12800 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
||
12803 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12804 file_pos
, __FILE__
, __LINE__
);
12805 tng_block_destroy(&block
);
12806 return(TNG_CRITICAL
);
12809 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
12811 if(tng_block_read_next(tng_data
, block
,
12812 hash_mode
) == TNG_SUCCESS
)
12814 tng_data
->n_trajectory_frame_sets
++;
12815 file_pos
= ftell(tng_data
->input_file
);
12816 /* Read all blocks until next frame set block */
12817 stat
= tng_block_header_read(tng_data
, block
);
12818 while(file_pos
< tng_data
->input_file_len
&&
12819 stat
!= TNG_CRITICAL
&&
12820 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
12823 stat
= tng_block_read_next(tng_data
, block
,
12825 if(stat
!= TNG_CRITICAL
)
12827 file_pos
= ftell(tng_data
->input_file
);
12828 if(file_pos
< tng_data
->input_file_len
)
12830 stat
= tng_block_header_read(tng_data
, block
);
12834 if(stat
== TNG_CRITICAL
)
12836 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12837 file_pos
, __FILE__
, __LINE__
);
12838 tng_block_destroy(&block
);
12842 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
12844 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
12848 tng_block_destroy(&block
);
12850 return(TNG_SUCCESS
);
12854 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
12855 (tng_trajectory_t tng_data
,
12856 const char hash_mode
,
12857 const int64_t block_id
)
12860 tng_gen_block_t block
;
12861 tng_function_status stat
;
12862 int found_flag
= 1;
12864 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12866 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12868 return(TNG_CRITICAL
);
12871 file_pos
= (long)tng_data
->current_trajectory_frame_set_input_file_pos
;
12875 /* No current frame set. This means that the first frame set must be
12878 file_pos
= (long)tng_data
->first_trajectory_frame_set_input_file_pos
;
12883 fseek(tng_data
->input_file
,
12889 return(TNG_FAILURE
);
12892 tng_block_init(&block
);
12894 if(!tng_data
->input_file_len
)
12896 fseek(tng_data
->input_file
, 0, SEEK_END
);
12897 tng_data
->input_file_len
= ftell(tng_data
->input_file
);
12898 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
12901 /* Read block headers first to see what block is found. */
12902 stat
= tng_block_header_read(tng_data
, block
);
12903 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
12905 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12906 file_pos
, __FILE__
, __LINE__
);
12907 tng_block_destroy(&block
);
12908 return(TNG_CRITICAL
);
12910 /* If the current frame set had already been read skip its block contents */
12913 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
12915 /* Otherwiese read the frame set block */
12918 stat
= tng_block_read_next(tng_data
, block
,
12920 if(stat
!= TNG_SUCCESS
)
12922 fprintf(stderr
, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__
, __LINE__
);
12923 tng_block_destroy(&block
);
12927 file_pos
= ftell(tng_data
->input_file
);
12931 /* Read only blocks of the requested ID
12932 * until next frame set block */
12933 stat
= tng_block_header_read(tng_data
, block
);
12934 while(file_pos
< tng_data
->input_file_len
&&
12935 stat
!= TNG_CRITICAL
&&
12936 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
12939 if(block
->id
== block_id
)
12941 stat
= tng_block_read_next(tng_data
, block
,
12943 if(stat
!= TNG_CRITICAL
)
12945 file_pos
= ftell(tng_data
->input_file
);
12947 if(file_pos
< tng_data
->input_file_len
)
12949 stat
= tng_block_header_read(tng_data
, block
);
12955 file_pos
+= (long)(block
->block_contents_size
+ block
->header_contents_size
);
12956 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
12957 if(file_pos
< tng_data
->input_file_len
)
12959 stat
= tng_block_header_read(tng_data
, block
);
12963 if(stat
== TNG_CRITICAL
)
12965 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
12966 file_pos
, __FILE__
, __LINE__
);
12967 tng_block_destroy(&block
);
12971 if(block
->id
== TNG_TRAJECTORY_FRAME_SET
)
12973 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
12976 tng_block_destroy(&block
);
12980 return(TNG_SUCCESS
);
12984 return(TNG_FAILURE
);
12988 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12989 (tng_trajectory_t tng_data
,
12990 const char hash_mode
)
12994 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
12996 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
12998 return(TNG_CRITICAL
);
13001 file_pos
= (long)tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
;
13003 if(file_pos
< 0 && tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
13005 file_pos
= (long)tng_data
->first_trajectory_frame_set_input_file_pos
;
13010 fseek(tng_data
->input_file
,
13016 return(TNG_FAILURE
);
13019 return(tng_frame_set_read(tng_data
, hash_mode
));
13022 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
13023 (tng_trajectory_t tng_data
,
13024 const char hash_mode
,
13025 const int64_t block_id
)
13028 tng_gen_block_t block
;
13029 tng_function_status stat
;
13031 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13033 if(tng_input_file_init(tng_data
) != TNG_SUCCESS
)
13035 return(TNG_CRITICAL
);
13038 file_pos
= (long)tng_data
->current_trajectory_frame_set
.next_frame_set_file_pos
;
13040 if(file_pos
< 0 && tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
13042 file_pos
= (long)tng_data
->first_trajectory_frame_set_input_file_pos
;
13047 fseek(tng_data
->input_file
,
13053 return(TNG_FAILURE
);
13056 tng_block_init(&block
);
13058 if(!tng_data
->input_file_len
)
13060 fseek(tng_data
->input_file
, 0, SEEK_END
);
13061 tng_data
->input_file_len
= ftell(tng_data
->input_file
);
13062 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
13065 /* Read block headers first to see what block is found. */
13066 stat
= tng_block_header_read(tng_data
, block
);
13067 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
13069 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13070 file_pos
, __FILE__
, __LINE__
);
13071 tng_block_destroy(&block
);
13072 return(TNG_CRITICAL
);
13075 tng_data
->current_trajectory_frame_set_input_file_pos
= file_pos
;
13077 if(tng_block_read_next(tng_data
, block
,
13078 hash_mode
) == TNG_SUCCESS
)
13080 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, hash_mode
, block_id
);
13083 tng_block_destroy(&block
);
13088 tng_function_status
tng_frame_set_write(tng_trajectory_t tng_data
,
13089 const char hash_mode
)
13092 tng_gen_block_t block
;
13093 tng_trajectory_frame_set_t frame_set
;
13094 tng_function_status stat
;
13096 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13098 frame_set
= &tng_data
->current_trajectory_frame_set
;
13100 if(frame_set
->n_written_frames
== frame_set
->n_frames
)
13102 return(TNG_SUCCESS
);
13105 tng_data
->current_trajectory_frame_set_output_file_pos
=
13106 ftell(tng_data
->output_file
);
13107 tng_data
->last_trajectory_frame_set_output_file_pos
=
13108 tng_data
->current_trajectory_frame_set_output_file_pos
;
13110 if(tng_data
->current_trajectory_frame_set_output_file_pos
<= 0)
13112 return(TNG_FAILURE
);
13115 if(tng_data
->first_trajectory_frame_set_output_file_pos
== -1)
13117 tng_data
->first_trajectory_frame_set_output_file_pos
=
13118 tng_data
->current_trajectory_frame_set_output_file_pos
;
13121 tng_block_init(&block
);
13123 if(tng_frame_set_block_write(tng_data
, block
, hash_mode
) != TNG_SUCCESS
)
13125 tng_block_destroy(&block
);
13126 return(TNG_FAILURE
);
13129 /* Write non-particle data blocks */
13130 for(i
= 0; i
<frame_set
->n_data_blocks
; i
++)
13132 block
->id
= frame_set
->tr_data
[i
].block_id
;
13133 tng_data_block_write(tng_data
, block
, i
, hash_mode
);
13135 /* Write the mapping blocks and particle data blocks*/
13136 if(frame_set
->n_mapping_blocks
)
13138 for(i
= 0; i
< frame_set
->n_mapping_blocks
; i
++)
13140 block
->id
= TNG_PARTICLE_MAPPING
;
13141 if(frame_set
->mappings
[i
].n_particles
> 0)
13143 tng_trajectory_mapping_block_write(tng_data
, block
, i
, hash_mode
);
13144 for(j
= 0; j
<frame_set
->n_particle_data_blocks
; j
++)
13146 block
->id
= frame_set
->tr_particle_data
[j
].block_id
;
13147 tng_particle_data_block_write(tng_data
, block
,
13148 j
, &frame_set
->mappings
[i
],
13156 for(i
= 0; i
<frame_set
->n_particle_data_blocks
; i
++)
13158 block
->id
= frame_set
->tr_particle_data
[i
].block_id
;
13159 tng_particle_data_block_write(tng_data
, block
,
13165 /* Update pointers in the general info block */
13166 stat
= tng_header_pointers_update(tng_data
, hash_mode
);
13168 if(stat
== TNG_SUCCESS
)
13170 stat
= tng_frame_set_pointers_update(tng_data
, hash_mode
);
13173 tng_block_destroy(&block
);
13175 frame_set
->n_unwritten_frames
= 0;
13177 fflush(tng_data
->output_file
);
13182 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
13183 (tng_trajectory_t tng_data
,
13184 const char hash_mode
)
13186 tng_trajectory_frame_set_t frame_set
;
13188 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13190 frame_set
= &tng_data
->current_trajectory_frame_set
;
13192 if(frame_set
->n_unwritten_frames
== 0)
13194 return(TNG_SUCCESS
);
13196 frame_set
->n_frames
= frame_set
->n_unwritten_frames
;
13198 return(tng_frame_set_write(tng_data
, hash_mode
));
13201 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
13202 (tng_trajectory_t tng_data
,
13203 const int64_t first_frame
,
13204 const int64_t n_frames
)
13206 tng_gen_block_t block
;
13207 tng_trajectory_frame_set_t frame_set
;
13208 FILE *temp
= tng_data
->input_file
;
13211 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13212 TNG_ASSERT(first_frame
>= 0, "TNG library: first_frame must be >= 0.");
13213 TNG_ASSERT(n_frames
>= 0, "TNG library: n_frames must be >= 0.");
13215 frame_set
= &tng_data
->current_trajectory_frame_set
;
13217 curr_pos
= ftell(tng_data
->output_file
);
13221 tng_file_headers_write(tng_data
, TNG_USE_HASH
);
13224 /* Set pointer to previous frame set to the one that was loaded
13226 * FIXME: This is a bit risky. If they are not added in order
13227 * it will be wrong. */
13228 if(tng_data
->n_trajectory_frame_sets
)
13230 frame_set
->prev_frame_set_file_pos
=
13231 tng_data
->current_trajectory_frame_set_output_file_pos
;
13234 tng_data
->current_trajectory_frame_set_output_file_pos
=
13235 ftell(tng_data
->output_file
);
13237 tng_data
->n_trajectory_frame_sets
++;
13239 /* Set the medium range pointers */
13240 if(tng_data
->n_trajectory_frame_sets
== tng_data
->medium_stride_length
+ 1)
13242 frame_set
->medium_stride_prev_frame_set_file_pos
=
13243 tng_data
->first_trajectory_frame_set_output_file_pos
;
13245 else if(tng_data
->n_trajectory_frame_sets
> tng_data
->medium_stride_length
+ 1)
13247 /* FIXME: Currently only working if the previous frame set has its
13248 * medium stride pointer already set. This might need some fixing. */
13249 if(frame_set
->medium_stride_prev_frame_set_file_pos
!= -1 &&
13250 frame_set
->medium_stride_prev_frame_set_file_pos
!= 0)
13252 tng_block_init(&block
);
13253 tng_data
->input_file
= tng_data
->output_file
;
13255 curr_pos
= ftell(tng_data
->output_file
);
13256 fseek(tng_data
->output_file
,
13257 (long)frame_set
->medium_stride_prev_frame_set_file_pos
,
13260 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
13262 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
13263 __FILE__
, __LINE__
);
13264 tng_data
->input_file
= temp
;
13265 tng_block_destroy(&block
);
13266 return(TNG_CRITICAL
);
13269 /* Read the next frame set from the previous frame set and one
13270 * medium stride step back */
13271 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (6 *
13272 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
13273 if(fread(&frame_set
->medium_stride_prev_frame_set_file_pos
,
13274 sizeof(frame_set
->medium_stride_prev_frame_set_file_pos
),
13275 1, tng_data
->output_file
) == 0)
13277 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
13278 tng_data
->input_file
= temp
;
13279 tng_block_destroy(&block
);
13280 return(TNG_CRITICAL
);
13283 if(tng_data
->input_endianness_swap_func_64
)
13285 if(tng_data
->input_endianness_swap_func_64(tng_data
,
13286 &frame_set
->medium_stride_prev_frame_set_file_pos
)
13289 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
13290 __FILE__
, __LINE__
);
13294 tng_block_destroy(&block
);
13296 /* Set the long range pointers */
13297 if(tng_data
->n_trajectory_frame_sets
== tng_data
->long_stride_length
+ 1)
13299 frame_set
->long_stride_prev_frame_set_file_pos
=
13300 tng_data
->first_trajectory_frame_set_output_file_pos
;
13302 else if(tng_data
->n_trajectory_frame_sets
> tng_data
->medium_stride_length
+ 1)
13304 /* FIXME: Currently only working if the previous frame set has its
13305 * long stride pointer already set. This might need some fixing. */
13306 if(frame_set
->long_stride_prev_frame_set_file_pos
!= -1 &&
13307 frame_set
->long_stride_prev_frame_set_file_pos
!= 0)
13309 tng_block_init(&block
);
13310 tng_data
->input_file
= tng_data
->output_file
;
13312 fseek(tng_data
->output_file
,
13313 (long)frame_set
->long_stride_prev_frame_set_file_pos
,
13316 if(tng_block_header_read(tng_data
, block
) != TNG_SUCCESS
)
13318 fprintf(stderr
, "TNG library: Cannot read frame set header. %s: %d\n",
13319 __FILE__
, __LINE__
);
13320 tng_data
->input_file
= temp
;
13321 tng_block_destroy(&block
);
13322 return(TNG_CRITICAL
);
13325 /* Read the next frame set from the previous frame set and one
13326 * long stride step back */
13327 fseek(tng_data
->output_file
, (long)block
->block_contents_size
- (6 *
13328 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR
);
13330 tng_block_destroy(&block
);
13332 if(fread(&frame_set
->long_stride_prev_frame_set_file_pos
,
13333 sizeof(frame_set
->long_stride_prev_frame_set_file_pos
),
13334 1, tng_data
->output_file
) == 0)
13336 fprintf(stderr
, "TNG library: Cannot read block. %s: %d\n", __FILE__
, __LINE__
);
13337 tng_data
->input_file
= temp
;
13338 return(TNG_CRITICAL
);
13341 if(tng_data
->input_endianness_swap_func_64
)
13343 if(tng_data
->input_endianness_swap_func_64(tng_data
,
13344 &frame_set
->long_stride_prev_frame_set_file_pos
)
13347 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
13348 __FILE__
, __LINE__
);
13355 tng_data
->input_file
= temp
;
13356 fseek(tng_data
->output_file
, (long)curr_pos
, SEEK_SET
);
13360 frame_set
->first_frame
= first_frame
;
13361 frame_set
->n_frames
= n_frames
;
13362 frame_set
->n_written_frames
= 0;
13363 frame_set
->n_unwritten_frames
= 0;
13364 frame_set
->first_frame_time
= -1;
13366 if(tng_data
->first_trajectory_frame_set_output_file_pos
== -1 ||
13367 tng_data
->first_trajectory_frame_set_output_file_pos
== 0)
13369 tng_data
->first_trajectory_frame_set_output_file_pos
=
13370 tng_data
->current_trajectory_frame_set_output_file_pos
;
13372 /* FIXME: Should check the frame number instead of the file_pos,
13373 * in case frame sets are not in order */
13374 if(tng_data
->last_trajectory_frame_set_output_file_pos
== -1 ||
13375 tng_data
->last_trajectory_frame_set_output_file_pos
== 0 ||
13376 tng_data
->last_trajectory_frame_set_output_file_pos
<
13377 tng_data
->current_trajectory_frame_set_output_file_pos
)
13379 tng_data
->last_trajectory_frame_set_output_file_pos
=
13380 tng_data
->current_trajectory_frame_set_output_file_pos
;
13383 return(TNG_SUCCESS
);
13386 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
13387 (tng_trajectory_t tng_data
,
13388 const int64_t first_frame
,
13389 const int64_t n_frames
,
13390 const double first_frame_time
)
13392 tng_function_status stat
;
13394 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13395 TNG_ASSERT(first_frame
>= 0, "TNG library: first_frame must be >= 0.");
13396 TNG_ASSERT(n_frames
>= 0, "TNG library: n_frames must be >= 0.");
13397 TNG_ASSERT(first_frame_time
>= 0, "TNG library: first_frame_time must be >= 0.");
13400 stat
= tng_frame_set_new(tng_data
, first_frame
, n_frames
);
13401 if(stat
!= TNG_SUCCESS
)
13405 stat
= tng_frame_set_first_frame_time_set(tng_data
, first_frame_time
);
13410 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
13411 (tng_trajectory_t tng_data
,
13412 const double first_frame_time
)
13414 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13415 TNG_ASSERT(first_frame_time
>= 0, "TNG library: first_frame_time must be >= 0.");
13417 tng_data
->current_trajectory_frame_set
.first_frame_time
= first_frame_time
;
13419 return(TNG_SUCCESS
);
13422 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
13423 (const tng_trajectory_t tng_data
,
13426 long file_pos
, next_frame_set_file_pos
;
13427 tng_gen_block_t block
;
13428 tng_function_status stat
;
13430 tng_trajectory_frame_set_t frame_set
;
13432 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13433 TNG_ASSERT(tng_data
->input_file
, "TNG library: An input file must be open to find the next frame set");
13434 TNG_ASSERT(frame
, "TNG library: frame must not be a NULL pointer");
13436 file_pos
= ftell(tng_data
->input_file
);
13438 if(tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
13440 next_frame_set_file_pos
= (long)tng_data
->first_trajectory_frame_set_input_file_pos
;
13444 frame_set
= &tng_data
->current_trajectory_frame_set
;
13445 next_frame_set_file_pos
= (long)frame_set
->next_frame_set_file_pos
;
13448 if(next_frame_set_file_pos
<= 0)
13450 return(TNG_FAILURE
);
13453 fseek(tng_data
->input_file
, (long)next_frame_set_file_pos
, SEEK_SET
);
13454 /* Read block headers first to see that a frame set block is found. */
13455 tng_block_init(&block
);
13456 stat
= tng_block_header_read(tng_data
, block
);
13457 if(stat
== TNG_CRITICAL
|| block
->id
!= TNG_TRAJECTORY_FRAME_SET
)
13459 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
13460 file_pos
, __FILE__
, __LINE__
);
13461 return(TNG_CRITICAL
);
13463 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
13465 tng_block_read_next(tng_data, block, TNG_USE_HASH);
13467 tng_block_destroy(&block
);
13469 if(fread(frame
, sizeof(int64_t), 1, tng_data
->input_file
) == 0)
13471 fprintf(stderr
, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
13472 __FILE__
, __LINE__
);
13473 return(TNG_CRITICAL
);
13475 fseek(tng_data
->input_file
, file_pos
, SEEK_SET
);
13477 return(TNG_SUCCESS
);
13480 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
13481 (tng_trajectory_t tng_data
,
13483 const char *block_name
,
13484 const char datatype
,
13485 const char block_type_flag
,
13487 const int64_t n_values_per_frame
,
13488 int64_t stride_length
,
13489 const int64_t codec_id
,
13492 int i
, j
, size
, len
;
13493 tng_trajectory_frame_set_t frame_set
;
13494 tng_non_particle_data_t data
;
13495 char **first_dim_values
;
13496 char *new_data_c
=new_data
;
13497 int64_t n_frames_div
;
13499 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13500 TNG_ASSERT(block_name
, "TNG library: block_name must not be a NULL pointer.");
13501 TNG_ASSERT(n_values_per_frame
> 0, "TNG library: n_values_per_frame must be a positive integer.");
13503 frame_set
= &tng_data
->current_trajectory_frame_set
;
13505 if(stride_length
<= 0)
13510 /* If the block does not exist, create it */
13511 if(tng_data_find(tng_data
, id
, &data
) != TNG_SUCCESS
)
13513 if(tng_data_block_create(tng_data
, block_type_flag
) !=
13516 fprintf(stderr
, "TNG library: Cannot create data block. %s: %d\n",
13517 __FILE__
, __LINE__
);
13518 return(TNG_CRITICAL
);
13520 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
13522 data
= &frame_set
->tr_data
[frame_set
->n_data_blocks
- 1];
13526 data
= &tng_data
->non_tr_data
[tng_data
->n_data_blocks
- 1];
13528 data
->block_id
= id
;
13530 data
->block_name
= malloc(strlen(block_name
) + 1);
13531 if(!data
->block_name
)
13533 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13534 (int)strlen(block_name
)+1, __FILE__
, __LINE__
);
13535 return(TNG_CRITICAL
);
13537 strncpy(data
->block_name
, block_name
, strlen(block_name
) + 1);
13540 /* FIXME: Memory leak from strings. */
13542 data
->last_retrieved_frame
= -1;
13545 data
->datatype
= datatype
;
13546 data
->stride_length
= tng_max_i64(stride_length
, 1);
13547 data
->n_values_per_frame
= n_values_per_frame
;
13548 data
->n_frames
= n_frames
;
13549 data
->codec_id
= codec_id
;
13550 data
->compression_multiplier
= 1.0;
13551 /* FIXME: This can cause problems. */
13552 data
->first_frame_with_data
= frame_set
->first_frame
;
13556 case TNG_FLOAT_DATA
:
13557 size
= sizeof(float);
13560 size
= sizeof(int64_t);
13562 case TNG_DOUBLE_DATA
:
13564 size
= sizeof(double);
13570 /* Allocate memory */
13571 if(tng_allocate_data_mem(tng_data
, data
, n_frames
, stride_length
,
13572 n_values_per_frame
) !=
13575 fprintf(stderr
, "TNG library: Cannot allocate data memory. %s: %d\n",
13576 __FILE__
, __LINE__
);
13577 return(TNG_CRITICAL
);
13580 if(n_frames
> frame_set
->n_unwritten_frames
)
13582 frame_set
->n_unwritten_frames
= n_frames
;
13585 n_frames_div
= (n_frames
% stride_length
) ?
13586 n_frames
/ stride_length
+ 1:
13587 n_frames
/ stride_length
;
13589 if(datatype
== TNG_CHAR_DATA
)
13591 for(i
= 0; i
< n_frames_div
; i
++)
13593 first_dim_values
= data
->strings
[i
];
13594 for(j
= 0; j
< n_values_per_frame
; j
++)
13596 len
= tng_min_i((int)strlen(new_data_c
) + 1,
13598 if(first_dim_values
[j
])
13600 free(first_dim_values
[j
]);
13602 first_dim_values
[j
] = malloc(len
);
13603 if(!first_dim_values
[j
])
13605 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13606 len
, __FILE__
, __LINE__
);
13607 return(TNG_CRITICAL
);
13609 strncpy(first_dim_values
[j
],
13617 memcpy(data
->values
, new_data
, size
* n_frames_div
*
13618 n_values_per_frame
);
13622 return(TNG_SUCCESS
);
13625 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
13626 (tng_trajectory_t tng_data
,
13628 const char *block_name
,
13629 const char datatype
,
13630 const char block_type_flag
,
13632 const int64_t n_values_per_frame
,
13633 int64_t stride_length
,
13634 const int64_t num_first_particle
,
13635 const int64_t n_particles
,
13636 const int64_t codec_id
,
13641 int64_t tot_n_particles
, n_frames_div
;
13642 char ***first_dim_values
, **second_dim_values
;
13643 tng_trajectory_frame_set_t frame_set
;
13644 tng_particle_data_t data
;
13645 char *new_data_c
=new_data
;
13647 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13648 TNG_ASSERT(block_name
, "TNG library: block_name mustnot be a NULL pointer.");
13649 TNG_ASSERT(n_values_per_frame
> 0, "TNG library: n_values_per_frame must be a positive integer.");
13650 TNG_ASSERT(num_first_particle
>= 0, "TNG library: num_first_particle must be >= 0.");
13651 TNG_ASSERT(n_particles
>= 0, "TNG library: n_particles must be >= 0.");
13654 frame_set
= &tng_data
->current_trajectory_frame_set
;
13656 if(stride_length
<= 0)
13661 /* If the block does not exist, create it */
13662 if(tng_particle_data_find(tng_data
, id
, &data
) != TNG_SUCCESS
)
13664 if(tng_particle_data_block_create(tng_data
, block_type_flag
) !=
13667 fprintf(stderr
, "TNG library: Cannot create particle data block. %s: %d\n",
13668 __FILE__
, __LINE__
);
13669 return(TNG_CRITICAL
);
13671 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
13673 data
= &frame_set
->tr_particle_data
[frame_set
->
13674 n_particle_data_blocks
- 1];
13678 data
= &tng_data
->non_tr_particle_data
[tng_data
->
13679 n_particle_data_blocks
- 1];
13681 data
->block_id
= id
;
13683 data
->block_name
= malloc(strlen(block_name
) + 1);
13684 if(!data
->block_name
)
13686 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13687 (int)strlen(block_name
)+1, __FILE__
, __LINE__
);
13688 return(TNG_CRITICAL
);
13690 strncpy(data
->block_name
, block_name
, strlen(block_name
) + 1);
13692 data
->datatype
= datatype
;
13695 /* FIXME: Memory leak from strings. */
13697 data
->last_retrieved_frame
= -1;
13700 data
->stride_length
= tng_max_i64(stride_length
, 1);
13701 data
->n_values_per_frame
= n_values_per_frame
;
13702 data
->n_frames
= n_frames
;
13703 data
->codec_id
= codec_id
;
13704 data
->compression_multiplier
= 1.0;
13705 /* FIXME: This can cause problems. */
13706 data
->first_frame_with_data
= frame_set
->first_frame
;
13708 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&& tng_data
->var_num_atoms_flag
)
13710 tot_n_particles
= frame_set
->n_particles
;
13714 tot_n_particles
= tng_data
->n_particles
;
13717 /* If data values are supplied add that data to the data block. */
13720 /* Allocate memory */
13721 if(tng_allocate_particle_data_mem(tng_data
, data
, n_frames
,
13722 stride_length
, tot_n_particles
,
13723 n_values_per_frame
) !=
13726 fprintf(stderr
, "TNG library: Cannot allocate particle data memory. %s: %d\n",
13727 __FILE__
, __LINE__
);
13728 return(TNG_CRITICAL
);
13731 if(n_frames
> frame_set
->n_unwritten_frames
)
13733 frame_set
->n_unwritten_frames
= n_frames
;
13736 n_frames_div
= (n_frames
% stride_length
) ?
13737 n_frames
/ stride_length
+ 1:
13738 n_frames
/ stride_length
;
13740 if(datatype
== TNG_CHAR_DATA
)
13742 for(i
= 0; i
< n_frames_div
; i
++)
13744 first_dim_values
= data
->strings
[i
];
13745 for(j
= num_first_particle
; j
< num_first_particle
+ n_particles
;
13748 second_dim_values
= first_dim_values
[j
];
13749 for(k
= 0; k
< n_values_per_frame
; k
++)
13751 len
= tng_min_i((int)strlen(new_data_c
) + 1,
13753 if(second_dim_values
[k
])
13755 free(second_dim_values
[k
]);
13757 second_dim_values
[k
] = malloc(len
);
13758 if(!second_dim_values
[k
])
13760 fprintf(stderr
, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
13761 len
, __FILE__
, __LINE__
);
13762 return(TNG_CRITICAL
);
13764 strncpy(second_dim_values
[k
],
13776 size
= sizeof(int64_t);
13778 case TNG_FLOAT_DATA
:
13779 size
= sizeof(float);
13781 case TNG_DOUBLE_DATA
:
13783 size
= sizeof(double);
13786 memcpy(data
->values
, new_data
, size
* n_frames_div
*
13787 n_particles
* n_values_per_frame
);
13791 return(TNG_SUCCESS
);
13794 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
13795 (tng_trajectory_t tng_data
,
13801 tng_trajectory_frame_set_t frame_set
;
13802 tng_function_status stat
;
13803 tng_particle_data_t p_data
;
13804 tng_non_particle_data_t np_data
;
13805 int block_type
= -1;
13807 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13808 TNG_ASSERT(name
, "TNG library: name must not be a NULL pointer.");
13810 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
13812 p_data
= &tng_data
->non_tr_particle_data
[i
];
13813 if(p_data
->block_id
== block_id
)
13815 strncpy(name
, p_data
->block_name
, max_len
);
13816 name
[max_len
- 1] = '\0';
13817 return(TNG_SUCCESS
);
13820 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
13822 np_data
= &tng_data
->non_tr_data
[i
];
13823 if(np_data
->block_id
== block_id
)
13825 strncpy(name
, np_data
->block_name
, max_len
);
13826 name
[max_len
- 1] = '\0';
13827 return(TNG_SUCCESS
);
13831 frame_set
= &tng_data
->current_trajectory_frame_set
;
13833 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
13834 if(stat
== TNG_SUCCESS
)
13836 block_type
= TNG_PARTICLE_BLOCK_DATA
;
13840 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
13841 if(stat
== TNG_SUCCESS
)
13843 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
13847 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
13848 if(stat
!= TNG_SUCCESS
)
13852 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
13853 if(stat
== TNG_SUCCESS
)
13855 block_type
= TNG_PARTICLE_BLOCK_DATA
;
13859 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
13860 if(stat
== TNG_SUCCESS
)
13862 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
13867 if(block_type
== TNG_PARTICLE_BLOCK_DATA
)
13869 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
13871 p_data
= &frame_set
->tr_particle_data
[i
];
13872 if(p_data
->block_id
== block_id
)
13874 strncpy(name
, p_data
->block_name
, max_len
);
13875 name
[max_len
- 1] = '\0';
13876 return(TNG_SUCCESS
);
13880 else if(block_type
== TNG_NON_PARTICLE_BLOCK_DATA
)
13882 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
13884 np_data
= &frame_set
->tr_data
[i
];
13885 if(np_data
->block_id
== block_id
)
13887 strncpy(name
, np_data
->block_name
, max_len
);
13888 name
[max_len
- 1] = '\0';
13889 return(TNG_SUCCESS
);
13894 return(TNG_FAILURE
);
13897 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
13898 (const tng_trajectory_t tng_data
,
13900 int *block_dependency
)
13903 tng_function_status stat
;
13904 tng_particle_data_t p_data
;
13905 tng_non_particle_data_t np_data
;
13907 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13908 TNG_ASSERT(block_dependency
, "TNG library: block_dependency must not be a NULL pointer.");
13910 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
13912 p_data
= &tng_data
->non_tr_particle_data
[i
];
13913 if(p_data
->block_id
== block_id
)
13915 *block_dependency
= TNG_PARTICLE_DEPENDENT
;
13916 return(TNG_SUCCESS
);
13919 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
13921 np_data
= &tng_data
->non_tr_data
[i
];
13922 if(np_data
->block_id
== block_id
)
13924 *block_dependency
= 0;
13925 return(TNG_SUCCESS
);
13929 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
13930 if(stat
== TNG_SUCCESS
)
13932 *block_dependency
= TNG_PARTICLE_DEPENDENT
+ TNG_FRAME_DEPENDENT
;
13933 return(TNG_SUCCESS
);
13937 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
13938 if(stat
== TNG_SUCCESS
)
13940 *block_dependency
= TNG_FRAME_DEPENDENT
;
13941 return(TNG_SUCCESS
);
13945 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
13946 if(stat
!= TNG_SUCCESS
)
13950 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
13951 if(stat
== TNG_SUCCESS
)
13953 *block_dependency
= TNG_PARTICLE_DEPENDENT
+ TNG_FRAME_DEPENDENT
;
13954 return(TNG_SUCCESS
);
13958 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
13959 if(stat
== TNG_SUCCESS
)
13961 *block_dependency
= TNG_FRAME_DEPENDENT
;
13962 return(TNG_SUCCESS
);
13968 return(TNG_FAILURE
);
13971 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13972 (const tng_trajectory_t tng_data
,
13974 int64_t *n_values_per_frame
)
13977 tng_function_status stat
;
13978 tng_particle_data_t p_data
;
13979 tng_non_particle_data_t np_data
;
13981 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
13982 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
13984 for(i
= 0; i
< tng_data
->n_particle_data_blocks
; i
++)
13986 p_data
= &tng_data
->non_tr_particle_data
[i
];
13987 if(p_data
->block_id
== block_id
)
13989 *n_values_per_frame
= p_data
->n_values_per_frame
;
13990 return(TNG_SUCCESS
);
13993 for(i
= 0; i
< tng_data
->n_data_blocks
; i
++)
13995 np_data
= &tng_data
->non_tr_data
[i
];
13996 if(np_data
->block_id
== block_id
)
13998 *n_values_per_frame
= np_data
->n_values_per_frame
;
13999 return(TNG_SUCCESS
);
14003 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
14004 if(stat
== TNG_SUCCESS
)
14006 *n_values_per_frame
= p_data
->n_values_per_frame
;
14007 return(TNG_SUCCESS
);
14011 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
14012 if(stat
== TNG_SUCCESS
)
14014 *n_values_per_frame
= np_data
->n_values_per_frame
;
14015 return(TNG_SUCCESS
);
14019 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
14020 if(stat
!= TNG_SUCCESS
)
14024 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
14025 if(stat
== TNG_SUCCESS
)
14027 *n_values_per_frame
= p_data
->n_values_per_frame
;
14028 return(TNG_SUCCESS
);
14032 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
14033 if(stat
== TNG_SUCCESS
)
14035 *n_values_per_frame
= np_data
->n_values_per_frame
;
14036 return(TNG_SUCCESS
);
14042 return(TNG_FAILURE
);
14045 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
14046 (tng_trajectory_t tng_data
,
14047 const int64_t frame_nr
,
14048 const int64_t block_id
,
14049 const void *values
,
14050 const char hash_mode
)
14052 int64_t header_pos
, file_pos
;
14053 int64_t output_file_len
, n_values_per_frame
, size
, contents_size
;
14054 int64_t header_size
, temp_first
, temp_last
;
14055 int64_t i
, last_frame
;
14057 tng_gen_block_t block
;
14058 tng_trajectory_frame_set_t frame_set
;
14059 FILE *temp
= tng_data
->input_file
;
14060 struct tng_non_particle_data data
;
14061 tng_function_status stat
;
14062 char dependency
, sparse_data
, datatype
;
14065 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14066 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
14067 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer.");
14069 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
14071 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
14072 __FILE__
, __LINE__
);
14073 return(TNG_CRITICAL
);
14076 temp_first
= tng_data
->first_trajectory_frame_set_input_file_pos
;
14077 temp_last
= tng_data
->last_trajectory_frame_set_input_file_pos
;
14078 temp_current
= tng_data
->current_trajectory_frame_set_input_file_pos
;
14079 tng_data
->first_trajectory_frame_set_input_file_pos
=
14080 tng_data
->first_trajectory_frame_set_output_file_pos
;
14081 tng_data
->last_trajectory_frame_set_input_file_pos
=
14082 tng_data
->last_trajectory_frame_set_output_file_pos
;
14083 tng_data
->current_trajectory_frame_set_input_file_pos
=
14084 tng_data
->current_trajectory_frame_set_output_file_pos
;
14086 tng_data
->input_file
= tng_data
->output_file
;
14088 stat
= tng_frame_set_of_frame_find(tng_data
, frame_nr
);
14090 frame_set
= &tng_data
->current_trajectory_frame_set
;
14092 if(stat
!= TNG_SUCCESS
)
14094 last_frame
= frame_set
->first_frame
+
14095 frame_set
->n_frames
- 1;
14096 /* If the wanted frame would be in the frame set after the last
14097 * frame set create a new frame set. */
14098 if(stat
== TNG_FAILURE
&&
14099 last_frame
< frame_nr
)
14100 /* (last_frame < frame_nr &&
14101 tng_data->current_trajectory_frame_set.first_frame +
14102 tng_data->frame_set_n_frames >= frame_nr))*/
14104 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
14106 last_frame
= frame_nr
- 1;
14108 tng_frame_set_new(tng_data
,
14110 tng_data
->frame_set_n_frames
);
14111 file_pos
= ftell(tng_data
->output_file
);
14112 fseek(tng_data
->output_file
, 0, SEEK_END
);
14113 output_file_len
= ftell(tng_data
->output_file
);
14114 fseek(tng_data
->output_file
, (long)file_pos
, SEEK_SET
);
14116 /* Read mapping blocks from the last frame set */
14117 tng_block_init(&block
);
14119 stat
= tng_block_header_read(tng_data
, block
);
14120 while(file_pos
< output_file_len
&&
14121 stat
!= TNG_CRITICAL
&&
14122 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14125 if(block
->id
== TNG_PARTICLE_MAPPING
)
14127 tng_trajectory_mapping_block_read(tng_data
, block
,
14132 fseek(tng_data
->output_file
, (long)block
->block_contents_size
,
14135 file_pos
= ftell(tng_data
->output_file
);
14136 if(file_pos
< output_file_len
)
14138 stat
= tng_block_header_read(tng_data
, block
);
14142 tng_block_destroy(&block
);
14143 /* Write the frame set to disk */
14144 if(tng_frame_set_write(tng_data
, hash_mode
) != TNG_SUCCESS
)
14146 fprintf(stderr
, "TNG library: Error writing frame set. %s: %d\n", __FILE__
, __LINE__
);
14147 return(TNG_CRITICAL
);
14152 tng_data
->input_file
= temp
;
14153 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14154 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14155 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14160 tng_block_init(&block
);
14162 file_pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
14164 fseek(tng_data
->output_file
, 0, SEEK_END
);
14165 output_file_len
= ftell(tng_data
->output_file
);
14166 fseek(tng_data
->output_file
, (long)file_pos
, SEEK_SET
);
14168 /* Read past the frame set block first */
14169 stat
= tng_block_header_read(tng_data
, block
);
14170 if(stat
== TNG_CRITICAL
)
14172 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
14173 file_pos
, __FILE__
, __LINE__
);
14174 tng_block_destroy(&block
);
14175 tng_data
->input_file
= temp
;
14177 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14178 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14179 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14182 fseek(tng_data
->output_file
, (long)block
->block_contents_size
,
14185 /* Read all block headers until next frame set block or
14186 * until the wanted block id is found */
14187 stat
= tng_block_header_read(tng_data
, block
);
14188 while(file_pos
< output_file_len
&&
14189 stat
!= TNG_CRITICAL
&&
14190 block
->id
!= block_id
&&
14191 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14194 fseek(tng_data
->output_file
, (long)block
->block_contents_size
, SEEK_CUR
);
14195 file_pos
= ftell(tng_data
->output_file
);
14196 if(file_pos
< output_file_len
)
14198 stat
= tng_block_header_read(tng_data
, block
);
14201 if(stat
== TNG_CRITICAL
)
14203 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
14204 file_pos
, __FILE__
, __LINE__
);
14205 tng_block_destroy(&block
);
14206 tng_data
->input_file
= temp
;
14207 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14208 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14209 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14213 contents_size
= block
->block_contents_size
;
14214 header_size
= block
->header_contents_size
;
14216 header_pos
= ftell(tng_data
->output_file
) - header_size
;
14217 frame_set
= &tng_data
->current_trajectory_frame_set
;
14219 if(fread(&datatype
, sizeof(datatype
), 1, tng_data
->input_file
) == 0)
14221 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14222 tng_block_destroy(&block
);
14223 return(TNG_CRITICAL
);
14225 if(fread(&dependency
, sizeof(dependency
), 1, tng_data
->input_file
) == 0)
14227 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14228 tng_block_destroy(&block
);
14229 return(TNG_CRITICAL
);
14231 data
.datatype
= datatype
;
14233 if(!(dependency
& TNG_FRAME_DEPENDENT
) ||
14234 (dependency
& TNG_PARTICLE_DEPENDENT
))
14236 tng_block_destroy(&block
);
14237 tng_data
->input_file
= temp
;
14239 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14240 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14241 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14242 return(TNG_FAILURE
);
14245 if(fread(&sparse_data
, sizeof(sparse_data
), 1, tng_data
->input_file
) == 0)
14247 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14248 tng_block_destroy(&block
);
14249 return(TNG_CRITICAL
);
14252 if(fread(&data
.n_values_per_frame
, sizeof(data
.n_values_per_frame
), 1,
14253 tng_data
->input_file
) == 0)
14255 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14256 tng_block_destroy(&block
);
14257 return(TNG_CRITICAL
);
14259 if(tng_data
->output_endianness_swap_func_64
)
14261 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14262 &data
.n_values_per_frame
)
14265 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14266 __FILE__
, __LINE__
);
14270 if(fread(&data
.codec_id
, sizeof(data
.codec_id
), 1,
14271 tng_data
->input_file
) == 0)
14273 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14274 tng_block_destroy(&block
);
14275 return(TNG_CRITICAL
);
14277 if(tng_data
->output_endianness_swap_func_64
)
14279 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14283 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14284 __FILE__
, __LINE__
);
14288 if(data
.codec_id
!= TNG_UNCOMPRESSED
)
14290 if(fread(&data
.compression_multiplier
,
14291 sizeof(data
.compression_multiplier
), 1, tng_data
->input_file
)
14294 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14295 tng_block_destroy(&block
);
14296 return(TNG_CRITICAL
);
14298 if(tng_data
->output_endianness_swap_func_64
)
14300 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14301 (int64_t *)&data
.compression_multiplier
)
14304 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14305 __FILE__
, __LINE__
);
14311 data
.compression_multiplier
= 1;
14316 if(fread(&data
.first_frame_with_data
, sizeof(data
.first_frame_with_data
),
14317 1, tng_data
->input_file
) == 0)
14319 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14320 tng_block_destroy(&block
);
14321 return(TNG_CRITICAL
);
14323 if(tng_data
->output_endianness_swap_func_64
)
14325 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14326 &data
.first_frame_with_data
)
14329 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14330 __FILE__
, __LINE__
);
14334 if(fread(&data
.stride_length
, sizeof(data
.stride_length
),
14335 1, tng_data
->input_file
) == 0)
14337 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14338 tng_block_destroy(&block
);
14339 return(TNG_CRITICAL
);
14341 if(tng_data
->output_endianness_swap_func_64
)
14343 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14344 &data
.stride_length
)
14347 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14348 __FILE__
, __LINE__
);
14354 data
.first_frame_with_data
= 0;
14355 data
.stride_length
= 1;
14357 data
.n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
;
14359 tng_data
->input_file
= temp
;
14361 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14362 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14363 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14365 switch(data
.datatype
)
14367 case(TNG_INT_DATA
):
14368 size
= sizeof(int64_t);
14370 case(TNG_FLOAT_DATA
):
14371 size
= sizeof(float);
14373 case(TNG_DOUBLE_DATA
):
14374 size
= sizeof(double);
14377 fprintf(stderr
, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__
,
14379 tng_block_destroy(&block
);
14380 return(TNG_FAILURE
);
14383 n_values_per_frame
= data
.n_values_per_frame
;
14385 file_pos
= (frame_nr
- tng_max_i64(frame_set
->first_frame
,
14386 data
.first_frame_with_data
)) /
14387 data
.stride_length
;
14388 file_pos
*= size
* n_values_per_frame
;
14390 if(file_pos
> contents_size
)
14392 fprintf(stderr
, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__
,
14394 tng_block_destroy(&block
);
14395 return(TNG_FAILURE
);
14398 fseek(tng_data
->output_file
, (long)file_pos
, SEEK_CUR
);
14400 /* If the endianness is not big endian the data needs to be swapped */
14401 if((data
.datatype
== TNG_INT_DATA
||
14402 data
.datatype
== TNG_DOUBLE_DATA
) &&
14403 tng_data
->output_endianness_swap_func_64
)
14405 copy
= malloc(n_values_per_frame
* size
);
14406 memcpy(copy
, values
, n_values_per_frame
* size
);
14407 for(i
= 0; i
< n_values_per_frame
; i
++)
14409 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14413 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14414 __FILE__
, __LINE__
);
14417 fwrite(copy
, n_values_per_frame
, size
,
14418 tng_data
->output_file
);
14421 else if(data
.datatype
== TNG_FLOAT_DATA
&&
14422 tng_data
->output_endianness_swap_func_32
)
14424 copy
= malloc(n_values_per_frame
* size
);
14425 memcpy(copy
, values
, n_values_per_frame
* size
);
14426 for(i
= 0; i
< n_values_per_frame
; i
++)
14428 if(tng_data
->output_endianness_swap_func_32(tng_data
,
14432 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14433 __FILE__
, __LINE__
);
14436 fwrite(copy
, n_values_per_frame
, size
,
14437 tng_data
->output_file
);
14443 fwrite(values
, n_values_per_frame
, size
, tng_data
->output_file
);
14446 fflush(tng_data
->output_file
);
14448 /* Update the number of written frames in the frame set. */
14449 if(frame_nr
- frame_set
->first_frame
+ 1 > frame_set
->n_written_frames
)
14451 frame_set
->n_written_frames
= frame_nr
- frame_set
->first_frame
+ 1;
14454 /* If the last frame has been written update the hash */
14455 if(hash_mode
== TNG_USE_HASH
&& (frame_nr
+ data
.stride_length
-
14456 data
.first_frame_with_data
) >=
14457 frame_set
->n_frames
)
14459 tng_md5_hash_update(tng_data
, block
, header_pos
, header_pos
+
14463 tng_block_destroy(&block
);
14465 return(TNG_SUCCESS
);
14468 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
14469 (tng_trajectory_t tng_data
,
14470 const int64_t frame_nr
,
14471 const int64_t block_id
,
14472 const int64_t val_first_particle
,
14473 const int64_t val_n_particles
,
14474 const void *values
,
14475 const char hash_mode
)
14477 int64_t header_pos
, file_pos
, tot_n_particles
;
14478 int64_t output_file_len
, n_values_per_frame
, size
, contents_size
;
14479 int64_t header_size
, temp_first
, temp_last
;
14480 int64_t mapping_block_end_pos
, num_first_particle
, block_n_particles
;
14481 int64_t i
, last_frame
;
14483 tng_gen_block_t block
;
14484 tng_trajectory_frame_set_t frame_set
;
14485 FILE *temp
= tng_data
->input_file
;
14486 struct tng_particle_data data
;
14487 tng_function_status stat
;
14488 tng_particle_mapping_t mapping
;
14489 char dependency
, sparse_data
, datatype
;
14492 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
14493 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
14494 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer.");
14495 TNG_ASSERT(val_first_particle
>= 0, "TNG library: val_first_particle must be >= 0.");
14496 TNG_ASSERT(val_n_particles
>= 0, "TNG library: val_n_particles must be >= 0.");
14498 if(tng_output_file_init(tng_data
) != TNG_SUCCESS
)
14500 fprintf(stderr
, "TNG library: Cannot initialise destination file. %s: %d\n",
14501 __FILE__
, __LINE__
);
14502 return(TNG_CRITICAL
);
14505 temp_first
= tng_data
->first_trajectory_frame_set_input_file_pos
;
14506 temp_last
= tng_data
->last_trajectory_frame_set_input_file_pos
;
14507 temp_current
= tng_data
->current_trajectory_frame_set_input_file_pos
;
14508 tng_data
->first_trajectory_frame_set_input_file_pos
=
14509 tng_data
->first_trajectory_frame_set_output_file_pos
;
14510 tng_data
->last_trajectory_frame_set_input_file_pos
=
14511 tng_data
->last_trajectory_frame_set_output_file_pos
;
14512 tng_data
->current_trajectory_frame_set_input_file_pos
=
14513 tng_data
->current_trajectory_frame_set_output_file_pos
;
14515 tng_data
->input_file
= tng_data
->output_file
;
14517 stat
= tng_frame_set_of_frame_find(tng_data
, frame_nr
);
14519 frame_set
= &tng_data
->current_trajectory_frame_set
;
14521 if(stat
!= TNG_SUCCESS
)
14523 last_frame
= frame_set
->first_frame
+
14524 frame_set
->n_frames
- 1;
14525 /* fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
14527 /* If the wanted frame would be in the frame set after the last
14528 * frame set create a new frame set. */
14529 if(stat
== TNG_FAILURE
&&
14530 (last_frame
< frame_nr
&&
14531 last_frame
+ tng_data
->frame_set_n_frames
>= frame_nr
))
14533 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
14535 last_frame
= frame_nr
- 1;
14537 tng_frame_set_new(tng_data
,
14539 tng_data
->frame_set_n_frames
);
14541 file_pos
= ftell(tng_data
->output_file
);
14542 fseek(tng_data
->output_file
, 0, SEEK_END
);
14543 output_file_len
= ftell(tng_data
->output_file
);
14544 fseek(tng_data
->output_file
, (long)file_pos
, SEEK_SET
);
14546 /* Read mapping blocks from the last frame set */
14547 tng_block_init(&block
);
14549 stat
= tng_block_header_read(tng_data
, block
);
14550 while(file_pos
< output_file_len
&&
14551 stat
!= TNG_CRITICAL
&&
14552 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14555 if(block
->id
== TNG_PARTICLE_MAPPING
)
14557 tng_trajectory_mapping_block_read(tng_data
, block
,
14562 fseek(tng_data
->output_file
, (long)block
->block_contents_size
,
14565 file_pos
= ftell(tng_data
->output_file
);
14566 if(file_pos
< output_file_len
)
14568 stat
= tng_block_header_read(tng_data
, block
);
14572 tng_block_destroy(&block
);
14573 /* Write the frame set to disk */
14574 if(tng_frame_set_write(tng_data
, hash_mode
) != TNG_SUCCESS
)
14576 fprintf(stderr
, "TNG library: Error writing frame set. %s: %d\n", __FILE__
, __LINE__
);
14582 tng_data
->input_file
= temp
;
14583 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14584 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14585 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14591 tng_block_init(&block
);
14593 file_pos
= tng_data
->current_trajectory_frame_set_output_file_pos
;
14595 fseek(tng_data
->output_file
, 0, SEEK_END
);
14596 output_file_len
= ftell(tng_data
->output_file
);
14597 fseek(tng_data
->output_file
, (long)file_pos
, SEEK_SET
);
14599 /* Read past the frame set block first */
14600 stat
= tng_block_header_read(tng_data
, block
);
14601 if(stat
== TNG_CRITICAL
)
14603 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
14604 file_pos
, __FILE__
, __LINE__
);
14605 tng_block_destroy(&block
);
14606 tng_data
->input_file
= temp
;
14608 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14609 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14610 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14613 fseek(tng_data
->output_file
, (long)block
->block_contents_size
,
14616 if(tng_data
->var_num_atoms_flag
)
14618 tot_n_particles
= frame_set
->n_particles
;
14622 tot_n_particles
= tng_data
->n_particles
;
14625 if(val_n_particles
< tot_n_particles
)
14627 mapping_block_end_pos
= -1;
14628 /* Read all mapping blocks to find the right place to put the data */
14629 stat
= tng_block_header_read(tng_data
, block
);
14630 while(file_pos
< output_file_len
&&
14631 stat
!= TNG_CRITICAL
&&
14632 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14635 if(block
->id
== TNG_PARTICLE_MAPPING
)
14637 tng_trajectory_mapping_block_read(tng_data
, block
, hash_mode
);
14641 fseek(tng_data
->output_file
, (long)block
->block_contents_size
,
14644 file_pos
= ftell(tng_data
->output_file
);
14645 if(block
->id
== TNG_PARTICLE_MAPPING
)
14647 mapping
= &frame_set
->mappings
[frame_set
->n_mapping_blocks
- 1];
14648 if(val_first_particle
>= mapping
->num_first_particle
&&
14649 val_first_particle
< mapping
->num_first_particle
+
14650 mapping
->n_particles
&&
14651 val_first_particle
+ val_n_particles
<=
14652 mapping
->num_first_particle
+ mapping
->n_particles
)
14654 mapping_block_end_pos
= file_pos
;
14657 if(file_pos
< output_file_len
)
14659 stat
= tng_block_header_read(tng_data
, block
);
14662 if(stat
== TNG_CRITICAL
)
14664 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
14665 file_pos
, __FILE__
, __LINE__
);
14666 tng_block_destroy(&block
);
14667 tng_data
->input_file
= temp
;
14669 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14670 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14671 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14674 if(mapping_block_end_pos
< 0)
14676 tng_block_destroy(&block
);
14677 tng_data
->input_file
= temp
;
14679 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14680 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14681 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14682 return(TNG_FAILURE
);
14684 fseek(tng_data
->output_file
, (long)mapping_block_end_pos
, SEEK_SET
);
14687 /* Read all block headers until next frame set block or
14688 * until the wanted block id is found */
14689 stat
= tng_block_header_read(tng_data
, block
);
14690 while(file_pos
< output_file_len
&&
14691 stat
!= TNG_CRITICAL
&&
14692 block
->id
!= block_id
&&
14693 block
->id
!= TNG_PARTICLE_MAPPING
&&
14694 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
14697 fseek(tng_data
->output_file
, (long)block
->block_contents_size
, SEEK_CUR
);
14698 file_pos
= ftell(tng_data
->output_file
);
14699 if(file_pos
< output_file_len
)
14701 stat
= tng_block_header_read(tng_data
, block
);
14704 if(stat
== TNG_CRITICAL
)
14706 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
14707 file_pos
, __FILE__
, __LINE__
);
14708 tng_block_destroy(&block
);
14709 tng_data
->input_file
= temp
;
14711 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14712 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14713 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14717 contents_size
= block
->block_contents_size
;
14718 header_size
= block
->header_contents_size
;
14720 header_pos
= ftell(tng_data
->output_file
) - header_size
;
14721 frame_set
= &tng_data
->current_trajectory_frame_set
;
14723 if(fread(&datatype
, sizeof(datatype
), 1, tng_data
->input_file
) == 0)
14725 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14726 tng_block_destroy(&block
);
14727 return(TNG_CRITICAL
);
14730 data
.datatype
= datatype
;
14732 if(fread(&dependency
, sizeof(dependency
), 1, tng_data
->input_file
) == 0)
14734 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14735 tng_block_destroy(&block
);
14736 return(TNG_CRITICAL
);
14739 if(!(dependency
& TNG_FRAME_DEPENDENT
) ||
14740 !(dependency
& TNG_PARTICLE_DEPENDENT
))
14742 tng_block_destroy(&block
);
14743 tng_data
->input_file
= temp
;
14745 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14746 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14747 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14748 return(TNG_FAILURE
);
14751 if(fread(&sparse_data
, sizeof(sparse_data
), 1, tng_data
->input_file
) == 0)
14753 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14754 tng_block_destroy(&block
);
14755 return(TNG_CRITICAL
);
14758 if(fread(&data
.n_values_per_frame
, sizeof(data
.n_values_per_frame
), 1,
14759 tng_data
->input_file
) == 0)
14761 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14762 tng_block_destroy(&block
);
14763 return(TNG_CRITICAL
);
14765 if(tng_data
->output_endianness_swap_func_64
)
14767 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14768 &data
.n_values_per_frame
)
14771 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14772 __FILE__
, __LINE__
);
14776 if(fread(&data
.codec_id
, sizeof(data
.codec_id
), 1,
14777 tng_data
->input_file
) == 0)
14779 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14780 tng_block_destroy(&block
);
14781 return(TNG_CRITICAL
);
14783 if(tng_data
->output_endianness_swap_func_64
)
14785 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14789 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14790 __FILE__
, __LINE__
);
14794 if(data
.codec_id
!= TNG_UNCOMPRESSED
)
14796 if(fread(&data
.compression_multiplier
,
14797 sizeof(data
.compression_multiplier
), 1, tng_data
->input_file
)
14800 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14801 tng_block_destroy(&block
);
14802 return(TNG_CRITICAL
);
14805 if(tng_data
->output_endianness_swap_func_64
)
14807 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14808 (int64_t *)&data
.compression_multiplier
)
14811 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14812 __FILE__
, __LINE__
);
14818 data
.compression_multiplier
= 1;
14823 if(fread(&data
.first_frame_with_data
,
14824 sizeof(data
.first_frame_with_data
),
14825 1, tng_data
->input_file
) == 0)
14827 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14828 tng_block_destroy(&block
);
14829 return(TNG_CRITICAL
);
14831 if(tng_data
->output_endianness_swap_func_64
)
14833 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14834 &data
.first_frame_with_data
)
14837 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14838 __FILE__
, __LINE__
);
14842 if(fread(&data
.stride_length
, sizeof(data
.stride_length
),
14843 1, tng_data
->input_file
) == 0)
14845 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14846 tng_block_destroy(&block
);
14847 return(TNG_CRITICAL
);
14849 if(tng_data
->output_endianness_swap_func_64
)
14851 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14852 &data
.stride_length
)
14855 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14856 __FILE__
, __LINE__
);
14862 data
.first_frame_with_data
= 0;
14863 data
.stride_length
= 1;
14865 data
.n_frames
= tng_data
->current_trajectory_frame_set
.n_frames
;
14867 if(fread(&num_first_particle
, sizeof(num_first_particle
), 1,
14868 tng_data
->input_file
) == 0)
14870 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14871 tng_block_destroy(&block
);
14872 return(TNG_CRITICAL
);
14874 if(tng_data
->output_endianness_swap_func_64
)
14876 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14877 &num_first_particle
)
14880 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14881 __FILE__
, __LINE__
);
14885 if(fread(&block_n_particles
, sizeof(block_n_particles
), 1,
14886 tng_data
->input_file
) == 0)
14888 fprintf(stderr
, "TNG library: Error reading file. %s: %d\n", __FILE__
, __LINE__
);
14889 tng_block_destroy(&block
);
14890 return(TNG_CRITICAL
);
14892 if(tng_data
->output_endianness_swap_func_64
)
14894 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14895 &block_n_particles
)
14898 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14899 __FILE__
, __LINE__
);
14904 tng_data
->input_file
= temp
;
14906 tng_data
->first_trajectory_frame_set_input_file_pos
= temp_first
;
14907 tng_data
->last_trajectory_frame_set_input_file_pos
= temp_last
;
14908 tng_data
->current_trajectory_frame_set_input_file_pos
= temp_current
;
14911 switch(data
.datatype
)
14913 case(TNG_INT_DATA
):
14914 size
= sizeof(int64_t);
14916 case(TNG_FLOAT_DATA
):
14917 size
= sizeof(float);
14919 case(TNG_DOUBLE_DATA
):
14920 size
= sizeof(double);
14923 fprintf(stderr
, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__
,
14925 tng_block_destroy(&block
);
14926 return(TNG_FAILURE
);
14929 n_values_per_frame
= data
.n_values_per_frame
;
14931 file_pos
= (frame_nr
- tng_max_i64(frame_set
->first_frame
,
14932 data
.first_frame_with_data
)) /
14933 data
.stride_length
;
14934 file_pos
*= block_n_particles
* size
* n_values_per_frame
;
14936 if(file_pos
> contents_size
)
14938 fprintf(stderr
, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__
,
14940 tng_block_destroy(&block
);
14941 return(TNG_FAILURE
);
14944 fseek(tng_data
->output_file
, (long)file_pos
, SEEK_CUR
);
14946 /* If the endianness is not big endian the data needs to be swapped */
14947 if((data
.datatype
== TNG_INT_DATA
||
14948 data
.datatype
== TNG_DOUBLE_DATA
) &&
14949 tng_data
->output_endianness_swap_func_64
)
14951 copy
= malloc(val_n_particles
* n_values_per_frame
* size
);
14952 memcpy(copy
, values
, val_n_particles
* n_values_per_frame
* size
);
14953 for(i
= 0; i
< val_n_particles
* n_values_per_frame
; i
++)
14955 if(tng_data
->output_endianness_swap_func_64(tng_data
,
14956 (int64_t *) copy
+i
)
14959 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14960 __FILE__
, __LINE__
);
14963 fwrite(copy
, val_n_particles
* n_values_per_frame
, size
,
14964 tng_data
->output_file
);
14967 else if(data
.datatype
== TNG_FLOAT_DATA
&&
14968 tng_data
->output_endianness_swap_func_32
)
14970 copy
= malloc(val_n_particles
* n_values_per_frame
* size
);
14971 memcpy(copy
, values
, val_n_particles
* n_values_per_frame
* size
);
14972 for(i
= 0; i
< val_n_particles
* n_values_per_frame
; i
++)
14974 if(tng_data
->output_endianness_swap_func_32(tng_data
,
14975 (int32_t *) copy
+i
)
14978 fprintf(stderr
, "TNG library: Cannot swap byte order. %s: %d\n",
14979 __FILE__
, __LINE__
);
14982 fwrite(copy
, val_n_particles
* n_values_per_frame
, size
,
14983 tng_data
->output_file
);
14989 fwrite(values
, val_n_particles
* n_values_per_frame
, size
,
14990 tng_data
->output_file
);
14992 fflush(tng_data
->output_file
);
14994 /* Update the number of written frames in the frame set. */
14995 if(frame_nr
- frame_set
->first_frame
+ 1 > frame_set
->n_written_frames
)
14997 frame_set
->n_written_frames
= frame_nr
- frame_set
->first_frame
+ 1;
15000 /* If the last frame has been written update the hash */
15001 if(hash_mode
== TNG_USE_HASH
&& (frame_nr
+ data
.stride_length
-
15002 data
.first_frame_with_data
) >=
15003 frame_set
->n_frames
)
15005 tng_md5_hash_update(tng_data
, block
, header_pos
, header_pos
+
15009 tng_block_destroy(&block
);
15010 return(TNG_SUCCESS
);
15013 static tng_function_status tng_data_values_alloc
15014 (const tng_trajectory_t tng_data
,
15015 union data_values
***values
,
15016 const int64_t n_frames
,
15017 const int64_t n_values_per_frame
,
15021 tng_function_status stat
;
15023 if(n_frames
<= 0 || n_values_per_frame
<= 0)
15025 return(TNG_FAILURE
);
15030 stat
= tng_data_values_free(tng_data
, *values
, n_frames
,
15031 n_values_per_frame
,
15033 if(stat
!= TNG_SUCCESS
)
15035 fprintf(stderr
, "TNG library: Cannot free particle data values. %s: %d\n",
15036 __FILE__
, __LINE__
);
15040 *values
= malloc(sizeof(union data_values
*) * n_frames
);
15043 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15044 sizeof(union data_values
**) * n_frames
,
15045 __FILE__
, __LINE__
);
15046 return(TNG_CRITICAL
);
15050 for(i
= 0; i
< n_frames
; i
++)
15052 (*values
)[i
] = malloc(sizeof(union data_values
) *
15053 n_values_per_frame
);
15056 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15057 sizeof(union data_values
) * n_values_per_frame
,
15058 __FILE__
, __LINE__
);
15061 return(TNG_CRITICAL
);
15064 return(TNG_SUCCESS
);
15067 /* FIXME: This needs ***values */
15068 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
15069 (const tng_trajectory_t tng_data
,
15070 union data_values
**values
,
15071 const int64_t n_frames
,
15072 const int64_t n_values_per_frame
,
15080 for(i
= 0; i
< n_frames
; i
++)
15084 if(type
== TNG_CHAR_DATA
)
15086 for(j
= 0; j
< n_values_per_frame
; j
++)
15090 free(values
[i
][j
].c
);
15091 values
[i
][j
].c
= 0;
15103 return(TNG_SUCCESS
);
15106 static tng_function_status tng_particle_data_values_alloc
15107 (const tng_trajectory_t tng_data
,
15108 union data_values
****values
,
15109 const int64_t n_frames
,
15110 const int64_t n_particles
,
15111 const int64_t n_values_per_frame
,
15115 tng_function_status stat
;
15117 if(n_particles
== 0 || n_values_per_frame
== 0)
15119 return(TNG_FAILURE
);
15124 stat
= tng_particle_data_values_free(tng_data
, *values
, n_frames
,
15125 n_particles
, n_values_per_frame
,
15127 if(stat
!= TNG_SUCCESS
)
15129 fprintf(stderr
, "TNG library: Cannot free particle data values. %s: %d\n",
15130 __FILE__
, __LINE__
);
15134 *values
= malloc(sizeof(union data_values
**) * n_frames
);
15137 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15138 sizeof(union data_values
**) * n_frames
,
15139 __FILE__
, __LINE__
);
15140 return(TNG_CRITICAL
);
15144 for(i
= 0; i
< n_frames
; i
++)
15146 (*values
)[i
] = malloc(sizeof(union data_values
*) *
15150 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15151 sizeof(union data_values
*) * n_particles
,
15152 __FILE__
, __LINE__
);
15155 return(TNG_CRITICAL
);
15157 for(j
= 0; j
< n_particles
; j
++)
15159 (*values
)[i
][j
] = malloc(sizeof(union data_values
) *
15160 n_values_per_frame
);
15161 if(!(*values
)[i
][j
])
15163 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15164 sizeof(union data_values
*) * n_particles
,
15165 __FILE__
, __LINE__
);
15166 tng_particle_data_values_free(tng_data
, *values
, n_frames
,
15167 n_particles
, n_values_per_frame
,
15170 return(TNG_CRITICAL
);
15174 return(TNG_SUCCESS
);
15177 /* FIXME: This needs ****values */
15178 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
15179 (const tng_trajectory_t tng_data
,
15180 union data_values
***values
,
15181 const int64_t n_frames
,
15182 const int64_t n_particles
,
15183 const int64_t n_values_per_frame
,
15191 for(i
= 0; i
< n_frames
; i
++)
15195 for(j
= 0; j
< n_particles
; j
++)
15197 if(type
== TNG_CHAR_DATA
)
15199 for(k
= 0; k
< n_values_per_frame
; k
++)
15201 if(values
[i
][j
][k
].c
)
15203 free(values
[i
][j
][k
].c
);
15204 values
[i
][j
][k
].c
= 0;
15208 free(values
[i
][j
]);
15219 return(TNG_SUCCESS
);
15223 tng_function_status DECLSPECDLLEXPORT tng_data_get
15224 (tng_trajectory_t tng_data
,
15225 const int64_t block_id
,
15226 union data_values
***values
,
15228 int64_t *n_values_per_frame
,
15231 int64_t i
, j
, file_pos
, block_index
;
15234 tng_non_particle_data_t data
;
15235 tng_trajectory_frame_set_t frame_set
;
15236 tng_gen_block_t block
;
15237 tng_function_status stat
;
15239 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15240 TNG_ASSERT(n_frames
, "TNG library: n_frames must not be a NULL pointer.");
15241 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15242 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15244 frame_set
= &tng_data
->current_trajectory_frame_set
;
15249 if(tng_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
15251 tng_block_init(&block
);
15252 file_pos
= ftell(tng_data
->input_file
);
15253 /* Read all blocks until next frame set block */
15254 stat
= tng_block_header_read(tng_data
, block
);
15255 while(file_pos
< tng_data
->input_file_len
&&
15256 stat
!= TNG_CRITICAL
&&
15257 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
15260 /* Use hash by default */
15261 stat
= tng_block_read_next(tng_data
, block
,
15263 if(stat
!= TNG_CRITICAL
)
15265 file_pos
= ftell(tng_data
->input_file
);
15266 if(file_pos
< tng_data
->input_file_len
)
15268 stat
= tng_block_header_read(tng_data
, block
);
15272 tng_block_destroy(&block
);
15273 if(stat
== TNG_CRITICAL
)
15275 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
15276 file_pos
, __FILE__
, __LINE__
);
15280 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
15282 data
= &frame_set
->tr_data
[i
];
15283 if(data
->block_id
== block_id
)
15289 if(block_index
< 0)
15291 return(TNG_FAILURE
);
15295 *n_frames
= tng_max_i64(1, data
->n_frames
);
15296 *n_values_per_frame
= data
->n_values_per_frame
;
15297 *type
= data
->datatype
;
15301 if(tng_data_values_alloc(tng_data
, values
, *n_frames
,
15302 *n_values_per_frame
,
15306 return(TNG_CRITICAL
);
15312 case TNG_CHAR_DATA
:
15313 for(i
= 0; i
< *n_frames
; i
++)
15315 for(j
= 0; j
< *n_values_per_frame
; j
++)
15317 len
= strlen(data
->strings
[i
][j
]) + 1;
15318 (*values
)[i
][j
].c
= malloc(len
);
15319 strncpy((*values
)[i
][j
].c
, data
->strings
[i
][j
], len
);
15324 size
= sizeof(int);
15325 for(i
= 0; i
< *n_frames
; i
++)
15327 for(j
= 0; j
< *n_values_per_frame
; j
++)
15329 (*values
)[i
][j
].i
= *(int *)((char *)data
->values
+ size
*
15330 (i
*(*n_values_per_frame
) + j
));
15334 case TNG_FLOAT_DATA
:
15335 size
= sizeof(float);
15336 for(i
= 0; i
< *n_frames
; i
++)
15338 for(j
= 0; j
< *n_values_per_frame
; j
++)
15340 (*values
)[i
][j
].f
= *(float *)((char *)data
->values
+ size
*
15341 (i
*(*n_values_per_frame
) + j
));
15345 case TNG_DOUBLE_DATA
:
15347 size
= sizeof(double);
15348 for(i
= 0; i
< *n_frames
; i
++)
15350 for(j
= 0; j
< *n_values_per_frame
; j
++)
15352 (*values
)[i
][j
].d
= *(double *)((char *)data
->values
+ size
*
15353 (i
*(*n_values_per_frame
) + j
));
15358 data
->last_retrieved_frame
= frame_set
->first_frame
+ data
->n_frames
- 1;
15360 return(TNG_SUCCESS
);
15363 tng_function_status
tng_data_vector_get(tng_trajectory_t tng_data
,
15364 const int64_t block_id
,
15367 int64_t *stride_length
,
15368 int64_t *n_values_per_frame
,
15371 int64_t file_pos
, data_size
, n_frames_div
, block_index
;
15373 tng_non_particle_data_t data
;
15374 tng_trajectory_frame_set_t frame_set
;
15375 tng_gen_block_t block
;
15377 tng_function_status stat
;
15379 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15380 TNG_ASSERT(n_frames
, "TNG library: n_frames must not be a NULL pointer.");
15381 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
15382 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15383 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15385 frame_set
= &tng_data
->current_trajectory_frame_set
;
15390 if(tng_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
15392 tng_block_init(&block
);
15393 file_pos
= ftell(tng_data
->input_file
);
15394 /* Read all blocks until next frame set block */
15395 stat
= tng_block_header_read(tng_data
, block
);
15396 while(file_pos
< tng_data
->input_file_len
&&
15397 stat
!= TNG_CRITICAL
&&
15398 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
15401 /* Use hash by default */
15402 stat
= tng_block_read_next(tng_data
, block
,
15404 if(stat
!= TNG_CRITICAL
)
15406 file_pos
= ftell(tng_data
->input_file
);
15407 if(file_pos
< tng_data
->input_file_len
)
15409 stat
= tng_block_header_read(tng_data
, block
);
15413 tng_block_destroy(&block
);
15414 if(stat
== TNG_CRITICAL
)
15416 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
15417 file_pos
, __FILE__
, __LINE__
);
15421 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
15423 data
= &frame_set
->tr_data
[i
];
15424 if(data
->block_id
== block_id
)
15430 if(block_index
< 0)
15432 return(TNG_FAILURE
);
15436 *type
= data
->datatype
;
15440 case TNG_CHAR_DATA
:
15441 return(TNG_FAILURE
);
15443 size
= sizeof(int64_t);
15445 case TNG_FLOAT_DATA
:
15446 size
= sizeof(float);
15448 case TNG_DOUBLE_DATA
:
15450 size
= sizeof(double);
15453 *n_frames
= data
->n_frames
;
15454 *n_values_per_frame
= data
->n_values_per_frame
;
15455 *stride_length
= data
->stride_length
;
15456 n_frames_div
= (*n_frames
% *stride_length
) ? *n_frames
/ *stride_length
+ 1:
15457 *n_frames
/ *stride_length
;
15459 data_size
= n_frames_div
* size
*
15460 *n_values_per_frame
;
15462 temp
= realloc(*values
, data_size
);
15465 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15466 data_size
, __FILE__
, __LINE__
);
15469 return(TNG_CRITICAL
);
15474 memcpy(*values
, data
->values
, data_size
);
15476 data
->last_retrieved_frame
= frame_set
->first_frame
+ data
->n_frames
- 1;
15478 return(TNG_SUCCESS
);
15481 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
15482 (tng_trajectory_t tng_data
,
15483 const int64_t block_id
,
15484 const int64_t start_frame_nr
,
15485 const int64_t end_frame_nr
,
15486 const char hash_mode
,
15487 union data_values
***values
,
15488 int64_t *n_values_per_frame
,
15491 int64_t i
, j
, n_frames
, file_pos
, current_frame_pos
, first_frame
;
15492 int64_t block_index
;
15495 tng_non_particle_data_t data
;
15496 tng_trajectory_frame_set_t frame_set
;
15497 tng_gen_block_t block
;
15498 tng_function_status stat
;
15500 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15501 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15502 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15503 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15507 frame_set
= &tng_data
->current_trajectory_frame_set
;
15508 first_frame
= frame_set
->first_frame
;
15510 stat
= tng_frame_set_of_frame_find(tng_data
, start_frame_nr
);
15511 if(stat
!= TNG_SUCCESS
)
15517 /* Do not re-read the frame set. */
15518 if(first_frame
!= frame_set
->first_frame
||
15519 frame_set
->n_data_blocks
<= 0)
15521 tng_block_init(&block
);
15522 file_pos
= ftell(tng_data
->input_file
);
15523 /* Read all blocks until next frame set block */
15524 stat
= tng_block_header_read(tng_data
, block
);
15525 while(file_pos
< tng_data
->input_file_len
&&
15526 stat
!= TNG_CRITICAL
&&
15527 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
15530 stat
= tng_block_read_next(tng_data
, block
,
15532 if(stat
!= TNG_CRITICAL
)
15534 file_pos
= ftell(tng_data
->input_file
);
15535 if(file_pos
< tng_data
->input_file_len
)
15537 stat
= tng_block_header_read(tng_data
, block
);
15541 tng_block_destroy(&block
);
15542 if(stat
== TNG_CRITICAL
)
15544 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
15545 file_pos
, __FILE__
, __LINE__
);
15551 /* See if there is a data block of this ID.
15552 * Start checking the last read frame set */
15553 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
15555 data
= &frame_set
->tr_data
[i
];
15556 if(data
->block_id
== block_id
)
15563 if(block_index
< 0)
15565 fprintf(stderr
, "TNG library: Could not find non-particle data block with id %"PRId64
". %s: %d\n",
15566 block_id
, __FILE__
, __LINE__
);
15567 return(TNG_FAILURE
);
15570 n_frames
= end_frame_nr
- start_frame_nr
+ 1;
15571 *n_values_per_frame
= data
->n_values_per_frame
;
15572 *type
= data
->datatype
;
15576 if(tng_data_values_alloc(tng_data
, values
, n_frames
,
15577 *n_values_per_frame
,
15578 *type
) != TNG_SUCCESS
)
15580 return(TNG_CRITICAL
);
15584 current_frame_pos
= start_frame_nr
- frame_set
->first_frame
;
15585 /* It's not very elegant to reuse so much of the code in the different case
15586 * statements, but it's unnecessarily slow to have the switch-case block
15587 * inside the for loops. */
15590 case TNG_CHAR_DATA
:
15591 for(i
=0; i
<n_frames
; i
++)
15593 if(current_frame_pos
== frame_set
->n_frames
)
15595 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
15596 if(stat
!= TNG_SUCCESS
)
15600 current_frame_pos
= 0;
15602 for(j
= 0; j
< *n_values_per_frame
; j
++)
15604 len
= strlen(data
->strings
[current_frame_pos
][j
]) + 1;
15605 (*values
)[i
][j
].c
= malloc(len
);
15606 strncpy((*values
)[i
][j
].c
, data
->strings
[current_frame_pos
][j
], len
);
15608 current_frame_pos
++;
15612 size
= sizeof(int);
15613 for(i
=0; i
<n_frames
; i
++)
15615 if(current_frame_pos
== frame_set
->n_frames
)
15617 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
15618 if(stat
!= TNG_SUCCESS
)
15622 current_frame_pos
= 0;
15624 for(j
= 0; j
< *n_values_per_frame
; j
++)
15626 (*values
)[i
][j
].i
= *(int *)((char *)data
->values
+ size
*
15627 (current_frame_pos
*
15628 (*n_values_per_frame
) + j
));
15630 current_frame_pos
++;
15633 case TNG_FLOAT_DATA
:
15634 size
= sizeof(float);
15635 for(i
=0; i
<n_frames
; i
++)
15637 if(current_frame_pos
== frame_set
->n_frames
)
15639 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
15640 if(stat
!= TNG_SUCCESS
)
15644 current_frame_pos
= 0;
15646 for(j
= 0; j
< *n_values_per_frame
; j
++)
15648 (*values
)[i
][j
].f
= *(float *)((char *)data
->values
+ size
*
15649 (current_frame_pos
*
15650 (*n_values_per_frame
) + j
));
15652 current_frame_pos
++;
15655 case TNG_DOUBLE_DATA
:
15657 size
= sizeof(double);
15658 for(i
=0; i
<n_frames
; i
++)
15660 if(current_frame_pos
== frame_set
->n_frames
)
15662 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
15663 if(stat
!= TNG_SUCCESS
)
15667 current_frame_pos
= 0;
15669 for(j
= 0; j
< *n_values_per_frame
; j
++)
15671 (*values
)[i
][j
].d
= *(double *)((char *)data
->values
+ size
*
15672 (current_frame_pos
*
15673 (*n_values_per_frame
) + j
));
15675 current_frame_pos
++;
15679 data
->last_retrieved_frame
= end_frame_nr
;
15681 return(TNG_SUCCESS
);
15684 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
15685 (tng_trajectory_t tng_data
,
15686 const int64_t block_id
,
15687 const int64_t start_frame_nr
,
15688 const int64_t end_frame_nr
,
15689 const char hash_mode
,
15691 int64_t *stride_length
,
15692 int64_t *n_values_per_frame
,
15695 int64_t n_frames
, tot_n_frames
, n_frames_div
, n_frames_div_2
, first_frame
;
15696 int64_t file_pos
, current_frame_pos
, data_size
, frame_size
;
15697 int64_t last_frame_pos
;
15699 tng_trajectory_frame_set_t frame_set
;
15700 tng_non_particle_data_t np_data
;
15701 tng_gen_block_t block
;
15702 void *current_values
= 0, *temp
;
15703 tng_function_status stat
;
15705 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15706 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15707 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
15708 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15709 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15711 frame_set
= &tng_data
->current_trajectory_frame_set
;
15712 first_frame
= frame_set
->first_frame
;
15714 stat
= tng_frame_set_of_frame_find(tng_data
, start_frame_nr
);
15715 if(stat
!= TNG_SUCCESS
)
15720 /* Do not re-read the frame set and only need the requested block. */
15721 /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
15722 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
15723 if(first_frame
!= frame_set
->first_frame
||
15724 stat
!= TNG_SUCCESS
)
15726 tng_block_init(&block
);
15727 if(stat
!= TNG_SUCCESS
)
15729 fseek(tng_data
->input_file
,
15730 (long)tng_data
->current_trajectory_frame_set_input_file_pos
,
15732 stat
= tng_block_header_read(tng_data
, block
);
15733 if(stat
!= TNG_SUCCESS
)
15735 fprintf(stderr
, "TNG library: Cannot read block header. %s: %d\n",
15736 __FILE__
, __LINE__
);
15740 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
15742 file_pos
= ftell(tng_data
->input_file
);
15743 /* Read until next frame set block */
15744 stat
= tng_block_header_read(tng_data
, block
);
15745 while(file_pos
< tng_data
->input_file_len
&&
15746 stat
!= TNG_CRITICAL
&&
15747 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
15750 if(block
->id
== block_id
)
15752 stat
= tng_block_read_next(tng_data
, block
,
15754 if(stat
!= TNG_CRITICAL
)
15756 file_pos
= ftell(tng_data
->input_file
);
15757 if(file_pos
< tng_data
->input_file_len
)
15759 stat
= tng_block_header_read(tng_data
, block
);
15765 file_pos
+= block
->block_contents_size
+ block
->header_contents_size
;
15766 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
15767 if(file_pos
< tng_data
->input_file_len
)
15769 stat
= tng_block_header_read(tng_data
, block
);
15773 tng_block_destroy(&block
);
15774 if(stat
== TNG_CRITICAL
)
15776 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
15777 file_pos
, __FILE__
, __LINE__
);
15782 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
15783 if(stat
!= TNG_SUCCESS
)
15788 stat
= tng_data_vector_get(tng_data
, block_id
, ¤t_values
,
15789 &n_frames
, stride_length
,
15790 n_values_per_frame
, type
);
15792 if(stat
!= TNG_SUCCESS
)
15796 free(current_values
);
15801 if(n_frames
== 1 && n_frames
< frame_set
->n_frames
)
15807 tot_n_frames
= end_frame_nr
- start_frame_nr
+ 1;
15812 case TNG_CHAR_DATA
:
15813 return(TNG_FAILURE
);
15815 size
= sizeof(int64_t);
15817 case TNG_FLOAT_DATA
:
15818 size
= sizeof(float);
15820 case TNG_DOUBLE_DATA
:
15822 size
= sizeof(double);
15825 n_frames_div
= (tot_n_frames
% *stride_length
) ?
15826 tot_n_frames
/ *stride_length
+ 1:
15827 tot_n_frames
/ *stride_length
;
15828 data_size
= n_frames_div
* size
* (*n_values_per_frame
);
15830 /* fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
15831 size, n_frames_div, data_size);
15833 temp
= realloc(*values
, data_size
);
15836 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
15837 data_size
, __FILE__
, __LINE__
);
15840 return(TNG_CRITICAL
);
15845 if( n_frames
== 1 && n_frames
< frame_set
->n_frames
)
15847 memcpy(*values
, current_values
, size
* (*n_values_per_frame
));
15851 current_frame_pos
= start_frame_nr
- frame_set
->first_frame
;
15853 frame_size
= size
* (*n_values_per_frame
);
15855 last_frame_pos
= tng_min_i64(n_frames
,
15856 end_frame_nr
- start_frame_nr
);
15858 n_frames_div
= current_frame_pos
/ *stride_length
;
15859 n_frames_div_2
= (last_frame_pos
% *stride_length
) ?
15860 last_frame_pos
/ *stride_length
+ 1:
15861 last_frame_pos
/ *stride_length
;
15862 n_frames_div_2
= tng_max_i64(1, n_frames_div_2
);
15864 memcpy(*values
, (char *)current_values
+ n_frames_div
* frame_size
,
15865 n_frames_div_2
* frame_size
);
15867 current_frame_pos
+= n_frames
- current_frame_pos
;
15869 while(current_frame_pos
<= end_frame_nr
- start_frame_nr
)
15871 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
15872 if(stat
!= TNG_SUCCESS
)
15876 free(current_values
);
15883 stat
= tng_data_vector_get(tng_data
, block_id
, ¤t_values
,
15884 &n_frames
, stride_length
,
15885 n_values_per_frame
, type
);
15887 if(stat
!= TNG_SUCCESS
)
15891 free(current_values
);
15898 last_frame_pos
= tng_min_i64(n_frames
,
15899 end_frame_nr
- current_frame_pos
);
15901 n_frames_div
= current_frame_pos
/ *stride_length
;
15902 n_frames_div_2
= (last_frame_pos
% *stride_length
) ?
15903 last_frame_pos
/ *stride_length
+ 1:
15904 last_frame_pos
/ *stride_length
;
15905 n_frames_div_2
= tng_max_i64(1, n_frames_div_2
);
15907 memcpy(((char *)*values
) + n_frames_div
* frame_size
,
15909 n_frames_div_2
* frame_size
);
15911 current_frame_pos
+= n_frames
;
15917 free(current_values
);
15920 np_data
->last_retrieved_frame
= end_frame_nr
;
15922 return(TNG_SUCCESS
);
15925 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15926 (tng_trajectory_t tng_data
,
15927 const int64_t block_id
,
15928 union data_values
****values
,
15930 int64_t *n_particles
,
15931 int64_t *n_values_per_frame
,
15934 int64_t i
, j
, k
, mapping
, file_pos
, i_step
, block_index
;
15937 tng_particle_data_t data
;
15938 tng_trajectory_frame_set_t frame_set
;
15939 tng_gen_block_t block
;
15940 char block_type_flag
;
15941 tng_function_status stat
;
15943 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
15944 TNG_ASSERT(n_frames
, "TNG library: n_frames must not be a NULL pointer.");
15945 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
15946 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
15947 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
15949 frame_set
= &tng_data
->current_trajectory_frame_set
;
15954 if(tng_particle_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
15956 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
15958 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
15962 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
15965 tng_block_init(&block
);
15966 file_pos
= ftell(tng_data
->input_file
);
15967 /* Read all blocks until next frame set block */
15968 stat
= tng_block_header_read(tng_data
, block
);
15969 while(file_pos
< tng_data
->input_file_len
&&
15970 stat
!= TNG_CRITICAL
&&
15971 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
15974 /* Use hash by default */
15975 stat
= tng_block_read_next(tng_data
, block
,
15977 if(stat
!= TNG_CRITICAL
)
15979 file_pos
= ftell(tng_data
->input_file
);
15980 if(file_pos
< tng_data
->input_file_len
)
15982 stat
= tng_block_header_read(tng_data
, block
);
15986 tng_block_destroy(&block
);
15987 if(stat
== TNG_CRITICAL
)
15989 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
15990 file_pos
, __FILE__
, __LINE__
);
15994 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
15996 data
= &frame_set
->tr_particle_data
[i
];
15997 if(data
->block_id
== block_id
)
16000 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
16004 if(block_index
< 0)
16006 return(TNG_FAILURE
);
16011 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
16013 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
16017 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
16021 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
16022 tng_data
->var_num_atoms_flag
)
16024 *n_particles
= frame_set
->n_particles
;
16028 *n_particles
= tng_data
->n_particles
;
16031 *n_frames
= tng_max_i64(1, data
->n_frames
);
16032 *n_values_per_frame
= data
->n_values_per_frame
;
16033 *type
= data
->datatype
;
16037 if(tng_particle_data_values_alloc(tng_data
, values
, *n_frames
,
16038 *n_particles
, *n_values_per_frame
,
16042 return(TNG_CRITICAL
);
16046 /* It's not very elegant to reuse so much of the code in the different case
16047 * statements, but it's unnecessarily slow to have the switch-case block
16048 * inside the for loops. */
16051 case TNG_CHAR_DATA
:
16052 for(i
= 0; i
< *n_frames
; i
++)
16054 for(j
= 0; j
< *n_particles
; j
++)
16056 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16057 for(k
= 0; k
< *n_values_per_frame
; k
++)
16059 len
= strlen(data
->strings
[i
][j
][k
]) + 1;
16060 (*values
)[i
][mapping
][k
].c
= malloc(len
);
16061 strncpy((*values
)[i
][mapping
][k
].c
,
16062 data
->strings
[i
][j
][k
], len
);
16068 size
= sizeof(int);
16069 i_step
= (*n_particles
) * (*n_values_per_frame
);
16070 for(i
= 0; i
< *n_frames
; i
++)
16072 for(j
= 0; j
< *n_particles
; j
++)
16074 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16075 for(k
= 0; k
< *n_values_per_frame
; k
++)
16077 (*values
)[i
][mapping
][k
].i
= *(int *)
16078 ((char *)data
->values
+ size
*
16080 (*n_values_per_frame
) + k
));
16085 case TNG_FLOAT_DATA
:
16086 size
= sizeof(float);
16087 i_step
= (*n_particles
) * (*n_values_per_frame
);
16088 for(i
= 0; i
< *n_frames
; i
++)
16090 for(j
= 0; j
< *n_particles
; j
++)
16092 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16093 for(k
= 0; k
< *n_values_per_frame
; k
++)
16095 (*values
)[i
][mapping
][k
].f
= *(float *)
16096 ((char *)data
->values
+ size
*
16098 (*n_values_per_frame
) + k
));
16103 case TNG_DOUBLE_DATA
:
16105 size
= sizeof(double);
16106 i_step
= (*n_particles
) * (*n_values_per_frame
);
16107 for(i
= 0; i
< *n_frames
; i
++)
16109 for(j
= 0; j
< *n_particles
; j
++)
16111 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16112 for(k
= 0; k
< *n_values_per_frame
; k
++)
16114 (*values
)[i
][mapping
][k
].d
= *(double *)
16115 ((char *)data
->values
+ size
*
16117 (*n_values_per_frame
) + k
));
16123 data
->last_retrieved_frame
= frame_set
->first_frame
+ data
->n_frames
- 1;
16125 return(TNG_SUCCESS
);
16128 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
16129 (tng_trajectory_t tng_data
,
16130 const int64_t block_id
,
16133 int64_t *stride_length
,
16134 int64_t *n_particles
,
16135 int64_t *n_values_per_frame
,
16138 int64_t i
, j
, mapping
, file_pos
, i_step
, data_size
, n_frames_div
;
16139 int64_t block_index
;
16141 tng_particle_data_t data
;
16142 tng_trajectory_frame_set_t frame_set
;
16143 tng_gen_block_t block
;
16145 char block_type_flag
;
16146 tng_function_status stat
;
16148 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16149 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
16150 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
16151 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
16152 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
16154 frame_set
= &tng_data
->current_trajectory_frame_set
;
16159 if(tng_particle_data_find(tng_data
, block_id
, &data
) != TNG_SUCCESS
)
16161 tng_block_init(&block
);
16162 file_pos
= ftell(tng_data
->input_file
);
16163 /* Read all blocks until next frame set block */
16164 stat
= tng_block_header_read(tng_data
, block
);
16165 while(file_pos
< tng_data
->input_file_len
&&
16166 stat
!= TNG_CRITICAL
&&
16167 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
16170 /* Use hash by default */
16171 stat
= tng_block_read_next(tng_data
, block
,
16173 if(stat
!= TNG_CRITICAL
)
16175 file_pos
= ftell(tng_data
->input_file
);
16176 if(file_pos
< tng_data
->input_file_len
)
16178 stat
= tng_block_header_read(tng_data
, block
);
16182 tng_block_destroy(&block
);
16183 if(stat
== TNG_CRITICAL
)
16185 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
16186 file_pos
, __FILE__
, __LINE__
);
16190 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
16192 data
= &frame_set
->tr_particle_data
[i
];
16193 if(data
->block_id
== block_id
)
16199 if(block_index
< 0)
16201 return(TNG_FAILURE
);
16205 if(tng_data
->current_trajectory_frame_set_input_file_pos
> 0)
16207 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
16211 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
16214 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
16215 tng_data
->var_num_atoms_flag
)
16217 *n_particles
= frame_set
->n_particles
;
16221 *n_particles
= tng_data
->n_particles
;
16224 *type
= data
->datatype
;
16228 case TNG_CHAR_DATA
:
16229 return(TNG_FAILURE
);
16231 size
= sizeof(int64_t);
16233 case TNG_FLOAT_DATA
:
16234 size
= sizeof(float);
16236 case TNG_DOUBLE_DATA
:
16238 size
= sizeof(double);
16241 *n_frames
= tng_max_i64(1, data
->n_frames
);
16242 *n_values_per_frame
= data
->n_values_per_frame
;
16243 *stride_length
= data
->stride_length
;
16245 n_frames_div
= (*n_frames
% *stride_length
) ?
16246 *n_frames
/ *stride_length
+ 1:
16247 *n_frames
/ *stride_length
;
16249 data_size
= n_frames_div
* size
* (*n_particles
) *
16250 (*n_values_per_frame
);
16252 temp
= realloc(*values
, data_size
);
16255 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
16256 data_size
, __FILE__
, __LINE__
);
16259 return(TNG_CRITICAL
);
16264 if(frame_set
->n_mapping_blocks
<= 0)
16266 memcpy(*values
, data
->values
, data_size
);
16270 i_step
= (*n_particles
) * (*n_values_per_frame
);
16271 for(i
= 0; i
< *n_frames
; i
++)
16273 for(j
= 0; j
< *n_particles
; j
++)
16275 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16276 memcpy(((char *)*values
) + size
* (i
* i_step
+ mapping
*
16277 (*n_values_per_frame
)),
16278 (char *)data
->values
+ size
*
16279 (i
* i_step
+ j
* (*n_values_per_frame
)),
16280 size
* (*n_values_per_frame
));
16285 data
->last_retrieved_frame
= frame_set
->first_frame
+ data
->n_frames
- 1;
16287 return(TNG_SUCCESS
);
16290 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
16291 (tng_trajectory_t tng_data
,
16292 const int64_t block_id
,
16293 const int64_t start_frame_nr
,
16294 const int64_t end_frame_nr
,
16295 const char hash_mode
,
16296 union data_values
****values
,
16297 int64_t *n_particles
,
16298 int64_t *n_values_per_frame
,
16301 int64_t i
, j
, k
, mapping
, n_frames
, file_pos
, current_frame_pos
, i_step
;
16302 int64_t first_frame
, block_index
;
16305 tng_particle_data_t data
;
16306 tng_trajectory_frame_set_t frame_set
;
16307 tng_gen_block_t block
;
16308 char block_type_flag
;
16309 tng_function_status stat
;
16311 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16312 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16313 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
16314 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
16315 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
16319 frame_set
= &tng_data
->current_trajectory_frame_set
;
16320 first_frame
= frame_set
->first_frame
;
16322 stat
= tng_frame_set_of_frame_find(tng_data
, start_frame_nr
);
16323 if(stat
!= TNG_SUCCESS
)
16328 /* Do not re-read the frame set. */
16329 if(first_frame
!= frame_set
->first_frame
||
16330 frame_set
->n_particle_data_blocks
<= 0)
16332 tng_block_init(&block
);
16333 file_pos
= ftell(tng_data
->input_file
);
16334 /* Read all blocks until next frame set block */
16335 stat
= tng_block_header_read(tng_data
, block
);
16336 while(file_pos
< tng_data
->input_file_len
&&
16337 stat
!= TNG_CRITICAL
&&
16338 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
16341 stat
= tng_block_read_next(tng_data
, block
,
16343 if(stat
!= TNG_CRITICAL
)
16345 file_pos
= ftell(tng_data
->input_file
);
16346 if(file_pos
< tng_data
->input_file_len
)
16348 stat
= tng_block_header_read(tng_data
, block
);
16352 tng_block_destroy(&block
);
16353 if(stat
== TNG_CRITICAL
)
16355 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
16356 file_pos
, __FILE__
, __LINE__
);
16361 /* See if there is already a data block of this ID.
16362 * Start checking the last read frame set */
16363 for(i
= frame_set
->n_particle_data_blocks
; i
-- ;)
16365 data
= &frame_set
->tr_particle_data
[i
];
16366 if(data
->block_id
== block_id
)
16369 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
16374 if(block_index
< 0)
16376 fprintf(stderr
, "TNG library: Could not find particle data block with id %"PRId64
". %s: %d\n",
16377 block_id
, __FILE__
, __LINE__
);
16378 return(TNG_FAILURE
);
16381 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
&&
16382 tng_data
->var_num_atoms_flag
)
16384 *n_particles
= frame_set
->n_particles
;
16388 *n_particles
= tng_data
->n_particles
;
16391 n_frames
= end_frame_nr
- start_frame_nr
+ 1;
16392 *n_values_per_frame
= data
->n_values_per_frame
;
16393 *type
= data
->datatype
;
16397 if(tng_particle_data_values_alloc(tng_data
, values
, n_frames
,
16398 *n_particles
, *n_values_per_frame
,
16402 return(TNG_CRITICAL
);
16406 current_frame_pos
= start_frame_nr
- frame_set
->first_frame
;
16407 /* It's not very elegant to reuse so much of the code in the different case
16408 * statements, but it's unnecessarily slow to have the switch-case block
16409 * inside the for loops. */
16412 case TNG_CHAR_DATA
:
16413 for(i
=0; i
<n_frames
; i
++)
16415 if(current_frame_pos
== frame_set
->n_frames
)
16417 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
16418 if(stat
!= TNG_SUCCESS
)
16422 current_frame_pos
= 0;
16424 for(j
= 0; j
< *n_particles
; j
++)
16426 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16427 for(k
= 0; k
< *n_values_per_frame
; k
++)
16429 len
= strlen(data
->strings
[current_frame_pos
][j
][k
]) + 1;
16430 (*values
)[i
][mapping
][k
].c
= malloc(len
);
16431 strncpy((*values
)[i
][mapping
][k
].c
, data
->strings
[current_frame_pos
][j
][k
], len
);
16434 current_frame_pos
++;
16438 size
= sizeof(int);
16439 i_step
= (*n_particles
) * (*n_values_per_frame
);
16440 for(i
=0; i
<n_frames
; i
++)
16442 if(current_frame_pos
== frame_set
->n_frames
)
16444 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
16445 if(stat
!= TNG_SUCCESS
)
16449 current_frame_pos
= 0;
16451 for(j
= 0; j
< *n_particles
; j
++)
16453 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16454 for(k
= 0; k
< *n_values_per_frame
; k
++)
16456 (*values
)[i
][mapping
][k
].i
= *(int *)
16457 ((char *)data
->values
+ size
*
16458 (current_frame_pos
*
16460 (*n_values_per_frame
) + k
));
16463 current_frame_pos
++;
16466 case TNG_FLOAT_DATA
:
16467 size
= sizeof(float);
16468 i_step
= (*n_particles
) * (*n_values_per_frame
);
16469 for(i
=0; i
<n_frames
; i
++)
16471 if(current_frame_pos
== frame_set
->n_frames
)
16473 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
16474 if(stat
!= TNG_SUCCESS
)
16478 current_frame_pos
= 0;
16480 for(j
=0; j
<*n_particles
; j
++)
16482 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16483 for(k
=0; k
<*n_values_per_frame
; k
++)
16485 (*values
)[i
][mapping
][k
].f
= *(float *)
16486 ((char *)data
->values
+ size
*
16487 (current_frame_pos
*
16489 (*n_values_per_frame
) + k
));
16492 current_frame_pos
++;
16495 case TNG_DOUBLE_DATA
:
16497 size
= sizeof(double);
16498 i_step
= (*n_particles
) * (*n_values_per_frame
);
16499 for(i
=0; i
<n_frames
; i
++)
16501 if(current_frame_pos
== frame_set
->n_frames
)
16503 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
16504 if(stat
!= TNG_SUCCESS
)
16508 current_frame_pos
= 0;
16510 for(j
=0; j
<*n_particles
; j
++)
16512 tng_particle_mapping_get_real_particle(frame_set
, j
, &mapping
);
16513 for(k
=0; k
<*n_values_per_frame
; k
++)
16515 (*values
)[i
][mapping
][k
].d
= *(double *)
16516 ((char *)data
->values
+ size
*
16517 (current_frame_pos
*
16519 (*n_values_per_frame
) + k
));
16522 current_frame_pos
++;
16526 data
->last_retrieved_frame
= end_frame_nr
;
16528 return(TNG_SUCCESS
);
16531 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
16532 (tng_trajectory_t tng_data
,
16533 const int64_t block_id
,
16534 const int64_t start_frame_nr
,
16535 const int64_t end_frame_nr
,
16536 const char hash_mode
,
16538 int64_t *n_particles
,
16539 int64_t *stride_length
,
16540 int64_t *n_values_per_frame
,
16543 int64_t n_frames
, tot_n_frames
, n_frames_div
, n_frames_div_2
, first_frame
;
16544 int64_t file_pos
, current_frame_pos
, last_frame_pos
, data_size
, frame_size
;
16546 tng_trajectory_frame_set_t frame_set
;
16547 tng_particle_data_t p_data
;
16548 tng_gen_block_t block
;
16549 void *current_values
= 0, *temp
;
16550 tng_function_status stat
;
16552 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16553 TNG_ASSERT(start_frame_nr
<= end_frame_nr
, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
16554 TNG_ASSERT(n_particles
, "TNG library: n_particles must not be a NULL pointer.");
16555 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer.");
16556 TNG_ASSERT(n_values_per_frame
, "TNG library: n_values_per_frame must not be a NULL pointer.");
16557 TNG_ASSERT(type
, "TNG library: type must not be a NULL pointer.");
16559 frame_set
= &tng_data
->current_trajectory_frame_set
;
16560 first_frame
= frame_set
->first_frame
;
16562 stat
= tng_frame_set_of_frame_find(tng_data
, start_frame_nr
);
16563 if(stat
!= TNG_SUCCESS
)
16568 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
16569 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
16570 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
16571 if(first_frame
!= frame_set
->first_frame
||
16572 stat
!= TNG_SUCCESS
)
16574 tng_block_init(&block
);
16575 if(stat
!= TNG_SUCCESS
)
16577 fseek(tng_data
->input_file
,
16578 (long)tng_data
->current_trajectory_frame_set_input_file_pos
,
16580 stat
= tng_block_header_read(tng_data
, block
);
16581 if(stat
!= TNG_SUCCESS
)
16583 fprintf(stderr
, "TNG library: Cannot read block header. %s: %d\n",
16584 __FILE__
, __LINE__
);
16588 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
16590 file_pos
= ftell(tng_data
->input_file
);
16591 /* Read until next frame set block */
16592 stat
= tng_block_header_read(tng_data
, block
);
16593 while(file_pos
< tng_data
->input_file_len
&&
16594 stat
!= TNG_CRITICAL
&&
16595 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
16598 if(block
->id
== block_id
|| block
->id
== TNG_PARTICLE_MAPPING
)
16600 stat
= tng_block_read_next(tng_data
, block
,
16602 if(stat
!= TNG_CRITICAL
)
16604 file_pos
= ftell(tng_data
->input_file
);
16605 if(file_pos
< tng_data
->input_file_len
)
16607 stat
= tng_block_header_read(tng_data
, block
);
16613 file_pos
+= block
->block_contents_size
+ block
->header_contents_size
;
16614 fseek(tng_data
->input_file
, (long)block
->block_contents_size
, SEEK_CUR
);
16615 if(file_pos
< tng_data
->input_file_len
)
16617 stat
= tng_block_header_read(tng_data
, block
);
16621 tng_block_destroy(&block
);
16622 if(stat
== TNG_CRITICAL
)
16624 fprintf(stderr
, "TNG library: Cannot read block header at pos %"PRId64
". %s: %d\n",
16625 file_pos
, __FILE__
, __LINE__
);
16629 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
16630 if(stat
!= TNG_SUCCESS
)
16635 stat
= tng_particle_data_vector_get(tng_data
, block_id
, ¤t_values
,
16636 &n_frames
, stride_length
, n_particles
,
16637 n_values_per_frame
, type
);
16639 if(stat
!= TNG_SUCCESS
|| *n_particles
== 0)
16643 free(current_values
);
16648 if(n_frames
== 1 && n_frames
< frame_set
->n_frames
)
16654 tot_n_frames
= end_frame_nr
- start_frame_nr
+ 1;
16659 case TNG_CHAR_DATA
:
16660 return(TNG_FAILURE
);
16662 size
= sizeof(int64_t);
16664 case TNG_FLOAT_DATA
:
16665 size
= sizeof(float);
16667 case TNG_DOUBLE_DATA
:
16669 size
= sizeof(double);
16672 n_frames_div
= (tot_n_frames
% *stride_length
) ?
16673 tot_n_frames
/ *stride_length
+ 1:
16674 tot_n_frames
/ *stride_length
;
16676 data_size
= n_frames_div
* size
* (*n_particles
) *
16677 (*n_values_per_frame
);
16679 temp
= realloc(*values
, data_size
);
16682 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
16683 data_size
, __FILE__
, __LINE__
);
16686 return(TNG_CRITICAL
);
16691 if( n_frames
== 1 && n_frames
< frame_set
->n_frames
)
16693 memcpy(*values
, current_values
, size
* (*n_particles
) *
16694 (*n_values_per_frame
));
16698 current_frame_pos
= start_frame_nr
- frame_set
->first_frame
;
16700 frame_size
= size
* (*n_particles
) * (*n_values_per_frame
);
16702 last_frame_pos
= tng_min_i64(n_frames
,
16703 end_frame_nr
- start_frame_nr
);
16705 n_frames_div
= current_frame_pos
/ *stride_length
;
16706 n_frames_div_2
= (last_frame_pos
% *stride_length
) ?
16707 last_frame_pos
/ *stride_length
+ 1:
16708 last_frame_pos
/ *stride_length
;
16709 n_frames_div_2
= tng_max_i64(1, n_frames_div_2
+ 1);
16711 memcpy(*values
, (char *)current_values
+ n_frames_div
* frame_size
,
16712 n_frames_div_2
* frame_size
);
16714 current_frame_pos
+= n_frames
- current_frame_pos
;
16716 while(current_frame_pos
<= end_frame_nr
- start_frame_nr
)
16718 stat
= tng_frame_set_read_next(tng_data
, hash_mode
);
16719 if(stat
!= TNG_SUCCESS
)
16723 free(current_values
);
16730 stat
= tng_particle_data_vector_get(tng_data
, block_id
, ¤t_values
,
16731 &n_frames
, stride_length
, n_particles
,
16732 n_values_per_frame
, type
);
16734 if(stat
!= TNG_SUCCESS
)
16738 free(current_values
);
16745 last_frame_pos
= tng_min_i64(n_frames
,
16746 end_frame_nr
- current_frame_pos
);
16748 n_frames_div
= current_frame_pos
/ *stride_length
;
16749 n_frames_div_2
= (last_frame_pos
% *stride_length
) ?
16750 last_frame_pos
/ *stride_length
+ 1:
16751 last_frame_pos
/ *stride_length
;
16752 n_frames_div_2
= tng_max_i64(1, n_frames_div_2
);
16754 memcpy(((char *)*values
) + n_frames_div
* frame_size
,
16756 n_frames_div_2
* frame_size
);
16758 current_frame_pos
+= n_frames
;
16764 free(current_values
);
16767 p_data
->last_retrieved_frame
= end_frame_nr
;
16769 return(TNG_SUCCESS
);
16772 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
16773 (const tng_trajectory_t tng_data
,
16774 const int64_t block_id
,
16776 int64_t *stride_length
)
16778 tng_function_status stat
;
16779 tng_non_particle_data_t np_data
;
16780 tng_particle_data_t p_data
;
16781 long orig_file_pos
, file_pos
;
16782 int is_particle_data
;
16784 if(tng_data
->current_trajectory_frame_set_input_file_pos
<= 0)
16791 stat
= tng_frame_set_of_frame_find(tng_data
, frame
);
16792 if(stat
!= TNG_SUCCESS
)
16797 orig_file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
16798 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
16799 if(stat
!= TNG_SUCCESS
)
16801 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
16802 if(stat
!= TNG_SUCCESS
)
16804 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
16805 /* If no specific frame was required read until this data block is found */
16808 file_pos
= ftell(tng_data
->input_file
);
16809 while(stat
!= TNG_SUCCESS
&& file_pos
< tng_data
->input_file_len
)
16811 stat
= tng_frame_set_read_next_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
16812 file_pos
= ftell(tng_data
->input_file
);
16815 if(stat
!= TNG_SUCCESS
)
16817 tng_reread_frame_set_at_file_pos(tng_data
, orig_file_pos
);
16821 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
16822 if(stat
!= TNG_SUCCESS
)
16824 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
16825 if(stat
!= TNG_SUCCESS
)
16827 tng_reread_frame_set_at_file_pos(tng_data
, orig_file_pos
);
16833 is_particle_data
= 1;
16838 is_particle_data
= 0;
16843 is_particle_data
= 1;
16848 is_particle_data
= 0;
16850 if(is_particle_data
)
16852 *stride_length
= p_data
->stride_length
;
16856 *stride_length
= np_data
->stride_length
;
16858 tng_reread_frame_set_at_file_pos(tng_data
, orig_file_pos
);
16860 return(TNG_SUCCESS
);
16863 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
16864 (const tng_trajectory_t tng_data
,
16867 struct tm
*time_data
;
16870 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
16871 TNG_ASSERT(time
, "TNG library: time must not be a NULL pointer");
16873 secs
= tng_data
->time
;
16875 time_data
= localtime(&secs
); /* Returns a statically allocated variable. */
16876 TNG_SNPRINTF(time
, TNG_MAX_DATE_STR_LEN
,
16877 "%4d-%02d-%02d %02d:%02d:%02d",
16878 time_data
->tm_year
+1900, time_data
->tm_mon
+1, time_data
->tm_mday
,
16879 time_data
->tm_hour
, time_data
->tm_min
, time_data
->tm_sec
);
16881 return(TNG_SUCCESS
);
16885 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
16886 (const char *filename
,
16888 tng_trajectory_t
*tng_data_p
)
16890 tng_function_status stat
;
16892 TNG_ASSERT(filename
, "TNG library: filename must not be a NULL pointer.");
16894 if(mode
!= 'r' && mode
!= 'w' && mode
!= 'a')
16896 return(TNG_FAILURE
);
16899 if(tng_trajectory_init(tng_data_p
) != TNG_SUCCESS
)
16901 tng_trajectory_destroy(tng_data_p
);
16902 return(TNG_CRITICAL
);
16905 if(mode
== 'r' || mode
== 'a')
16907 tng_input_file_set(*tng_data_p
, filename
);
16909 /* Read the file headers */
16910 tng_file_headers_read(*tng_data_p
, TNG_USE_HASH
);
16912 stat
= tng_num_frame_sets_get(*tng_data_p
, &(*tng_data_p
)->n_trajectory_frame_sets
);
16914 if(stat
!= TNG_SUCCESS
)
16922 tng_output_file_set(*tng_data_p
, filename
);
16924 else if(mode
== 'a')
16926 if((*tng_data_p
)->output_file
)
16928 fclose((*tng_data_p
)->output_file
);
16930 (*tng_data_p
)->output_file
= (*tng_data_p
)->input_file
;
16931 fseek((*tng_data_p
)->input_file
,
16932 (long)(*tng_data_p
)->last_trajectory_frame_set_input_file_pos
,
16935 stat
= tng_frame_set_read(*tng_data_p
, TNG_USE_HASH
);
16936 if(stat
!= TNG_SUCCESS
)
16938 fprintf(stderr
, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
16939 __FILE__
, __LINE__
);
16941 (*tng_data_p
)->output_file
= 0;
16943 (*tng_data_p
)->first_trajectory_frame_set_output_file_pos
=
16944 (*tng_data_p
)->first_trajectory_frame_set_input_file_pos
;
16945 (*tng_data_p
)->last_trajectory_frame_set_output_file_pos
=
16946 (*tng_data_p
)->last_trajectory_frame_set_input_file_pos
;
16947 (*tng_data_p
)->current_trajectory_frame_set_output_file_pos
=
16948 (*tng_data_p
)->current_trajectory_frame_set_input_file_pos
;
16949 if((*tng_data_p
)->input_file
)
16951 fclose((*tng_data_p
)->input_file
);
16952 (*tng_data_p
)->input_file
= 0;
16954 if((*tng_data_p
)->input_file_path
)
16956 free((*tng_data_p
)->input_file_path
);
16957 (*tng_data_p
)->input_file_path
= 0;
16959 tng_output_append_file_set(*tng_data_p
, filename
);
16961 fseek((*tng_data_p
)->output_file
, 0, SEEK_END
);
16964 return(TNG_SUCCESS
);
16967 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
16968 (tng_trajectory_t
*tng_data_p
)
16970 tng_trajectory_frame_set_t frame_set
;
16972 if(tng_data_p
== 0)
16974 fprintf(stderr
, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
16975 __FILE__
, __LINE__
);
16976 return(TNG_FAILURE
);
16979 if(*tng_data_p
== 0)
16981 return(TNG_SUCCESS
);
16984 frame_set
= &(*tng_data_p
)->current_trajectory_frame_set
;
16986 if(frame_set
->n_unwritten_frames
> 0)
16988 frame_set
->n_frames
= frame_set
->n_unwritten_frames
;
16989 tng_frame_set_write(*tng_data_p
, TNG_USE_HASH
);
16992 return(tng_trajectory_destroy(tng_data_p
));
16995 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
16996 (tng_trajectory_t tng_data
,
16997 const int64_t frame_nr
,
17000 int64_t first_frame
;
17001 tng_trajectory_frame_set_t frame_set
;
17002 tng_function_status stat
;
17004 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17005 TNG_ASSERT(time
, "TNG library: time must not be a NULL pointer");
17007 stat
= tng_frame_set_of_frame_find(tng_data
, frame_nr
);
17008 if(stat
!= TNG_SUCCESS
)
17010 fprintf(stderr
, "TNG library: Cannot find frame nr %"PRId64
". %s: %d\n",
17011 frame_nr
, __FILE__
, __LINE__
);
17015 frame_set
= &tng_data
->current_trajectory_frame_set
;
17016 first_frame
= frame_set
->first_frame
;
17018 if(tng_data
->time_per_frame
<= 0)
17020 return(TNG_FAILURE
);
17023 *time
= frame_set
->first_frame_time
+ (tng_data
->time_per_frame
* (frame_nr
- first_frame
));
17025 return(TNG_SUCCESS
);
17029 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
17030 (tng_trajectory_t tng_data,
17032 int64_t **molecule_cnt_list,
17033 tng_molecule_t *mols)
17035 tng_trajectory_frame_set_t frame_set;
17037 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17038 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
17040 *n_mols = tng_data->n_molecules;
17042 frame_set = &tng_data->current_trajectory_frame_set;
17043 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
17045 *molecule_cnt_list = frame_set->molecule_cnt_list;
17049 *molecule_cnt_list = tng_data->molecule_cnt_list;
17052 *mols = tng_data->molecules;
17054 return(TNG_SUCCESS);
17058 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
17059 (tng_trajectory_t tng_data,
17062 tng_molecule_t *mol)
17064 tng_function_status stat;
17066 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
17067 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
17069 stat = tng_molecule_add(tng_data, name, mol);
17070 if(stat != TNG_SUCCESS)
17074 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17079 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
17080 (tng_trajectory_t tng_data
,
17081 const tng_molecule_t mol
,
17082 int64_t *n_particles
,
17087 char ***chain_names
,
17088 int64_t **chain_ids
)
17096 *n_particles
= mol
->n_atoms
;
17098 *names
= malloc(sizeof(char *) * *n_particles
);
17099 *types
= malloc(sizeof(char *) * *n_particles
);
17100 *res_names
= malloc(sizeof(char *) * *n_particles
);
17101 *chain_names
= malloc(sizeof(char *) * *n_particles
);
17102 *res_ids
= malloc(sizeof(int64_t) * *n_particles
);
17103 *chain_ids
= malloc(sizeof(int64_t) * *n_particles
);
17105 for(i
= 0; i
< *n_particles
; i
++)
17107 atom
= &mol
->atoms
[i
];
17108 res
= atom
->residue
;
17109 chain
= res
->chain
;
17110 (*names
)[i
] = malloc(strlen(atom
->name
));
17111 strcpy(*names
[i
], atom
->name
);
17112 (*types
)[i
] = malloc(strlen(atom
->atom_type
));
17113 strcpy(*types
[i
], atom
->atom_type
);
17114 (*res_names
)[i
] = malloc(strlen(res
->name
));
17115 strcpy(*res_names
[i
], res
->name
);
17116 (*chain_names
)[i
] = malloc(strlen(chain
->name
));
17117 strcpy(*chain_names
[i
], chain
->name
);
17118 (*res_ids
)[i
] = res
->id
;
17119 (*chain_ids
)[i
] = chain
->id
;
17122 return(TNG_SUCCESS
);
17125 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
17126 (tng_trajectory_t tng_data
,
17127 tng_molecule_t mol
,
17128 const int64_t n_particles
,
17129 const char **names
,
17130 const char **types
,
17131 const char **res_names
,
17132 const int64_t *res_ids
,
17133 const char **chain_names
,
17134 const int64_t *chain_ids
)
17138 tng_residue_t residue
;
17140 tng_function_status stat
;
17142 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17143 TNG_ASSERT(names
, "TNG library: names must not be a NULL pointer");
17144 TNG_ASSERT(types
, "TNG library: types must not be a NULL pointer");
17145 TNG_ASSERT(res_names
, "TNG library: res_names must not be a NULL pointer");
17146 TNG_ASSERT(res_ids
, "TNG library: res_ids must not be a NULL pointer");
17147 TNG_ASSERT(chain_names
, "TNG library: chain_names must not be a NULL pointer");
17148 TNG_ASSERT(chain_ids
, "TNG library: chain_ids must not be a NULL pointer");
17150 for(i
= 0; i
< n_particles
; i
++)
17152 if(tng_molecule_chain_find(tng_data
, mol
, chain_names
[i
], chain_ids
[i
],
17153 &chain
) == TNG_FAILURE
)
17155 stat
= tng_molecule_chain_add(tng_data
, mol
, chain_names
[i
],
17157 if(stat
!= TNG_SUCCESS
)
17162 if(tng_chain_residue_find(tng_data
, chain
, res_names
[i
], res_ids
[i
],
17163 &residue
) == TNG_FAILURE
)
17165 stat
= tng_chain_residue_add(tng_data
, chain
, res_names
[i
],
17167 if(stat
!= TNG_SUCCESS
)
17172 stat
= tng_residue_atom_add(tng_data
, residue
, names
[i
], types
[i
], &atom
);
17173 if(stat
!= TNG_SUCCESS
)
17178 return(TNG_SUCCESS
);
17181 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
17182 (tng_trajectory_t tng_data
,
17183 float **positions
, int64_t *stride_length
)
17185 int64_t n_frames
, n_particles
, n_values_per_frame
;
17187 tng_function_status stat
;
17189 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17190 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
17191 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17193 stat
= tng_num_frames_get(tng_data
, &n_frames
);
17194 if(stat
!= TNG_SUCCESS
)
17199 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_POSITIONS
,
17200 0, n_frames
- 1, TNG_USE_HASH
,
17201 (void **)positions
,
17204 &n_values_per_frame
,
17210 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
17211 (tng_trajectory_t tng_data
,
17212 float **velocities
, int64_t *stride_length
)
17214 int64_t n_frames
, n_particles
, n_values_per_frame
;
17216 tng_function_status stat
;
17218 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17219 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
17220 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17222 stat
= tng_num_frames_get(tng_data
, &n_frames
);
17223 if(stat
!= TNG_SUCCESS
)
17228 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_VELOCITIES
,
17229 0, n_frames
- 1, TNG_USE_HASH
,
17230 (void **)velocities
,
17233 &n_values_per_frame
,
17239 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
17240 (tng_trajectory_t tng_data
,
17241 float **forces
, int64_t *stride_length
)
17243 int64_t n_frames
, n_particles
, n_values_per_frame
;
17245 tng_function_status stat
;
17247 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17248 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
17249 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17251 stat
= tng_num_frames_get(tng_data
, &n_frames
);
17252 if(stat
!= TNG_SUCCESS
)
17257 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_FORCES
,
17258 0, n_frames
- 1, TNG_USE_HASH
,
17262 &n_values_per_frame
,
17268 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17269 (tng_trajectory_t tng_data
,
17271 int64_t *stride_length
)
17273 int64_t n_frames
, n_values_per_frame
;
17275 tng_function_status stat
;
17277 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17278 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
17279 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17281 stat
= tng_num_frames_get(tng_data
, &n_frames
);
17282 if(stat
!= TNG_SUCCESS
)
17287 stat
= tng_data_vector_interval_get(tng_data
, TNG_TRAJ_BOX_SHAPE
,
17288 0, n_frames
- 1, TNG_USE_HASH
,
17289 (void **)box_shape
,
17291 &n_values_per_frame
,
17297 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17298 (tng_trajectory_t tng_data
,
17299 const int64_t block_id
,
17302 int64_t *retrieved_frame_number
,
17303 double *retrieved_time
)
17305 tng_trajectory_frame_set_t frame_set
;
17306 tng_particle_data_t data
= 0;
17307 tng_function_status stat
;
17309 int64_t i
, data_size
, n_particles
;
17313 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17314 TNG_ASSERT(values
, "TNG library: The pointer to the values array must not be a NULL pointer");
17315 TNG_ASSERT(data_type
, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17316 TNG_ASSERT(retrieved_frame_number
, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17317 TNG_ASSERT(retrieved_time
, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17319 frame_set
= &tng_data
->current_trajectory_frame_set
;
17321 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
17322 if(stat
!= TNG_SUCCESS
)
17324 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17325 file_pos
= ftell(tng_data
->input_file
);
17326 while(stat
!= TNG_SUCCESS
&& file_pos
< tng_data
->input_file_len
)
17328 stat
= tng_frame_set_read_next_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17329 file_pos
= ftell(tng_data
->input_file
);
17331 if(stat
!= TNG_SUCCESS
)
17335 stat
= tng_particle_data_find(tng_data
, block_id
, &data
);
17336 if(stat
!= TNG_SUCCESS
)
17341 if(data
->last_retrieved_frame
< 0)
17343 fseek(tng_data
->input_file
,
17344 (long)tng_data
->first_trajectory_frame_set_input_file_pos
,
17346 stat
= tng_frame_set_read(tng_data
, TNG_USE_HASH
);
17347 if(stat
!= TNG_SUCCESS
)
17351 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17352 if(stat
!= TNG_SUCCESS
)
17357 i
= data
->first_frame_with_data
;
17361 if(data
->n_frames
== 1)
17363 i
= data
->last_retrieved_frame
+ 1;
17367 i
= data
->last_retrieved_frame
+ data
->stride_length
;
17369 if(i
< frame_set
->first_frame
|| i
>= frame_set
->first_frame
+ frame_set
->n_frames
)
17371 stat
= tng_frame_set_of_frame_find(tng_data
, i
);
17372 if(stat
!= TNG_SUCCESS
)
17374 /* If the frame set search found the frame set after the starting
17375 * frame set there is a gap in the frame sets. So, even if the frame
17376 * was not found the next frame with data is still in the found
17378 if(stat
== TNG_CRITICAL
)
17382 if(frame_set
->first_frame
+ frame_set
->n_frames
- 1 < i
)
17384 return(TNG_FAILURE
);
17386 i
= frame_set
->first_frame
;
17389 if(data
->last_retrieved_frame
< frame_set
->first_frame
)
17391 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17392 if(stat
!= TNG_SUCCESS
)
17398 data
->last_retrieved_frame
= i
;
17399 *retrieved_frame_number
= i
;
17400 if(frame_set
->first_frame_time
>= 0 && tng_data
->time_per_frame
>= 0)
17402 *retrieved_time
= frame_set
->first_frame_time
+
17403 (i
- frame_set
->first_frame
) *
17404 tng_data
->time_per_frame
;
17408 *retrieved_time
= 0;
17411 if(data
->stride_length
> 1)
17413 i
= (i
- data
->first_frame_with_data
) / data
->stride_length
;
17417 i
= (i
- frame_set
->first_frame
);
17420 tng_num_particles_get(tng_data
, &n_particles
);
17422 *data_type
= data
->datatype
;
17426 case TNG_CHAR_DATA
:
17427 return(TNG_FAILURE
);
17429 size
= sizeof(int64_t);
17431 case TNG_FLOAT_DATA
:
17432 size
= sizeof(float);
17434 case TNG_DOUBLE_DATA
:
17436 size
= sizeof(double);
17439 data_size
= size
* n_particles
* data
->n_values_per_frame
;
17441 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
17442 // i, data_size, size, n_particles, data->n_values_per_frame);
17444 temp
= realloc(*values
, data_size
);
17447 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
17448 data_size
, __FILE__
, __LINE__
);
17451 return(TNG_CRITICAL
);
17456 memcpy(*values
, (char *)data
->values
+ i
* data_size
, data_size
);
17458 return(TNG_SUCCESS
);
17461 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
17462 (tng_trajectory_t tng_data
,
17463 const int64_t block_id
,
17466 int64_t *retrieved_frame_number
,
17467 double *retrieved_time
)
17469 tng_trajectory_frame_set_t frame_set
;
17470 tng_non_particle_data_t data
= 0;
17471 tng_function_status stat
;
17473 int64_t i
, data_size
;
17477 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17478 TNG_ASSERT(values
, "TNG library: The pointer to the values array must not be a NULL pointer");
17479 TNG_ASSERT(data_type
, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
17480 TNG_ASSERT(retrieved_frame_number
, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
17481 TNG_ASSERT(retrieved_time
, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
17483 frame_set
= &tng_data
->current_trajectory_frame_set
;
17485 stat
= tng_data_find(tng_data
, block_id
, &data
);
17486 if(stat
!= TNG_SUCCESS
)
17488 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17489 file_pos
= ftell(tng_data
->input_file
);
17490 while(stat
!= TNG_SUCCESS
&& file_pos
< tng_data
->input_file_len
)
17492 stat
= tng_frame_set_read_next_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17493 file_pos
= ftell(tng_data
->input_file
);
17495 if(stat
!= TNG_SUCCESS
)
17499 stat
= tng_data_find(tng_data
, block_id
, &data
);
17500 if(stat
!= TNG_SUCCESS
)
17505 if(data
->last_retrieved_frame
< 0)
17507 fseek(tng_data
->input_file
,
17508 (long)tng_data
->first_trajectory_frame_set_input_file_pos
,
17510 stat
= tng_frame_set_read(tng_data
, TNG_USE_HASH
);
17511 if(stat
!= TNG_SUCCESS
)
17515 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17516 if(stat
!= TNG_SUCCESS
)
17521 i
= data
->first_frame_with_data
;
17525 if(data
->n_frames
== 1)
17527 i
= data
->last_retrieved_frame
+ 1;
17531 i
= data
->last_retrieved_frame
+ data
->stride_length
;
17533 if(i
< frame_set
->first_frame
|| i
>= frame_set
->first_frame
+ frame_set
->n_frames
)
17535 stat
= tng_frame_set_of_frame_find(tng_data
, i
);
17536 if(stat
!= TNG_SUCCESS
)
17538 /* If the frame set search found the frame set after the starting
17539 * frame set there is a gap in the frame sets. So, even if the frame
17540 * was not found the next frame with data is still in the found
17542 if(stat
== TNG_CRITICAL
)
17546 if(frame_set
->first_frame
+ frame_set
->n_frames
- 1 < i
)
17548 return(TNG_FAILURE
);
17550 i
= frame_set
->first_frame
;
17553 if(data
->last_retrieved_frame
< frame_set
->first_frame
)
17555 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
17556 if(stat
!= TNG_SUCCESS
)
17562 data
->last_retrieved_frame
= i
;
17563 *retrieved_frame_number
= i
;
17564 if(frame_set
->first_frame_time
>= 0 && tng_data
->time_per_frame
>= 0)
17566 *retrieved_time
= frame_set
->first_frame_time
+
17567 (i
- frame_set
->first_frame
) *
17568 tng_data
->time_per_frame
;
17572 *retrieved_time
= 0;
17575 if(data
->stride_length
> 1)
17577 i
= (i
- data
->first_frame_with_data
) / data
->stride_length
;
17581 i
= (i
- frame_set
->first_frame
);
17584 *data_type
= data
->datatype
;
17588 case TNG_CHAR_DATA
:
17589 return(TNG_FAILURE
);
17591 size
= sizeof(int64_t);
17593 case TNG_FLOAT_DATA
:
17594 size
= sizeof(float);
17596 case TNG_DOUBLE_DATA
:
17598 size
= sizeof(double);
17601 data_size
= size
* data
->n_values_per_frame
;
17603 temp
= realloc(*values
, data_size
);
17606 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
17607 data_size
, __FILE__
, __LINE__
);
17610 return(TNG_CRITICAL
);
17615 memcpy(*values
, (char *)data
->values
+ i
* data_size
, data_size
);
17617 return(TNG_SUCCESS
);
17620 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
17621 (tng_trajectory_t tng_data
,
17622 const int64_t first_frame
,
17623 const int64_t last_frame
,
17625 int64_t *stride_length
)
17627 int64_t n_particles
, n_values_per_frame
;
17629 tng_function_status stat
;
17631 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17632 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
17633 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
17634 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17636 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_POSITIONS
,
17637 first_frame
, last_frame
,
17639 (void **)positions
,
17642 &n_values_per_frame
,
17648 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
17649 (tng_trajectory_t tng_data
,
17650 const int64_t first_frame
,
17651 const int64_t last_frame
,
17652 float **velocities
,
17653 int64_t *stride_length
)
17655 int64_t n_particles
, n_values_per_frame
;
17657 tng_function_status stat
;
17659 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17660 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
17661 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
17662 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17664 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_VELOCITIES
,
17665 first_frame
, last_frame
,
17667 (void **)velocities
,
17670 &n_values_per_frame
,
17676 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
17677 (tng_trajectory_t tng_data
,
17678 const int64_t first_frame
,
17679 const int64_t last_frame
,
17681 int64_t *stride_length
)
17683 int64_t n_particles
, n_values_per_frame
;
17685 tng_function_status stat
;
17687 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17688 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
17689 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
17690 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17692 stat
= tng_particle_data_vector_interval_get(tng_data
, TNG_TRAJ_FORCES
,
17693 first_frame
, last_frame
,
17698 &n_values_per_frame
,
17704 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
17705 (tng_trajectory_t tng_data
,
17706 const int64_t first_frame
,
17707 const int64_t last_frame
,
17709 int64_t *stride_length
)
17711 int64_t n_values_per_frame
;
17713 tng_function_status stat
;
17715 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17716 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
17717 TNG_ASSERT(first_frame
<= last_frame
, "TNG library: first_frame must be lower or equal to last_frame.");
17718 TNG_ASSERT(stride_length
, "TNG library: stride_length must not be a NULL pointer");
17720 stat
= tng_data_vector_interval_get(tng_data
, TNG_TRAJ_BOX_SHAPE
,
17721 first_frame
, last_frame
,
17723 (void **)box_shape
,
17725 &n_values_per_frame
,
17731 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17732 (tng_trajectory_t tng_data
,
17734 const int64_t n_values_per_frame
,
17735 const int64_t block_id
,
17736 const char *block_name
,
17737 const char particle_dependency
,
17738 const char compression
)
17740 tng_trajectory_frame_set_t frame_set
;
17741 tng_particle_data_t p_data
;
17742 tng_non_particle_data_t np_data
;
17743 int64_t n_particles
, n_frames
;
17744 tng_function_status stat
;
17746 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17747 TNG_ASSERT(i
>= 0, "TNG library: i (writing interval) must be >= 0.");
17751 fprintf(stderr
, "TNG library: Cannot set writing frequency to %"PRId64
". %s: %d\n",
17752 i
, __FILE__
, __LINE__
);
17753 return(TNG_FAILURE
);
17756 frame_set
= &tng_data
->current_trajectory_frame_set
;
17758 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
17760 n_frames
= tng_data
->frame_set_n_frames
;
17762 stat
= tng_frame_set_new(tng_data
, 0, n_frames
);
17763 if(stat
!= TNG_SUCCESS
)
17765 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
17772 n_frames
= frame_set
->n_frames
;
17775 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
17777 tng_num_particles_get(tng_data
, &n_particles
);
17778 if(n_particles
<= 0)
17780 return(TNG_FAILURE
);
17783 if(tng_particle_data_find(tng_data
, block_id
, &p_data
)
17786 stat
= tng_particle_data_block_add(tng_data
, block_id
,
17789 TNG_TRAJECTORY_BLOCK
,
17790 n_frames
, n_values_per_frame
, i
,
17793 if(stat
!= TNG_SUCCESS
)
17795 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
17796 __FILE__
, __LINE__
);
17799 p_data
= &frame_set
->tr_particle_data
[frame_set
->
17800 n_particle_data_blocks
- 1];
17801 stat
= tng_allocate_particle_data_mem(tng_data
, p_data
, n_frames
,
17803 n_values_per_frame
);
17804 if(stat
!= TNG_SUCCESS
)
17806 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
17807 __FILE__
, __LINE__
);
17813 if(p_data
->stride_length
!= i
)
17815 p_data
->stride_length
= i
;
17816 stat
= tng_allocate_particle_data_mem(tng_data
, p_data
, n_frames
,
17818 n_values_per_frame
);
17819 if(stat
!= TNG_SUCCESS
)
17821 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
17822 __FILE__
, __LINE__
);
17830 if(tng_data_find(tng_data
, block_id
, &np_data
) != TNG_SUCCESS
)
17832 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
17833 TNG_FLOAT_DATA
, TNG_TRAJECTORY_BLOCK
,
17834 n_frames
, n_values_per_frame
,
17835 i
, compression
, 0);
17836 if(stat
!= TNG_SUCCESS
)
17838 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
17839 __FILE__
, __LINE__
);
17842 np_data
= &frame_set
->tr_data
[frame_set
->
17843 n_data_blocks
- 1];
17844 stat
= tng_allocate_data_mem(tng_data
, np_data
, n_frames
,
17845 i
, n_values_per_frame
);
17846 if(stat
!= TNG_SUCCESS
)
17848 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
17849 __FILE__
, __LINE__
);
17855 if(np_data
->stride_length
!= i
)
17857 np_data
->stride_length
= i
;
17858 stat
= tng_allocate_data_mem(tng_data
, np_data
, n_frames
,
17859 i
, n_values_per_frame
);
17860 if(stat
!= TNG_SUCCESS
)
17862 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
17863 __FILE__
, __LINE__
);
17870 return(TNG_SUCCESS
);
17873 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17874 (tng_trajectory_t tng_data
,
17876 const int64_t n_values_per_frame
,
17877 const int64_t block_id
,
17878 const char *block_name
,
17879 const char particle_dependency
,
17880 const char compression
)
17882 tng_trajectory_frame_set_t frame_set
;
17883 tng_particle_data_t p_data
;
17884 tng_non_particle_data_t np_data
;
17885 int64_t n_particles
, n_frames
;
17886 tng_function_status stat
;
17888 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
17889 TNG_ASSERT(i
>= 0, "TNG library: i (writing interval) must be >= 0.");
17893 fprintf(stderr
, "TNG library: Cannot set writing frequency to %"PRId64
". %s: %d\n",
17894 i
, __FILE__
, __LINE__
);
17895 return(TNG_FAILURE
);
17898 frame_set
= &tng_data
->current_trajectory_frame_set
;
17900 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
17902 n_frames
= tng_data
->frame_set_n_frames
;
17904 stat
= tng_frame_set_new(tng_data
, 0, n_frames
);
17905 if(stat
!= TNG_SUCCESS
)
17907 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
17914 n_frames
= frame_set
->n_frames
;
17917 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
17919 tng_num_particles_get(tng_data
, &n_particles
);
17921 if(n_particles
<= 0)
17923 return(TNG_FAILURE
);
17926 if(tng_particle_data_find(tng_data
, block_id
, &p_data
)
17929 stat
= tng_particle_data_block_add(tng_data
, block_id
,
17932 TNG_TRAJECTORY_BLOCK
,
17933 n_frames
, n_values_per_frame
, i
,
17936 if(stat
!= TNG_SUCCESS
)
17938 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
17939 __FILE__
, __LINE__
);
17942 p_data
= &frame_set
->tr_particle_data
[frame_set
->
17943 n_particle_data_blocks
- 1];
17944 stat
= tng_allocate_particle_data_mem(tng_data
, p_data
, n_frames
,
17946 n_values_per_frame
);
17947 if(stat
!= TNG_SUCCESS
)
17949 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
17950 __FILE__
, __LINE__
);
17956 p_data
->stride_length
= i
;
17961 if(tng_data_find(tng_data
, block_id
, &np_data
) != TNG_SUCCESS
)
17963 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
17964 TNG_DOUBLE_DATA
, TNG_TRAJECTORY_BLOCK
,
17965 n_frames
, n_values_per_frame
,
17966 i
, compression
, 0);
17967 if(stat
!= TNG_SUCCESS
)
17969 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
17970 __FILE__
, __LINE__
);
17973 np_data
= &frame_set
->tr_data
[frame_set
->
17974 n_data_blocks
- 1];
17975 stat
= tng_allocate_data_mem(tng_data
, np_data
, n_frames
,
17976 i
, n_values_per_frame
);
17977 if(stat
!= TNG_SUCCESS
)
17979 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
17980 __FILE__
, __LINE__
);
17986 np_data
->stride_length
= i
;
17990 return(TNG_SUCCESS
);
17993 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
17994 (tng_trajectory_t tng_data
,
17996 const int64_t n_values_per_frame
,
17997 const int64_t block_id
,
17998 const char *block_name
,
17999 const char particle_dependency
,
18000 const char compression
)
18002 fprintf(stderr
, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
18003 "See documentation. %s: %d", __FILE__
, __LINE__
);
18004 return(tng_util_generic_write_interval_set(tng_data
, i
, n_values_per_frame
,
18005 block_id
, block_name
,
18006 particle_dependency
,
18009 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18010 (tng_trajectory_t tng_data
,
18013 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18014 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18016 return(tng_util_generic_write_interval_set(tng_data
, i
, 3,
18017 TNG_TRAJ_POSITIONS
,
18019 TNG_PARTICLE_BLOCK_DATA
,
18020 TNG_TNG_COMPRESSION
));
18023 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
18024 (tng_trajectory_t tng_data
,
18027 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18028 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18030 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 3,
18031 TNG_TRAJ_POSITIONS
,
18033 TNG_PARTICLE_BLOCK_DATA
,
18034 TNG_TNG_COMPRESSION
));
18037 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
18038 (tng_trajectory_t tng_data
,
18041 fprintf(stderr
, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
18042 "See documentation. %s: %d", __FILE__
, __LINE__
);
18043 return(tng_util_pos_write_interval_set(tng_data
, i
));
18046 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
18047 (tng_trajectory_t tng_data
,
18050 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18051 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18053 return(tng_util_generic_write_interval_set(tng_data
, i
, 3,
18054 TNG_TRAJ_VELOCITIES
,
18056 TNG_PARTICLE_BLOCK_DATA
,
18057 TNG_TNG_COMPRESSION
));
18060 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
18061 (tng_trajectory_t tng_data
,
18064 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18065 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18067 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 3,
18068 TNG_TRAJ_VELOCITIES
,
18070 TNG_PARTICLE_BLOCK_DATA
,
18071 TNG_TNG_COMPRESSION
));
18074 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
18075 (tng_trajectory_t tng_data
,
18078 fprintf(stderr
, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
18079 "See documentation. %s: %d", __FILE__
, __LINE__
);
18080 return(tng_util_vel_write_interval_set(tng_data
, i
));
18083 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
18084 (tng_trajectory_t tng_data
,
18087 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18088 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18090 return(tng_util_generic_write_interval_set(tng_data
, i
, 3,
18093 TNG_PARTICLE_BLOCK_DATA
,
18094 TNG_GZIP_COMPRESSION
));
18097 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
18098 (tng_trajectory_t tng_data
,
18101 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18102 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18104 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 3,
18107 TNG_PARTICLE_BLOCK_DATA
,
18108 TNG_GZIP_COMPRESSION
));
18111 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
18112 (tng_trajectory_t tng_data
,
18115 fprintf(stderr
, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
18116 "See documentation. %s: %d", __FILE__
, __LINE__
);
18117 return(tng_util_force_write_interval_set(tng_data
, i
));
18120 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
18121 (tng_trajectory_t tng_data
,
18124 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18125 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18127 return(tng_util_generic_write_interval_set(tng_data
, i
, 9,
18128 TNG_TRAJ_BOX_SHAPE
,
18130 TNG_NON_PARTICLE_BLOCK_DATA
,
18131 TNG_GZIP_COMPRESSION
));
18134 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
18135 (tng_trajectory_t tng_data
,
18138 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18139 TNG_ASSERT(i
> 0, "TNG library: i (writing interval) must be >= 0.");
18141 return(tng_util_generic_write_interval_double_set(tng_data
, i
, 9,
18142 TNG_TRAJ_BOX_SHAPE
,
18144 TNG_NON_PARTICLE_BLOCK_DATA
,
18145 TNG_GZIP_COMPRESSION
));
18148 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
18149 (tng_trajectory_t tng_data
,
18152 fprintf(stderr
, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
18153 "See documentation. %s: %d", __FILE__
, __LINE__
);
18154 return(tng_util_box_shape_write_interval_set(tng_data
, i
));
18157 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
18158 (tng_trajectory_t tng_data
,
18159 const int64_t frame_nr
,
18160 const float *values
,
18161 const int64_t n_values_per_frame
,
18162 const int64_t block_id
,
18163 const char *block_name
,
18164 const char particle_dependency
,
18165 const char compression
)
18167 tng_trajectory_frame_set_t frame_set
;
18168 tng_particle_data_t p_data
;
18169 tng_non_particle_data_t np_data
;
18170 int64_t n_particles
= 0, n_frames
, stride_length
= 100, frame_pos
;
18171 int64_t last_frame
;
18172 int is_first_frame_flag
= 0;
18173 char block_type_flag
;
18174 tng_function_status stat
;
18176 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18177 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18178 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
18180 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
18182 tng_num_particles_get(tng_data
, &n_particles
);
18183 TNG_ASSERT(n_particles
> 0, "TNG library: There must be particles in the system to write particle data.");
18188 return(TNG_FAILURE
);
18191 frame_set
= &tng_data
->current_trajectory_frame_set
;
18195 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
18196 n_frames
= stride_length
= 1;
18200 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
18202 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
18204 stat
= tng_frame_set_new(tng_data
, 0, tng_data
->frame_set_n_frames
);
18205 if(stat
!= TNG_SUCCESS
)
18207 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
18212 last_frame
= frame_set
->first_frame
+
18213 frame_set
->n_frames
- 1;
18214 if(frame_nr
> last_frame
)
18216 stat
= tng_frame_set_write(tng_data
, TNG_USE_HASH
);
18217 if(stat
!= TNG_SUCCESS
)
18219 fprintf(stderr
, "TNG library: Cannot write frame set. %s: %d\n", __FILE__
,
18223 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
18225 last_frame
= frame_nr
- 1;
18227 stat
= tng_frame_set_new(tng_data
, last_frame
+ 1,
18228 tng_data
->frame_set_n_frames
);
18229 if(stat
!= TNG_SUCCESS
)
18231 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
18236 if(frame_set
->n_unwritten_frames
== 0)
18238 is_first_frame_flag
= 1;
18240 frame_set
->n_unwritten_frames
= frame_nr
-
18241 frame_set
->first_frame
+ 1;
18243 n_frames
= frame_set
->n_frames
;
18246 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
18248 if(tng_particle_data_find(tng_data
, block_id
, &p_data
)
18251 stat
= tng_particle_data_block_add(tng_data
, block_id
,
18255 n_frames
, n_values_per_frame
,
18259 if(stat
!= TNG_SUCCESS
)
18261 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
18262 __FILE__
, __LINE__
);
18265 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18267 p_data
= &frame_set
->tr_particle_data
[frame_set
->
18268 n_particle_data_blocks
- 1];
18272 p_data
= &tng_data
->non_tr_particle_data
[tng_data
->
18273 n_particle_data_blocks
- 1];
18275 stat
= tng_allocate_particle_data_mem(tng_data
, p_data
, n_frames
,
18276 stride_length
, n_particles
,
18277 n_values_per_frame
);
18278 if(stat
!= TNG_SUCCESS
)
18280 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
18281 __FILE__
, __LINE__
);
18286 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18288 stride_length
= p_data
->stride_length
;
18290 if(is_first_frame_flag
|| p_data
->first_frame_with_data
< frame_set
->first_frame
)
18292 p_data
->first_frame_with_data
= frame_nr
;
18297 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
18300 memcpy((char *)p_data
->values
+ sizeof(float) * frame_pos
* n_particles
*
18301 n_values_per_frame
, values
, sizeof(float) *
18302 n_particles
* n_values_per_frame
);
18306 memcpy(p_data
->values
, values
, sizeof(float) * n_particles
*
18307 n_values_per_frame
);
18312 if(tng_data_find(tng_data
, block_id
, &np_data
) != TNG_SUCCESS
)
18314 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
18315 TNG_FLOAT_DATA
, block_type_flag
,
18316 n_frames
, n_values_per_frame
,
18317 stride_length
, compression
, 0);
18318 if(stat
!= TNG_SUCCESS
)
18320 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
18321 __FILE__
, __LINE__
);
18324 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18326 np_data
= &frame_set
->tr_data
[frame_set
->
18327 n_data_blocks
- 1];
18331 np_data
= &tng_data
->non_tr_data
[tng_data
->
18332 n_data_blocks
- 1];
18334 stat
= tng_allocate_data_mem(tng_data
, np_data
, n_frames
,
18335 stride_length
, n_values_per_frame
);
18336 if(stat
!= TNG_SUCCESS
)
18338 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
18339 __FILE__
, __LINE__
);
18344 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18346 stride_length
= np_data
->stride_length
;
18348 if(is_first_frame_flag
|| np_data
->first_frame_with_data
< frame_set
->first_frame
)
18350 np_data
->first_frame_with_data
= frame_nr
;
18355 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
18358 memcpy((char *)np_data
->values
+ sizeof(float) * frame_pos
*
18359 n_values_per_frame
, values
, sizeof(float) *
18360 n_values_per_frame
);
18364 memcpy(np_data
->values
, values
, sizeof(float) * n_values_per_frame
);
18368 return(TNG_SUCCESS
);
18371 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
18372 (tng_trajectory_t tng_data
,
18373 const int64_t frame_nr
,
18374 const double *values
,
18375 const int64_t n_values_per_frame
,
18376 const int64_t block_id
,
18377 const char *block_name
,
18378 const char particle_dependency
,
18379 const char compression
)
18381 tng_trajectory_frame_set_t frame_set
;
18382 tng_particle_data_t p_data
;
18383 tng_non_particle_data_t np_data
;
18384 int64_t n_particles
= 0, n_frames
, stride_length
= 100, frame_pos
;
18385 int64_t last_frame
;
18386 int is_first_frame_flag
= 0;
18387 char block_type_flag
;
18388 tng_function_status stat
;
18390 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18391 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18392 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
18394 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
18396 tng_num_particles_get(tng_data
, &n_particles
);
18397 TNG_ASSERT(n_particles
> 0, "TNG library: There must be particles in the system to write particle data.");
18402 return(TNG_FAILURE
);
18405 frame_set
= &tng_data
->current_trajectory_frame_set
;
18409 block_type_flag
= TNG_NON_TRAJECTORY_BLOCK
;
18410 n_frames
= stride_length
= 1;
18414 block_type_flag
= TNG_TRAJECTORY_BLOCK
;
18416 n_frames
= tng_data
->frame_set_n_frames
;
18418 if(!frame_set
|| tng_data
->n_trajectory_frame_sets
<= 0)
18420 stat
= tng_frame_set_new(tng_data
, 0, n_frames
);
18421 if(stat
!= TNG_SUCCESS
)
18423 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
18430 n_frames
= frame_set
->n_frames
;
18432 last_frame
= frame_set
->first_frame
+
18433 frame_set
->n_frames
- 1;
18434 if(frame_nr
> last_frame
)
18436 stat
= tng_frame_set_write(tng_data
, TNG_USE_HASH
);
18437 if(stat
!= TNG_SUCCESS
)
18439 fprintf(stderr
, "TNG library: Cannot write frame set. %s: %d\n", __FILE__
,
18443 if(last_frame
+ tng_data
->frame_set_n_frames
< frame_nr
)
18445 last_frame
= frame_nr
- 1;
18447 stat
= tng_frame_set_new(tng_data
, last_frame
+ 1, n_frames
);
18448 if(stat
!= TNG_SUCCESS
)
18450 fprintf(stderr
, "TNG library: Cannot create frame set. %s: %d\n", __FILE__
,
18455 if(frame_set
->n_unwritten_frames
== 0)
18457 is_first_frame_flag
= 1;
18459 frame_set
->n_unwritten_frames
= frame_nr
-
18460 frame_set
->first_frame
+ 1;
18463 if(particle_dependency
== TNG_PARTICLE_BLOCK_DATA
)
18465 if(tng_particle_data_find(tng_data
, block_id
, &p_data
)
18468 stat
= tng_particle_data_block_add(tng_data
, block_id
,
18472 n_frames
, n_values_per_frame
,
18476 if(stat
!= TNG_SUCCESS
)
18478 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
18479 __FILE__
, __LINE__
);
18482 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18484 p_data
= &frame_set
->tr_particle_data
[frame_set
->
18485 n_particle_data_blocks
- 1];
18489 p_data
= &tng_data
->non_tr_particle_data
[tng_data
->
18490 n_particle_data_blocks
- 1];
18492 stat
= tng_allocate_particle_data_mem(tng_data
, p_data
, n_frames
,
18493 stride_length
, n_particles
,
18494 n_values_per_frame
);
18495 if(stat
!= TNG_SUCCESS
)
18497 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
18498 __FILE__
, __LINE__
);
18503 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18505 stride_length
= p_data
->stride_length
;
18507 if(is_first_frame_flag
)
18509 p_data
->first_frame_with_data
= frame_nr
;
18514 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
18517 memcpy((char *)p_data
->values
+ sizeof(double) * frame_pos
* n_particles
*
18518 n_values_per_frame
, values
, sizeof(double) *
18519 n_particles
* n_values_per_frame
);
18523 memcpy(p_data
->values
, values
, sizeof(double) * n_particles
*
18524 n_values_per_frame
);
18529 if(tng_data_find(tng_data
, block_id
, &np_data
) != TNG_SUCCESS
)
18531 stat
= tng_data_block_add(tng_data
, block_id
, block_name
,
18532 TNG_DOUBLE_DATA
, block_type_flag
,
18533 n_frames
, n_values_per_frame
,
18534 stride_length
, compression
, 0);
18535 if(stat
!= TNG_SUCCESS
)
18537 fprintf(stderr
, "TNG library: Error %s adding data block. %s: %d\n", block_name
,
18538 __FILE__
, __LINE__
);
18541 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18543 np_data
= &frame_set
->tr_data
[frame_set
->
18544 n_data_blocks
- 1];
18548 np_data
= &tng_data
->non_tr_data
[tng_data
->
18549 n_data_blocks
- 1];
18551 stat
= tng_allocate_data_mem(tng_data
, np_data
, n_frames
,
18552 stride_length
, n_values_per_frame
);
18553 if(stat
!= TNG_SUCCESS
)
18555 fprintf(stderr
, "TNG library: Error allocating particle data memory. %s: %d\n",
18556 __FILE__
, __LINE__
);
18561 if(block_type_flag
== TNG_TRAJECTORY_BLOCK
)
18563 stride_length
= np_data
->stride_length
;
18565 if(is_first_frame_flag
)
18567 np_data
->first_frame_with_data
= frame_nr
;
18572 frame_pos
= (frame_nr
- frame_set
->first_frame
) / stride_length
;
18575 memcpy((char *)np_data
->values
+ sizeof(double) * frame_pos
*
18576 n_values_per_frame
, values
, sizeof(double) *
18577 n_values_per_frame
);
18581 memcpy(np_data
->values
, values
, sizeof(double) * n_values_per_frame
);
18585 return(TNG_SUCCESS
);
18588 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
18589 (tng_trajectory_t tng_data
,
18590 const int64_t frame_nr
,
18591 const float *positions
)
18593 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18594 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18595 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
18597 return(tng_util_generic_write(tng_data
, frame_nr
, positions
, 3,
18598 TNG_TRAJ_POSITIONS
, "POSITIONS",
18599 TNG_PARTICLE_BLOCK_DATA
,
18600 TNG_TNG_COMPRESSION
));
18603 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
18604 (tng_trajectory_t tng_data
,
18605 const int64_t frame_nr
,
18606 const double *positions
)
18608 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18609 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18610 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
18612 return(tng_util_generic_double_write(tng_data
, frame_nr
, positions
, 3,
18613 TNG_TRAJ_POSITIONS
, "POSITIONS",
18614 TNG_PARTICLE_BLOCK_DATA
,
18615 TNG_TNG_COMPRESSION
));
18618 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
18619 (tng_trajectory_t tng_data
,
18620 const int64_t frame_nr
,
18621 const float *velocities
)
18623 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18624 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18625 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
18627 return(tng_util_generic_write(tng_data
, frame_nr
, velocities
, 3,
18628 TNG_TRAJ_VELOCITIES
, "VELOCITIES",
18629 TNG_PARTICLE_BLOCK_DATA
,
18630 TNG_TNG_COMPRESSION
));
18633 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
18634 (tng_trajectory_t tng_data
,
18635 const int64_t frame_nr
,
18636 const double *velocities
)
18638 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18639 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18640 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
18642 return(tng_util_generic_double_write(tng_data
, frame_nr
, velocities
, 3,
18643 TNG_TRAJ_VELOCITIES
, "VELOCITIES",
18644 TNG_PARTICLE_BLOCK_DATA
,
18645 TNG_TNG_COMPRESSION
));
18648 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
18649 (tng_trajectory_t tng_data
,
18650 const int64_t frame_nr
,
18651 const float *forces
)
18653 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18654 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18655 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
18657 return(tng_util_generic_write(tng_data
, frame_nr
, forces
, 3,
18658 TNG_TRAJ_FORCES
, "FORCES",
18659 TNG_PARTICLE_BLOCK_DATA
,
18660 TNG_GZIP_COMPRESSION
));
18663 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
18664 (tng_trajectory_t tng_data
,
18665 const int64_t frame_nr
,
18666 const double *forces
)
18668 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18669 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18670 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
18672 return(tng_util_generic_double_write(tng_data
, frame_nr
, forces
, 3,
18673 TNG_TRAJ_FORCES
, "FORCES",
18674 TNG_PARTICLE_BLOCK_DATA
,
18675 TNG_GZIP_COMPRESSION
));
18678 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
18679 (tng_trajectory_t tng_data
,
18680 const int64_t frame_nr
,
18681 const float *box_shape
)
18683 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18684 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18685 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
18687 return(tng_util_generic_write(tng_data
, frame_nr
, box_shape
, 9,
18688 TNG_TRAJ_BOX_SHAPE
, "BOX SHAPE",
18689 TNG_NON_PARTICLE_BLOCK_DATA
,
18690 TNG_GZIP_COMPRESSION
));
18693 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
18694 (tng_trajectory_t tng_data
,
18695 const int64_t frame_nr
,
18696 const double *box_shape
)
18698 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18699 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18700 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
18702 return(tng_util_generic_double_write(tng_data
, frame_nr
, box_shape
, 9,
18703 TNG_TRAJ_BOX_SHAPE
, "BOX SHAPE",
18704 TNG_NON_PARTICLE_BLOCK_DATA
,
18705 TNG_GZIP_COMPRESSION
));
18708 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
18709 (tng_trajectory_t tng_data
,
18710 const int64_t frame_nr
,
18712 const float *values
,
18713 const int64_t n_values_per_frame
,
18714 const int64_t block_id
,
18715 const char *block_name
,
18716 const char particle_dependency
,
18717 const char compression
)
18719 tng_trajectory_frame_set_t frame_set
;
18720 tng_function_status stat
;
18722 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18723 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18724 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18725 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
18727 stat
= tng_util_generic_write(tng_data
, frame_nr
, values
, n_values_per_frame
,
18728 block_id
, block_name
,
18729 particle_dependency
,
18732 if(stat
!= TNG_SUCCESS
)
18737 frame_set
= &tng_data
->current_trajectory_frame_set
;
18739 /* first_frame_time is -1 when it is not yet set. */
18740 if(frame_set
->first_frame_time
< -0.1)
18742 if(frame_nr
> frame_set
->first_frame
)
18744 stat
= tng_frame_set_first_frame_time_set(tng_data
,
18747 frame_set
->first_frame
) *
18748 tng_data
->time_per_frame
);
18752 stat
= tng_frame_set_first_frame_time_set(tng_data
, time
);
18758 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18759 (tng_trajectory_t tng_data
,
18760 const int64_t frame_nr
,
18762 const double *values
,
18763 const int64_t n_values_per_frame
,
18764 const int64_t block_id
,
18765 const char *block_name
,
18766 const char particle_dependency
,
18767 const char compression
)
18769 tng_trajectory_frame_set_t frame_set
;
18770 tng_function_status stat
;
18772 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18773 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18774 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18775 TNG_ASSERT(values
, "TNG library: values must not be a NULL pointer");
18777 stat
= tng_util_generic_double_write(tng_data
, frame_nr
, values
, n_values_per_frame
,
18778 block_id
, block_name
,
18779 particle_dependency
,
18782 if(stat
!= TNG_SUCCESS
)
18787 frame_set
= &tng_data
->current_trajectory_frame_set
;
18789 /* first_frame_time is -1 when it is not yet set. */
18790 if(frame_set
->first_frame_time
< -0.1)
18792 if(frame_nr
> frame_set
->first_frame
)
18794 stat
= tng_frame_set_first_frame_time_set(tng_data
,
18797 frame_set
->first_frame
) *
18798 tng_data
->time_per_frame
);
18802 stat
= tng_frame_set_first_frame_time_set(tng_data
, time
);
18808 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18809 (tng_trajectory_t tng_data
,
18810 const int64_t frame_nr
,
18812 const float *positions
)
18814 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18815 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18816 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18817 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
18819 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
, positions
,
18820 3, TNG_TRAJ_POSITIONS
, "POSITIONS",
18821 TNG_PARTICLE_BLOCK_DATA
,
18822 TNG_TNG_COMPRESSION
));
18825 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
18826 (tng_trajectory_t tng_data
,
18827 const int64_t frame_nr
,
18829 const double *positions
)
18831 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18832 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18833 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18834 TNG_ASSERT(positions
, "TNG library: positions must not be a NULL pointer");
18836 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
, time
,
18838 TNG_TRAJ_POSITIONS
,
18840 TNG_PARTICLE_BLOCK_DATA
,
18841 TNG_TNG_COMPRESSION
));
18844 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
18845 (tng_trajectory_t tng_data
,
18846 const int64_t frame_nr
,
18848 const float *velocities
)
18850 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18851 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18852 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18853 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
18855 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
,
18857 TNG_TRAJ_VELOCITIES
,
18859 TNG_PARTICLE_BLOCK_DATA
,
18860 TNG_TNG_COMPRESSION
));
18863 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
18864 (tng_trajectory_t tng_data
,
18865 const int64_t frame_nr
,
18867 const double *velocities
)
18869 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18870 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18871 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18872 TNG_ASSERT(velocities
, "TNG library: velocities must not be a NULL pointer");
18874 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
, time
,
18876 TNG_TRAJ_VELOCITIES
,
18878 TNG_PARTICLE_BLOCK_DATA
,
18879 TNG_TNG_COMPRESSION
));
18882 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
18883 (tng_trajectory_t tng_data
,
18884 const int64_t frame_nr
,
18886 const float *forces
)
18888 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18889 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18890 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18891 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
18893 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
, forces
,
18894 3, TNG_TRAJ_FORCES
, "FORCES",
18895 TNG_PARTICLE_BLOCK_DATA
,
18896 TNG_GZIP_COMPRESSION
));
18899 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
18900 (tng_trajectory_t tng_data
,
18901 const int64_t frame_nr
,
18903 const double *forces
)
18905 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18906 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18907 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18908 TNG_ASSERT(forces
, "TNG library: forces must not be a NULL pointer");
18910 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
, time
,
18912 TNG_TRAJ_FORCES
, "FORCES",
18913 TNG_PARTICLE_BLOCK_DATA
,
18914 TNG_GZIP_COMPRESSION
));
18917 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
18918 (tng_trajectory_t tng_data
,
18919 const int64_t frame_nr
,
18921 const float *box_shape
)
18923 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18924 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18925 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18926 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
18928 return(tng_util_generic_with_time_write(tng_data
, frame_nr
, time
, box_shape
,
18929 9, TNG_TRAJ_BOX_SHAPE
, "BOX SHAPE",
18930 TNG_NON_PARTICLE_BLOCK_DATA
,
18931 TNG_GZIP_COMPRESSION
));
18934 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
18935 (tng_trajectory_t tng_data
,
18936 const int64_t frame_nr
,
18938 const double *box_shape
)
18940 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18941 TNG_ASSERT(frame_nr
>= 0, "TNG library: frame_nr must be >= 0.");
18942 TNG_ASSERT(time
>= 0, "TNG library: time must be >= 0.");
18943 TNG_ASSERT(box_shape
, "TNG library: box_shape must not be a NULL pointer");
18945 return(tng_util_generic_with_time_double_write(tng_data
, frame_nr
,
18946 time
, box_shape
, 9,
18947 TNG_TRAJ_BOX_SHAPE
,
18949 TNG_NON_PARTICLE_BLOCK_DATA
,
18950 TNG_GZIP_COMPRESSION
));
18953 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
18954 (tng_trajectory_t tng_data
,
18955 const int64_t block_id
,
18959 tng_trajectory_frame_set_t frame_set
;
18960 tng_particle_data_t p_data
= 0;
18961 tng_non_particle_data_t np_data
= 0;
18962 tng_function_status stat
;
18964 int block_type
= -1;
18966 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
18967 TNG_ASSERT(codec_id
, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
18968 TNG_ASSERT(factor
, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
18970 frame_set
= &tng_data
->current_trajectory_frame_set
;
18972 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
18973 if(stat
== TNG_SUCCESS
)
18975 block_type
= TNG_PARTICLE_BLOCK_DATA
;
18979 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
18980 if(stat
== TNG_SUCCESS
)
18982 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
18986 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
18987 if(stat
!= TNG_SUCCESS
)
18991 stat
= tng_particle_data_find(tng_data
, block_id
, &p_data
);
18992 if(stat
== TNG_SUCCESS
)
18994 block_type
= TNG_PARTICLE_BLOCK_DATA
;
18998 stat
= tng_data_find(tng_data
, block_id
, &np_data
);
18999 if(stat
== TNG_SUCCESS
)
19001 block_type
= TNG_NON_PARTICLE_BLOCK_DATA
;
19010 if(block_type
== TNG_PARTICLE_BLOCK_DATA
)
19012 if(p_data
->last_retrieved_frame
< 0)
19014 i
= p_data
->first_frame_with_data
;
19018 i
= p_data
->last_retrieved_frame
;
19021 else if(block_type
== TNG_NON_PARTICLE_BLOCK_DATA
)
19023 if(np_data
->last_retrieved_frame
< 0)
19025 i
= np_data
->first_frame_with_data
;
19029 i
= np_data
->last_retrieved_frame
;
19034 return(TNG_FAILURE
);
19036 if(i
< frame_set
->first_frame
|| i
>= frame_set
->first_frame
+ frame_set
->n_frames
)
19038 stat
= tng_frame_set_of_frame_find(tng_data
, i
);
19039 if(stat
!= TNG_SUCCESS
)
19043 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
, TNG_USE_HASH
, block_id
);
19044 if(stat
!= TNG_SUCCESS
)
19046 fprintf(stderr
, "TNG library: Cannot read data block of frame set. %s: %d\n",
19047 __FILE__
, __LINE__
);
19051 if(block_type
== TNG_PARTICLE_BLOCK_DATA
)
19053 *codec_id
= p_data
->codec_id
;
19054 *factor
= p_data
->compression_multiplier
;
19056 else if(block_type
== TNG_NON_PARTICLE_BLOCK_DATA
)
19058 *codec_id
= np_data
->codec_id
;
19059 *factor
= np_data
->compression_multiplier
;
19061 return(TNG_SUCCESS
);
19064 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
19065 (tng_trajectory_t tng_data
,
19066 int64_t current_frame
,
19067 const int64_t n_requested_data_block_ids
,
19068 const int64_t *requested_data_block_ids
,
19069 int64_t *next_frame
,
19070 int64_t *n_data_blocks_in_next_frame
,
19071 int64_t **data_block_ids_in_next_frame
)
19073 tng_trajectory_frame_set_t frame_set
;
19074 tng_function_status stat
;
19075 tng_particle_data_t p_data
;
19076 tng_non_particle_data_t np_data
;
19077 tng_gen_block_t block
;
19078 int64_t i
, j
, block_id
, *temp
;
19079 int64_t data_frame
, frame_diff
, min_diff
;
19080 int64_t size
, frame_set_file_pos
;
19081 int found
, read_all
= 0;
19084 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
19085 TNG_ASSERT(next_frame
, "TNG library: The pointer to the next frame must not be NULL.");
19086 TNG_ASSERT(n_data_blocks_in_next_frame
, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
19087 TNG_ASSERT(data_block_ids_in_next_frame
, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19089 if(n_requested_data_block_ids
)
19091 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.");
19092 size
= sizeof(int64_t) * n_requested_data_block_ids
;
19093 temp
= realloc(*data_block_ids_in_next_frame
, size
);
19096 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
19097 sizeof(int64_t) * (*n_data_blocks_in_next_frame
),
19098 __FILE__
, __LINE__
);
19099 free(*data_block_ids_in_next_frame
);
19100 *data_block_ids_in_next_frame
= 0;
19101 return(TNG_CRITICAL
);
19103 *data_block_ids_in_next_frame
= temp
;
19106 frame_set
= &tng_data
->current_trajectory_frame_set
;
19108 current_frame
+= 1;
19110 if(current_frame
< frame_set
->first_frame
||
19111 current_frame
>= frame_set
->first_frame
+ frame_set
->n_frames
)
19113 frame_set_file_pos
= tng_data
->current_trajectory_frame_set_input_file_pos
;
19114 stat
= tng_frame_set_of_frame_find(tng_data
, current_frame
);
19115 if(stat
!= TNG_SUCCESS
)
19117 /* If the frame set search found the frame set after the starting
19118 * frame set there is a gap in the frame sets. So, even if the frame
19119 * was not found the next frame with data is still in the found
19121 if(stat
== TNG_CRITICAL
|| frame_set
->prev_frame_set_file_pos
!=
19122 frame_set_file_pos
)
19126 current_frame
= frame_set
->first_frame
;
19130 /* Check for data blocks only if they have not already been found. */
19131 if(frame_set
->n_particle_data_blocks
<= 0 && frame_set
->n_data_blocks
<= 0)
19133 file_pos
= ftell(tng_data
->input_file
);
19134 if(file_pos
< tng_data
->input_file_len
)
19136 tng_block_init(&block
);
19137 stat
= tng_block_header_read(tng_data
, block
);
19138 while(file_pos
< tng_data
->input_file_len
&&
19139 stat
!= TNG_CRITICAL
&&
19140 block
->id
!= TNG_TRAJECTORY_FRAME_SET
&&
19143 stat
= tng_block_read_next(tng_data
, block
,
19145 if(stat
!= TNG_CRITICAL
)
19147 file_pos
= ftell(tng_data
->input_file
);
19148 if(file_pos
< tng_data
->input_file_len
)
19150 stat
= tng_block_header_read(tng_data
, block
);
19154 tng_block_destroy(&block
);
19155 if(stat
== TNG_CRITICAL
)
19157 fprintf(stderr
, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
19158 file_pos
, __FILE__
, __LINE__
);
19167 *n_data_blocks_in_next_frame
= 0;
19169 for(i
= 0; i
< frame_set
->n_particle_data_blocks
; i
++)
19171 p_data
= &frame_set
->tr_particle_data
[i
];
19172 block_id
= p_data
->block_id
;
19174 if(n_requested_data_block_ids
> 0)
19177 for(j
= 0; j
< n_requested_data_block_ids
; j
++)
19179 if(block_id
== requested_data_block_ids
[j
])
19191 if(!read_all
&& (p_data
->last_retrieved_frame
< frame_set
->first_frame
||
19192 p_data
->last_retrieved_frame
>=
19193 frame_set
->first_frame
+ frame_set
->n_frames
))
19195 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
,
19196 TNG_USE_HASH
, block_id
);
19197 if(stat
== TNG_CRITICAL
)
19199 fprintf(stderr
, "TNG library: Cannot read data block of frame set. %s: %d\n",
19200 __FILE__
, __LINE__
);
19203 if(stat
== TNG_FAILURE
)
19208 if(frame_set
->first_frame
!= current_frame
&&
19209 p_data
->last_retrieved_frame
>= 0)
19211 data_frame
= p_data
->last_retrieved_frame
+ p_data
->stride_length
;
19215 data_frame
= p_data
->first_frame_with_data
;
19217 frame_diff
= data_frame
- current_frame
;
19222 if(min_diff
== -1 || frame_diff
<= min_diff
)
19224 if(frame_diff
< min_diff
)
19226 *n_data_blocks_in_next_frame
= 1;
19230 *n_data_blocks_in_next_frame
+= 1;
19232 if(n_requested_data_block_ids
<= 0)
19234 size
= sizeof(int64_t) * (*n_data_blocks_in_next_frame
);
19235 temp
= realloc(*data_block_ids_in_next_frame
, size
);
19238 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
19239 sizeof(int64_t) * (*n_data_blocks_in_next_frame
),
19240 __FILE__
, __LINE__
);
19241 free(*data_block_ids_in_next_frame
);
19242 *data_block_ids_in_next_frame
= 0;
19243 return(TNG_CRITICAL
);
19245 *data_block_ids_in_next_frame
= temp
;
19249 TNG_ASSERT(*n_data_blocks_in_next_frame
<= n_requested_data_block_ids
, "TNG library: Array of data block IDs out of bounds");
19251 (*data_block_ids_in_next_frame
)[(*n_data_blocks_in_next_frame
) - 1] = block_id
;
19253 min_diff
= frame_diff
;
19256 for(i
= 0; i
< frame_set
->n_data_blocks
; i
++)
19258 np_data
= &frame_set
->tr_data
[i
];
19259 block_id
= np_data
->block_id
;
19261 if(n_requested_data_block_ids
> 0)
19264 for(j
= 0; j
< n_requested_data_block_ids
; j
++)
19266 if(block_id
== requested_data_block_ids
[j
])
19278 if(!read_all
&& (np_data
->last_retrieved_frame
< frame_set
->first_frame
||
19279 np_data
->last_retrieved_frame
>=
19280 frame_set
->first_frame
+ frame_set
->n_frames
))
19282 stat
= tng_frame_set_read_current_only_data_from_block_id(tng_data
,
19283 TNG_USE_HASH
, block_id
);
19284 if(stat
== TNG_CRITICAL
)
19286 fprintf(stderr
, "TNG library: Cannot read data block of frame set. %s: %d\n",
19287 __FILE__
, __LINE__
);
19290 if(stat
== TNG_FAILURE
)
19295 if(frame_set
->first_frame
!= current_frame
&&
19296 np_data
->last_retrieved_frame
>= 0)
19298 data_frame
= np_data
->last_retrieved_frame
+ np_data
->stride_length
;
19302 data_frame
= np_data
->first_frame_with_data
;
19304 frame_diff
= data_frame
- current_frame
;
19309 if(min_diff
== -1 || frame_diff
<= min_diff
)
19311 if(frame_diff
< min_diff
)
19313 *n_data_blocks_in_next_frame
= 1;
19317 *n_data_blocks_in_next_frame
+= 1;
19319 if(n_requested_data_block_ids
<= 0)
19321 size
= sizeof(int64_t) * (*n_data_blocks_in_next_frame
);
19322 temp
= realloc(*data_block_ids_in_next_frame
, size
);
19325 fprintf(stderr
, "TNG library: Cannot allocate memory (%"PRId64
" bytes). %s: %d\n",
19326 sizeof(int64_t) * (*n_data_blocks_in_next_frame
),
19327 __FILE__
, __LINE__
);
19328 free(*data_block_ids_in_next_frame
);
19329 *data_block_ids_in_next_frame
= 0;
19330 return(TNG_CRITICAL
);
19332 *data_block_ids_in_next_frame
= temp
;
19336 TNG_ASSERT(*n_data_blocks_in_next_frame
<= n_requested_data_block_ids
, "TNG library: Array of data block IDs out of bounds");
19338 (*data_block_ids_in_next_frame
)[(*n_data_blocks_in_next_frame
) - 1] = block_id
;
19340 min_diff
= frame_diff
;
19345 return(TNG_FAILURE
);
19347 *next_frame
= current_frame
+ min_diff
;
19349 return(TNG_SUCCESS
);
19353 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
19354 (tng_trajectory_t tng_data,
19355 int64_t *n_data_blocks,
19356 int64_t **data_block_ids,
19357 char ***data_block_names,
19358 int64_t **stride_lengths,
19359 int64_t **n_values_per_frame,
19360 char **block_types,
19361 char **dependencies,
19362 char **compressions)
19364 tng_gen_block_t block;
19365 long orig_file_pos, file_pos;
19367 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
19368 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
19369 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
19370 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
19371 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
19373 orig_file_pos = ftell(tng_data->input_file);
19375 if(!tng_data->input_file_len)
19377 fseek(tng_data->input_file, 0, SEEK_END);
19378 tng_data->input_file_len = ftell(tng_data->input_file);
19381 fseek(tng_data->input_file, 0, SEEK_SET);
19384 *n_data_blocks = 0;
19386 tng_block_init(&block);
19388 while(file_pos < tng_data->input_file_len &&
19389 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
19391 if(block->id > TNG_TRAJECTORY_FRAME_SET)
19395 file_pos += (long)(block->block_contents_size + block->header_contents_size);
19396 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
19399 fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
19401 return(TNG_SUCCESS);
19404 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
19405 (tng_trajectory_t tng_data
,
19406 const int64_t prev_frame
)
19408 tng_function_status stat
;
19409 FILE *temp
= tng_data
->input_file
;
19411 TNG_ASSERT(tng_data
, "TNG library: Trajectory container not properly setup.");
19412 TNG_ASSERT(prev_frame
>= 0, "TNG library: The previous frame must not be negative.");
19414 tng_data
->input_file
= tng_data
->output_file
;
19416 stat
= tng_frame_set_of_frame_find(tng_data
, prev_frame
);
19417 if(stat
!= TNG_SUCCESS
)
19422 tng_data
->current_trajectory_frame_set_output_file_pos
=
19423 tng_data
->current_trajectory_frame_set_input_file_pos
;
19425 tng_data
->input_file
= temp
;
19427 return(TNG_SUCCESS
);