Fix bug causing reading next frame not to stop.
[gromacs.git] / src / external / tng_io / src / lib / tng_io.c
blobd0028bd69fcd17cd1943608cb8c4a9eb0ed0b465
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
13 #include <inttypes.h>
14 #endif
16 #include <limits.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <time.h>
20 #include <math.h>
21 #ifdef USE_ZLIB
22 #include <zlib.h>
23 #endif
25 #include "tng/tng_io.h"
26 #include "tng/md5.h"
27 #include "compression/tng_compress.h"
28 #include "tng/version.h"
31 struct tng_bond {
32 /** One of the atoms of the bond */
33 int64_t from_atom_id;
34 /** The other atom of the bond */
35 int64_t to_atom_id;
38 struct tng_atom {
39 /** The residue containing this atom */
40 tng_residue_t residue;
41 /** A unique (per molecule) ID number of the atom */
42 int64_t id;
43 /** The atom_type (depending on the forcefield) */
44 char *atom_type;
45 /** The name of the atom */
46 char *name;
49 struct tng_residue {
50 /** The chain containing this residue */
51 tng_chain_t chain;
52 /** A unique (per chain) ID number of the residue */
53 int64_t id;
54 /** The name of the residue */
55 char *name;
56 /** The number of atoms in the residue */
57 int64_t n_atoms;
58 /** A list of atoms in the residue */
59 int64_t atoms_offset;
62 struct tng_chain {
63 /** The molecule containing this chain */
64 tng_molecule_t molecule;
65 /** A unique (per molecule) ID number of the chain */
66 int64_t id;
67 /** The name of the chain */
68 char *name;
69 /** The number of residues in the chain */
70 int64_t n_residues;
71 /** A list of residues in the chain */
72 tng_residue_t residues;
75 struct tng_molecule {
76 /** A unique ID number of the molecule */
77 int64_t id;
78 /** Quaternary structure of the molecule.
79 * 1 => monomeric
80 * 2 => dimeric
81 * 3 => trimeric
82 * etc */
83 int64_t quaternary_str;
84 /** The number of chains in the molecule */
85 int64_t n_chains;
86 /** The number of residues in the molecule */
87 int64_t n_residues;
88 /** The number of atoms in the molecule */
89 int64_t n_atoms;
90 /** The number of bonds in the molecule. If the bonds are not specified this
91 * value can be 0. */
92 int64_t n_bonds;
93 /** The name of the molecule */
94 char *name;
95 /** A list of chains in the molecule */
96 tng_chain_t chains;
97 /** A list of residues in the molecule */
98 tng_residue_t residues;
99 /** A list of the atoms in the molecule */
100 tng_atom_t atoms;
101 /** A list of the bonds in the molecule */
102 tng_bond_t bonds;
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 */
111 int64_t id;
112 /** The MD5 hash of the block to verify integrity */
113 char md5_hash[TNG_MD5_HASH_LEN];
114 /** The name of the block */
115 char *name;
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;
120 char *alt_hash;
121 int64_t signature_type;
122 int64_t signature_len;
123 char *signature;
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 */
134 int64_t n_particles;
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 */
148 int64_t first_frame;
149 /** The number of frames in this frame set */
150 int64_t n_frames;
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
163 * of atoms */
164 int64_t n_particles;
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 */
186 int n_data_blocks;
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 */
196 int64_t block_id;
197 /** The name of the data block. This is used to determine the kind of
198 * data that is stored */
199 char *block_name;
200 /** The type of data stored. */
201 char datatype;
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 */
205 int64_t n_frames;
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. */
212 int64_t codec_id;
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 */
219 void *values;
220 /** If storing character data store it in a 3-dimensional array */
221 char ****strings;
224 struct tng_non_particle_data {
225 /** The ID of the data block */
226 int64_t block_id;
227 /** The name of the data block. This is used to determine the kind of
228 * data that is stored */
229 char *block_name;
230 /** The type of data stored. */
231 char datatype;
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 */
235 int64_t n_frames;
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. */
242 int64_t codec_id;
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 */
250 void *values;
251 /** If storing character data store it in a 2-dimensional array */
252 char ***strings;
257 struct tng_trajectory {
258 /** The path of the input trajectory file */
259 char *input_file_path;
260 /** A handle to the input file */
261 FILE *input_file;
262 /** The length of the input file */
263 long input_file_len;
264 /** The path of the output trajectory file */
265 char *output_file_path;
266 /** A handle to the output file */
267 FILE *output_file;
268 /** Function to swap 32 bit values to and from the endianness of the
269 * input file */
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
272 * input file */
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
275 * input file */
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
278 * input file */
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 */
281 char endianness_32;
282 /** The endianness of 64 bit values of the current computer */
283 char endianness_64;
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
296 * file */
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
303 * file. */
304 char *last_pgp_signature;
305 /** The time (n seconds since 1970) when the file was created */
306 int64_t time;
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 */
327 int64_t n_molecules;
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 */
335 int64_t n_particles;
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 */
362 int n_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;
374 #ifndef USE_WINDOWS
375 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
376 #define USE_WINDOWS
377 #endif /* win32... */
378 #endif /* not defined USE_WINDOWS */
380 #ifdef USE_WINDOWS
381 #define TNG_INLINE __inline
382 #define TNG_SNPRINTF _snprintf
383 #else
384 #define TNG_INLINE inline
385 #define TNG_SNPRINTF snprintf
386 #endif
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
432 * to big endian.
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 */
451 return(TNG_SUCCESS);
453 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
454 *v = ((*v & 0xFFFF0000) >> 16) |
455 ((*v & 0x0000FFFF) << 16);
457 return(TNG_SUCCESS);
459 case TNG_BIG_ENDIAN_32: /* Already correct */
460 return(TNG_SUCCESS);
462 default:
463 return(TNG_FAILURE);
467 /** This function swaps the byte order of a 64 bit numerical variable
468 * to big endian.
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 */
493 return(TNG_SUCCESS);
495 case TNG_QUAD_SWAP_64: /* Byte quad swap */
496 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
497 ((*v & 0x00000000FFFFFFFFLL) << 32);
499 return(TNG_SUCCESS);
501 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
502 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
503 ((*v & 0x0000FFFF0000FFFFLL) << 16);
505 return(TNG_SUCCESS);
507 case TNG_BYTE_SWAP_64: /* Byte swap */
508 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
509 ((*v & 0x00FF00FF00FF00FFLL) << 8);
511 return(TNG_SUCCESS);
513 case TNG_BIG_ENDIAN_64: /* Already correct */
514 return(TNG_SUCCESS);
516 default:
517 return(TNG_FAILURE);
521 /** This function swaps the byte order of a 32 bit numerical variable
522 * to little endian.
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 */
536 return(TNG_SUCCESS);
538 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
539 *v = ((*v & 0xFF00FF00) >> 8) |
540 ((*v & 0x00FF00FF) << 8);
542 return(TNG_SUCCESS);
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 */
550 return(TNG_SUCCESS);
552 default:
553 return(TNG_FAILURE);
557 /** This function swaps the byte order of a 64 bit numerical variable
558 * to little endian.
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 */
574 return(TNG_SUCCESS);
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);
582 return(TNG_SUCCESS);
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);
590 return(TNG_SUCCESS);
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);
598 return(TNG_SUCCESS);
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 */
610 return(TNG_SUCCESS);
612 default:
613 return(TNG_FAILURE);
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);
630 return(TNG_SUCCESS);
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
640 * set.
642 static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
643 tng_bool *results)
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");
650 *results = TNG_TRUE;
651 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
653 return(TNG_FAILURE);
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;
665 return(TNG_SUCCESS);
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
671 * error has occured.
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",
680 __FILE__, __LINE__);
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);
691 return(TNG_SUCCESS);
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
697 * error has occured.
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",
706 __FILE__, __LINE__);
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);
719 return(TNG_SUCCESS);
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
726 * error has occured.
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));
733 if(!*block_p)
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);
740 block = *block_p;
742 block->id = -1;
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);
745 block->name = 0;
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;
752 return(TNG_SUCCESS);
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
759 * block_p itself.
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;
766 if(!*block_p)
768 return(TNG_SUCCESS);
771 /* fprintf(stderr, "TNG library: Destroying block\n"); */
772 if(block->name)
774 free(block->name);
775 block->name = 0;
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;
788 free(*block_p);
789 *block_p = 0;
791 return(TNG_SUCCESS);
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)
804 int len, offset = 0;
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",
818 __FILE__, __LINE__);
819 return(TNG_CRITICAL);
822 if(block->header_contents_size == 0)
824 block->id = -1;
825 return(TNG_FAILURE);
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
837 * endian */
838 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
840 tng_data->input_endianness_swap_func_32 = 0;
842 else
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;
851 else
853 tng_data->input_endianness_swap_func_64 =
854 &tng_swap_byte_order_little_endian_64;
857 /* File is big endian */
858 else
860 /* If the architecture endianness is big endian no byte swap
861 * will be needed. Otherwise use the functions to swap to big
862 * endian */
863 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
865 tng_data->input_endianness_swap_func_32 = 0;
867 else
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;
876 else
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)
888 != TNG_SUCCESS)
890 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
891 __FILE__, __LINE__);
895 /* Move the reading position to the beginning of the header. */
896 fseek(tng_data->input_file, -(long)sizeof(block->header_contents_size),
897 SEEK_CUR);
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)
935 != TNG_SUCCESS)
937 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
938 __FILE__, __LINE__);
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,
948 &block->id)
949 != TNG_SUCCESS)
951 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
952 __FILE__, __LINE__);
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)
963 free(block->name);
964 block->name = 0;
966 len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
967 if(!block->name)
969 block->name = malloc(len);
970 if(!block->name)
972 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
973 __FILE__, __LINE__);
974 return(TNG_CRITICAL);
976 strncpy(block->name, block->header_contents+offset, len);
978 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)
986 != TNG_SUCCESS)
988 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
989 __FILE__, __LINE__);
993 return(TNG_SUCCESS);
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)
1006 // {
1007 // if(!block->header_contents)
1008 // {
1009 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1010 // return(TNG_FAILURE);
1011 // }
1012 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1013 // tng_data->output_file) != 1)
1014 // {
1015 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1016 // __FILE__, __LINE__);
1017 // return(TNG_CRITICAL);
1018 // }
1020 // if(!block->block_contents)
1021 // {
1022 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1023 // __FILE__, __LINE__);
1024 // return(TNG_FAILURE);
1025 // }
1026 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1027 // tng_data->output_file) != 1)
1028 // {
1029 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1030 // __FILE__, __LINE__);
1031 // return(TNG_CRITICAL);
1032 // }
1033 // return(TNG_SUCCESS);
1034 // }
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
1042 * start.
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),
1075 SEEK_SET);
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,
1131 &pos)
1132 != TNG_SUCCESS)
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,
1150 &pos)
1151 != TNG_SUCCESS)
1153 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1154 __FILE__, __LINE__);
1158 if(fwrite(&pos,
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,
1214 SEEK_SET);
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,
1233 &pos)
1234 != TNG_SUCCESS)
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,
1259 SEEK_SET);
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,
1278 &pos)
1279 != TNG_SUCCESS)
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,
1306 SEEK_SET);
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,
1325 &pos)
1326 != TNG_SUCCESS)
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,
1352 SEEK_SET);
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,
1371 &pos)
1372 != TNG_SUCCESS)
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,
1399 SEEK_SET);
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,
1418 &pos)
1419 != TNG_SUCCESS)
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,
1445 SEEK_SET);
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,
1464 &pos)
1465 != TNG_SUCCESS)
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,
1498 const int64_t pos)
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);
1506 if(pos > 0)
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,
1532 int64_t *pos)
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;
1545 if(*pos <= 0)
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);
1591 return(stat);
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,
1614 int64_t block_len,
1615 int64_t new_pos)
1617 int64_t i;
1618 tng_bool updated = TNG_FALSE;
1620 char *contents;
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);
1630 if(!contents)
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__);
1641 free(contents);
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__);
1650 free(contents);
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;
1662 updated = TNG_TRUE;
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;
1667 updated = TNG_TRUE;
1669 if(updated)
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++)
1677 contents[i] = '\0';
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);
1684 free(contents);
1686 return(TNG_SUCCESS);
1689 static tng_function_status tng_length_of_current_frame_set_contents_get
1690 (tng_trajectory_t tng_data,
1691 int64_t *len)
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;
1700 *len = 0;
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)
1723 break;
1725 stat = tng_block_header_read(tng_data, block);
1726 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1728 break;
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
1744 * block.
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
1751 * data.
1753 static tng_function_status tng_migrate_data_in_file
1754 (tng_trajectory_t tng_data,
1755 int64_t start_pos,
1756 int64_t offset)
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;
1761 FILE *temp;
1763 if(offset <= 0)
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;
1774 return(stat);
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);
1812 return(stat);
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);
1820 return(stat);
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,
1834 int64_t *len)
1836 int name_len;
1837 (void)tng_data;
1839 /* If the string is unallocated allocate memory for just string
1840 * termination */
1841 if(!block->name)
1843 block->name = malloc(1);
1844 if(!block->name)
1846 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1847 __FILE__, __LINE__);
1848 return(TNG_CRITICAL);
1850 block->name[0] = 0;
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) +
1858 sizeof(block->id) +
1859 sizeof(block->block_version) +
1860 TNG_MD5_HASH_LEN +
1861 name_len;
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) !=
1891 TNG_SUCCESS)
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)
1926 != TNG_SUCCESS)
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)
1940 != TNG_SUCCESS)
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)
1953 != TNG_SUCCESS)
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);
1965 offset += 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)
1973 != TNG_SUCCESS)
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,
1991 int64_t *len)
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
2000 * termination */
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,
2102 TNG_MAX_STR_LEN);
2103 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2104 TNG_MAX_STR_LEN);
2105 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2106 TNG_MAX_STR_LEN);
2107 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2108 TNG_MAX_STR_LEN);
2109 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2110 TNG_MAX_STR_LEN);
2111 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2112 TNG_MAX_STR_LEN);
2113 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2114 TNG_MAX_STR_LEN);
2115 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2116 TNG_MAX_STR_LEN);
2117 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2118 TNG_MAX_STR_LEN);
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;
2156 tng_bool same_hash;
2158 void *temp;
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);
2168 if(!temp)
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. "
2196 "%s: %d\n",
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);
2204 if(!temp)
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);
2214 offset += 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);
2218 if(!temp)
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);
2228 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);
2232 if(!temp)
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);
2242 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);
2246 if(!temp)
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);
2256 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);
2260 if(!temp)
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);
2270 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);
2274 if(!temp)
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);
2284 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);
2288 if(!temp)
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);
2298 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);
2302 if(!temp)
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);
2312 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);
2316 if(!temp)
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);
2326 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,
2333 &tng_data->time)
2334 != TNG_SUCCESS)
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)
2352 != TNG_SUCCESS)
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)
2367 != TNG_SUCCESS)
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)
2386 != TNG_SUCCESS)
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)
2400 != TNG_SUCCESS)
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)
2414 != TNG_SUCCESS)
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)
2430 != TNG_SUCCESS)
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;
2457 int offset = 0;
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);
2472 if(!block->name)
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) !=
2484 TNG_SUCCESS)
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,
2493 TNG_MAX_STR_LEN);
2494 last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
2495 TNG_MAX_STR_LEN);
2496 first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
2497 TNG_MAX_STR_LEN);
2498 last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
2499 TNG_MAX_STR_LEN);
2500 first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
2501 TNG_MAX_STR_LEN);
2502 last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
2503 TNG_MAX_STR_LEN);
2504 first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
2505 TNG_MAX_STR_LEN);
2506 last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
2507 TNG_MAX_STR_LEN);
2508 forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
2509 TNG_MAX_STR_LEN);
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)
2562 != TNG_SUCCESS)
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)
2580 != TNG_SUCCESS)
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)
2595 != TNG_SUCCESS)
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)
2610 != TNG_SUCCESS)
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)
2624 != TNG_SUCCESS)
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)
2638 != TNG_SUCCESS)
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)
2652 != TNG_SUCCESS)
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,
2689 tng_chain_t chain,
2690 int *offset)
2692 int len;
2694 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2696 memcpy(&chain->id, block->block_contents+*offset,
2697 sizeof(chain->id));
2698 if(tng_data->input_endianness_swap_func_64)
2700 if(tng_data->input_endianness_swap_func_64(tng_data,
2701 &chain->id)
2702 != TNG_SUCCESS)
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,
2711 TNG_MAX_STR_LEN);
2712 chain->name = malloc(len);
2713 strncpy(chain->name,
2714 block->block_contents+*offset, len);
2715 *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,
2722 &chain->n_residues)
2723 != TNG_SUCCESS)
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,
2743 tng_chain_t chain,
2744 int *offset)
2746 int len;
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)
2755 != TNG_SUCCESS)
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);
2765 *offset += 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)
2773 != TNG_SUCCESS)
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,
2794 int *offset)
2796 int len;
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,
2805 &residue->id)
2806 != TNG_SUCCESS)
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,
2815 TNG_MAX_STR_LEN);
2816 residue->name = malloc(len);
2817 strncpy(residue->name,
2818 block->block_contents+*offset, len);
2819 *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,
2826 &residue->n_atoms)
2827 != TNG_SUCCESS)
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,
2848 int *offset)
2850 int len;
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)
2859 != TNG_SUCCESS)
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);
2869 *offset += 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)
2877 != TNG_SUCCESS)
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,
2897 tng_atom_t atom,
2898 int *offset)
2900 int len;
2902 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2904 memcpy(&atom->id, block->block_contents+*offset,
2905 sizeof(atom->id));
2906 if(tng_data->input_endianness_swap_func_64)
2908 if(tng_data->input_endianness_swap_func_64(tng_data,
2909 &atom->id)
2910 != TNG_SUCCESS)
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,
2919 TNG_MAX_STR_LEN);
2920 atom->name = malloc(len);
2921 strncpy(atom->name,
2922 block->block_contents+*offset, len);
2923 *offset += len;
2925 len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
2926 TNG_MAX_STR_LEN);
2927 atom->atom_type = malloc(len);
2928 strncpy(atom->atom_type,
2929 block->block_contents+*offset, len);
2930 *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,
2944 tng_atom_t atom,
2945 int *offset)
2947 int len;
2949 TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
2951 memcpy(block->block_contents+*offset, &atom->id,
2952 sizeof(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)
2957 != TNG_SUCCESS)
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);
2967 *offset += 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);
2971 *offset += len;
2973 return(TNG_SUCCESS);
2976 static tng_function_status tng_molecules_block_len_calculate
2977 (const tng_trajectory_t tng_data,
2978 int64_t *len)
2980 int64_t i, j;
2981 tng_molecule_t molecule;
2982 tng_chain_t chain;
2983 tng_residue_t residue;
2984 tng_atom_t atom;
2985 tng_bond_t bond;
2987 *len = 0;
2989 for(i = 0; i < tng_data->n_molecules; i++)
2991 molecule = &tng_data->molecules[i];
2992 if(!molecule->name)
2994 molecule->name = malloc(1);
2995 if(!molecule->name)
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);
3010 if(!chain->name)
3012 chain->name = malloc(1);
3013 if(!chain->name)
3015 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3016 __FILE__, __LINE__);
3017 return(TNG_CRITICAL);
3019 chain->name[0] = 0;
3021 *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
3023 *len += sizeof(chain->n_residues);
3025 chain++;
3028 residue = molecule->residues;
3029 for(j = 0; j < molecule->n_residues; j++)
3031 *len += sizeof(residue->id);
3033 if(!residue->name)
3035 residue->name = malloc(1);
3036 if(!residue->name)
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);
3048 residue++;
3051 atom = molecule->atoms;
3052 for(j = 0; j < molecule->n_atoms; j++)
3054 *len += sizeof(atom->id);
3055 if(!atom->name)
3057 atom->name = malloc(1);
3058 if(!atom->name)
3060 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
3061 __FILE__, __LINE__);
3062 return(TNG_CRITICAL);
3064 atom->name[0] = 0;
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);
3081 atom++;
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)
3120 int64_t i, j, k, l;
3121 int len, offset = 0;
3122 tng_molecule_t molecule;
3123 tng_chain_t chain;
3124 tng_residue_t residue;
3125 tng_atom_t atom;
3126 tng_bond_t bond;
3127 tng_bool same_hash;
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. "
3164 "%s: %d\n",
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)
3186 != TNG_SUCCESS)
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,
3238 &molecule->id)
3239 != TNG_SUCCESS)
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);
3251 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)
3259 != TNG_SUCCESS)
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,
3271 sizeof(int64_t));
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])
3276 != TNG_SUCCESS)
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)
3292 != TNG_SUCCESS)
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)
3306 != TNG_SUCCESS)
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,
3319 &molecule->n_atoms)
3320 != TNG_SUCCESS)
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;
3345 else
3347 chain = 0;
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;
3369 else
3371 residue = 0;
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);
3423 atom++;
3425 residue++;
3427 chain++;
3430 else
3432 if(molecule->n_residues > 0)
3434 for(k=0; k<molecule->n_residues; k++)
3436 residue->chain = 0;
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);
3448 atom++;
3450 residue++;
3453 else
3455 for(l=0; l<molecule->n_atoms; l++)
3457 atom->residue = 0;
3459 tng_atom_data_read(tng_data, block, atom, &offset);
3461 atom++;
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,
3471 &molecule->n_bonds)
3472 != TNG_SUCCESS)
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;
3499 if(molecule->atoms)
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)
3517 != TNG_SUCCESS)
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,
3530 &bond->to_atom_id)
3531 != TNG_SUCCESS)
3533 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3534 __FILE__, __LINE__);
3537 offset += sizeof(bond->to_atom_id);
3539 bond++;
3542 else
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;
3563 int64_t i, j, k, l;
3564 tng_molecule_t molecule;
3565 tng_chain_t chain;
3566 tng_residue_t residue;
3567 tng_atom_t atom;
3568 tng_bond_t bond;
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);
3581 if(!block->name)
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) !=
3593 TNG_SUCCESS)
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)
3616 != TNG_SUCCESS)
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)
3633 != TNG_SUCCESS)
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);
3644 offset += 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)
3652 != TNG_SUCCESS)
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)
3668 != TNG_SUCCESS)
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)
3683 != TNG_SUCCESS)
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)
3697 != TNG_SUCCESS)
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)
3711 != TNG_SUCCESS)
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);
3736 atom++;
3738 residue++;
3740 chain++;
3743 else
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);
3757 atom++;
3759 residue++;
3762 else
3764 atom = molecule->atoms;
3765 for(l = 0; l < molecule->n_atoms; l++)
3767 tng_atom_data_write(tng_data, block, atom, &offset);
3769 atom++;
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)
3780 != TNG_SUCCESS)
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)
3797 != TNG_SUCCESS)
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)
3811 != TNG_SUCCESS)
3813 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
3814 __FILE__, __LINE__);
3817 offset += sizeof(bond->to_atom_id);
3819 bond++;
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,
3847 int64_t *len)
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)
3873 long file_pos;
3874 int offset = 0;
3875 int64_t i, prev_n_particles;
3876 tng_bool same_hash;
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. "
3919 "%s: %d\n",
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)
3946 != TNG_SUCCESS)
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)
3960 != TNG_SUCCESS)
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,
3991 sizeof(int64_t));
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])
3996 != TNG_SUCCESS)
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)
4019 != TNG_SUCCESS)
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)
4034 != TNG_SUCCESS)
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)
4049 != TNG_SUCCESS)
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)
4064 != TNG_SUCCESS)
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)
4079 != TNG_SUCCESS)
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)
4094 != TNG_SUCCESS)
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)
4111 != TNG_SUCCESS)
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)
4126 != TNG_SUCCESS)
4128 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4129 __FILE__, __LINE__);
4133 else
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)
4164 char *temp_name;
4165 int64_t i;
4166 int offset = 0;
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);
4181 if(!temp_name)
4183 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4184 name_len+1, __FILE__, __LINE__);
4185 free(block->name);
4186 block->name = 0;
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) !=
4195 TNG_SUCCESS)
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)
4220 != TNG_SUCCESS)
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)
4234 != TNG_SUCCESS)
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],
4248 sizeof(int64_t));
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)
4253 != TNG_SUCCESS)
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)
4270 != TNG_SUCCESS)
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)
4284 != TNG_SUCCESS)
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)
4299 != TNG_SUCCESS)
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)
4314 != TNG_SUCCESS)
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)
4329 != TNG_SUCCESS)
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)
4344 != TNG_SUCCESS)
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)
4359 != TNG_SUCCESS)
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)
4374 != TNG_SUCCESS)
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,
4401 int64_t *len)
4403 (void)tng_data;
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)
4424 int64_t i;
4425 int offset = 0;
4426 tng_bool same_hash;
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. "
4468 "%s: %d\n",
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);
4478 if(!mappings)
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)
4496 != TNG_SUCCESS)
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)
4510 != TNG_SUCCESS)
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 *
4519 sizeof(int64_t));
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,
4535 sizeof(int64_t));
4536 if(tng_data->input_endianness_swap_func_64(tng_data,
4537 &mapping->real_particle_numbers[i])
4538 != TNG_SUCCESS)
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 */
4547 else
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)
4572 char *temp_name;
4573 int i, offset = 0;
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);
4596 if(!temp_name)
4598 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
4599 name_len+1, __FILE__, __LINE__);
4600 free(block->name);
4601 block->name = 0;
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) !=
4612 TNG_SUCCESS)
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)
4637 != TNG_SUCCESS)
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)
4651 != TNG_SUCCESS)
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],
4664 sizeof(int64_t));
4665 if(tng_data->output_endianness_swap_func_64(tng_data,
4666 (int64_t *)block->header_contents+offset)
4667 != TNG_SUCCESS)
4669 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
4670 __FILE__, __LINE__);
4672 offset += sizeof(int64_t);
4675 else
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);
4721 if(!data)
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;
4733 else
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);
4739 if(!data)
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,
4759 const char type,
4760 void *start_pos)
4762 int nalgo;
4763 int new_len;
4764 int *alt_algo = 0;
4765 char *dest, *temp;
4766 int64_t algo_find_n_frames;
4767 unsigned long offset;
4768 float f_precision;
4769 double d_precision;
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,
4806 (int)n_frames,
4807 f_precision,
4808 0, alt_algo,
4809 &new_len);
4812 else
4814 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
4815 (int)n_frames,
4816 d_precision,
4817 0, alt_algo,
4818 &new_len);
4821 else if(!tng_data->compress_algo_pos)
4823 if(n_frames > 10)
4825 algo_find_n_frames = 5;
4827 else
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,
4839 f_precision,
4840 0, tng_data->
4841 compress_algo_pos,
4842 &new_len);
4844 if(algo_find_n_frames < n_frames)
4846 dest = tng_compress_pos_float(start_pos, (int)n_particles,
4847 (int)n_frames,
4848 f_precision,
4849 0, tng_data->compress_algo_pos,
4850 &new_len);
4853 else
4855 dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
4856 (int)algo_find_n_frames,
4857 d_precision,
4858 0, tng_data->
4859 compress_algo_pos,
4860 &new_len);
4862 if(algo_find_n_frames < n_frames)
4864 dest = tng_compress_pos(start_pos, (int)n_particles,
4865 (int)n_frames,
4866 d_precision, 0,
4867 tng_data->compress_algo_pos,
4868 &new_len);
4872 else
4874 if(type == TNG_FLOAT_DATA)
4876 dest = tng_compress_pos_float(start_pos, (int)n_particles,
4877 (int)n_frames,
4878 f_precision, 0,
4879 tng_data->compress_algo_pos, &new_len);
4881 else
4883 dest = tng_compress_pos(start_pos, (int)n_particles,
4884 (int)n_frames,
4885 d_precision, 0,
4886 tng_data->compress_algo_pos,
4887 &new_len);
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,
4903 (int)n_frames,
4904 f_precision,
4905 0, alt_algo,
4906 &new_len);
4909 else
4911 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4912 (int)n_frames,
4913 d_precision,
4914 0, alt_algo,
4915 &new_len);
4918 else if(!tng_data->compress_algo_vel)
4920 if(n_frames > 10)
4922 algo_find_n_frames = 5;
4924 else
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,
4937 f_precision,
4938 0, tng_data->
4939 compress_algo_vel,
4940 &new_len);
4941 if(algo_find_n_frames < n_frames)
4943 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4944 (int)n_frames,
4945 f_precision,
4946 0, tng_data->compress_algo_vel,
4947 &new_len);
4950 else
4952 dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
4953 (int)algo_find_n_frames,
4954 d_precision,
4955 0, tng_data->
4956 compress_algo_vel,
4957 &new_len);
4958 if(algo_find_n_frames < n_frames)
4960 dest = tng_compress_vel(start_pos, (int)n_particles,
4961 (int)n_frames,
4962 d_precision,
4963 0, tng_data->compress_algo_vel,
4964 &new_len);
4968 else
4970 if(type == TNG_FLOAT_DATA)
4972 dest = tng_compress_vel_float(start_pos, (int)n_particles,
4973 (int)n_frames,
4974 f_precision,
4975 0, tng_data->
4976 compress_algo_vel,
4977 &new_len);
4979 else
4981 dest = tng_compress_vel(start_pos, (int)n_particles,
4982 (int)n_frames,
4983 d_precision,
4984 0, tng_data->
4985 compress_algo_vel,
4986 &new_len);
4990 else
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);
4998 if(alt_algo)
5000 free(alt_algo);
5003 block->block_contents_size = new_len + offset;
5005 temp = realloc(block->block_contents, block->block_contents_size);
5006 if(!temp)
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;
5015 if(dest)
5017 memcpy(temp + offset, dest, new_len);
5018 free(dest);
5020 else
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,
5031 const char type,
5032 void *start_pos,
5033 const unsigned long uncompressed_len)
5035 char *temp;
5036 double *d_dest = 0;
5037 float *f_dest = 0;
5038 unsigned long offset;
5039 int result;
5040 (void)tng_data;
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"
5048 "TNG method.\n");
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);
5060 if(!f_dest)
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);
5068 else
5070 d_dest = malloc(uncompressed_len);
5071 if(!d_dest)
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);
5080 if(result == 1)
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);
5091 if(!temp)
5093 free(block->block_contents);
5094 block->block_contents = 0;
5095 if(d_dest)
5097 free(d_dest);
5099 if(f_dest)
5101 free(f_dest);
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);
5112 else
5114 memcpy(temp + offset, d_dest, uncompressed_len);
5117 block->block_contents = temp;
5119 if(d_dest)
5121 free(d_dest);
5123 if(f_dest)
5125 free(f_dest);
5127 return(TNG_SUCCESS);
5130 #ifdef USE_ZLIB
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)
5135 Bytef *dest;
5136 char *temp;
5137 unsigned long max_len, stat, offset;
5138 (void)tng_data;
5140 max_len = compressBound(len);
5141 dest = malloc(max_len);
5142 if(!dest)
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)
5152 free(dest);
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);
5170 if(!temp)
5172 free(block->block_contents);
5173 free(dest);
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);
5184 free(dest);
5186 return(TNG_SUCCESS);
5189 static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
5190 tng_gen_block_t block,
5191 void *start_pos,
5192 unsigned long uncompressed_len)
5194 Bytef *dest;
5195 char *temp;
5196 unsigned long stat;
5197 int offset;
5198 (void)tng_data;
5200 offset = (char *)start_pos - (char *)block->block_contents;
5202 dest = malloc(uncompressed_len);
5203 if(!dest)
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);
5213 if(stat != Z_OK)
5215 free(dest);
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__,
5229 __LINE__);
5230 return(TNG_FAILURE);
5234 block->block_contents_size = uncompressed_len + offset;
5236 temp = realloc(block->block_contents, uncompressed_len + offset);
5237 if(!temp)
5239 free(block->block_contents);
5240 block->block_contents = 0;
5241 free(dest);
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;
5251 free(dest);
5252 return(TNG_SUCCESS);
5254 #endif
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
5260 * data->values.
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
5264 * frame.
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,
5271 int64_t n_frames,
5272 int64_t stride_length,
5273 const int64_t n_particles,
5274 const int64_t n_values_per_frame)
5276 void ***values;
5277 int64_t i, j, k, size, frame_alloc;
5278 (void)tng_data;
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 **) *
5316 n_particles);
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;
5342 else
5344 switch(data->datatype)
5346 case TNG_INT_DATA:
5347 size = sizeof(int64_t);
5348 break;
5349 case TNG_FLOAT_DATA:
5350 size = sizeof(float);
5351 break;
5352 case TNG_DOUBLE_DATA:
5353 default:
5354 size = sizeof(double);
5357 values = realloc(data->values,
5358 size * frame_alloc *
5359 n_particles * n_values_per_frame);
5360 if(!values)
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__);
5366 free(data->values);
5367 data->values = 0;
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,
5377 const int64_t id,
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;
5390 else
5392 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5395 block_index = -1;
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)
5403 block_index = i;
5404 break;
5408 else
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)
5415 block_index = i;
5416 break;
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,
5429 const int64_t id,
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;
5442 else
5444 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5447 block_index = -1;
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)
5455 block_index = i;
5456 break;
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)
5466 block_index = i;
5467 break;
5472 else
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)
5479 block_index = i;
5480 break;
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,
5502 int64_t *len)
5504 int size;
5505 int64_t i, j, k;
5506 char ***first_dim_values, **second_dim_values;
5507 (void)tng_data;
5509 if(data == 0)
5511 return(TNG_SUCCESS);
5514 switch(data->datatype)
5516 case TNG_CHAR_DATA:
5517 size = 1;
5518 break;
5519 case TNG_INT_DATA:
5520 size = sizeof(int64_t);
5521 break;
5522 case TNG_FLOAT_DATA:
5523 size = sizeof(float);
5524 break;
5525 case TNG_DOUBLE_DATA:
5526 default:
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;
5563 j++)
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;
5573 else
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;
5585 else
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
5601 * double).
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
5604 * block.
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
5612 * data block.
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,
5623 int *offset,
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,
5629 int64_t n_frames,
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;
5635 int size, len;
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.");
5645 switch(datatype)
5647 case TNG_CHAR_DATA:
5648 size = 1;
5649 break;
5650 case TNG_INT_DATA:
5651 size = sizeof(int64_t);
5652 break;
5653 case TNG_FLOAT_DATA:
5654 size = sizeof(float);
5655 break;
5656 case TNG_DOUBLE_DATA:
5657 default:
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;
5668 else
5670 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5673 if(tng_particle_data_block_create(tng_data, block_type_flag) !=
5674 TNG_SUCCESS)
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];
5685 else
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;
5703 data->values = 0;
5704 /* FIXME: Memory leak from strings. */
5705 data->strings = 0;
5706 data->n_frames = 0;
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;
5718 else
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);
5728 switch(codec_id)
5730 case TNG_XTC_COMPRESSION:
5731 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5732 break;
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);*/
5744 break;
5745 #ifdef USE_ZLIB
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__,
5753 __LINE__);
5754 return(TNG_CRITICAL);
5756 /* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
5757 break;
5758 #endif
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,
5766 stride_length,
5767 tot_n_particles, n_values) !=
5768 TNG_SUCCESS)
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;
5784 j++)
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,
5790 TNG_MAX_STR_LEN);
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);
5804 *offset += len;
5809 else
5811 memcpy((char *)data->values + n_frames_div * size * n_values *
5812 num_first_particle,
5813 block->block_contents + *offset,
5814 block->block_contents_size - *offset);
5815 switch(datatype)
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))
5824 != TNG_SUCCESS)
5826 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5827 __FILE__, __LINE__);
5831 break;
5832 case TNG_INT_DATA:
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))
5840 != TNG_SUCCESS)
5842 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5843 __FILE__, __LINE__);
5847 break;
5848 case TNG_CHAR_DATA:
5849 break;
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;
5875 int64_t i, j, k;
5876 int size;
5877 size_t len, offset = 0;
5878 char dependency, temp, *temp_name;
5879 double multiplier;
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;
5895 else
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);
5918 else
5920 data = &tng_data->non_tr_particle_data[block_index];
5921 stride_length = 1;
5924 switch(data->datatype)
5926 case TNG_CHAR_DATA:
5927 size = 1;
5928 break;
5929 case TNG_INT_DATA:
5930 size = sizeof(int64_t);
5931 break;
5932 case TNG_FLOAT_DATA:
5933 size = sizeof(float);
5934 break;
5935 case TNG_DOUBLE_DATA:
5936 default:
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);
5945 if(!temp_name)
5947 fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
5948 __FILE__, __LINE__);
5949 free(block->name);
5950 block->name = 0;
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
5960 to be at least 1 */
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;
5994 else
5996 num_first_particle = 0;
5997 if(tng_data->var_num_atoms_flag)
5999 n_particles = frame_set->n_particles;
6001 else
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;
6011 else
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)
6049 temp = 1;
6051 else
6053 temp = 0;
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)
6065 != TNG_SUCCESS)
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)
6079 != TNG_SUCCESS)
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)
6095 != TNG_SUCCESS)
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)
6117 != TNG_SUCCESS)
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)
6131 != TNG_SUCCESS)
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)
6147 != TNG_SUCCESS)
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)
6160 != TNG_SUCCESS)
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)
6170 if(data->strings)
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;
6176 j++)
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);
6184 offset += 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))
6207 != TNG_SUCCESS)
6209 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6210 __FILE__, __LINE__);
6215 else
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))
6227 != TNG_SUCCESS)
6229 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6230 __FILE__, __LINE__);
6235 break;
6236 case TNG_INT_DATA:
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))
6243 != TNG_SUCCESS)
6245 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6246 __FILE__, __LINE__);
6250 break;
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))
6261 != TNG_SUCCESS)
6263 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6264 __FILE__, __LINE__);
6269 else
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))
6281 != TNG_SUCCESS)
6283 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6284 __FILE__, __LINE__);
6289 break;
6290 case TNG_CHAR_DATA:
6291 break;
6294 else
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;
6309 break;
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,
6327 hash_mode);
6328 return(stat);
6330 break;
6331 #ifdef USE_ZLIB
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__,
6340 __LINE__);
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,
6350 hash_mode);
6351 return(stat);
6353 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
6354 break;
6355 #endif
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__,
6370 __LINE__);
6371 return(TNG_CRITICAL);
6374 return(TNG_SUCCESS);
6377 /* TEST: */
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);
6399 if(!data)
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;
6410 else
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);
6415 if(!data)
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);
6430 /* TEST: */
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
6435 * data->values.
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,
6444 int64_t n_frames,
6445 int64_t stride_length,
6446 const int64_t n_values_per_frame)
6448 void **values;
6449 int64_t i, j, size, frame_alloc;
6450 (void)tng_data;
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",
6489 n_values_per_frame,
6490 __FILE__, __LINE__);
6491 return(TNG_CRITICAL);
6493 for(j = 0; j < n_values_per_frame; j++)
6495 data->strings[i][j] = 0;
6499 else
6501 switch(data->datatype)
6503 case TNG_INT_DATA:
6504 size = sizeof(int64_t);
6505 break;
6506 case TNG_FLOAT_DATA:
6507 size = sizeof(float);
6508 break;
6509 case TNG_DOUBLE_DATA:
6510 default:
6511 size = sizeof(double);
6514 values = realloc(data->values,
6515 size * frame_alloc *
6516 n_values_per_frame);
6517 if(!values)
6519 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6520 size * frame_alloc *
6521 n_values_per_frame,
6522 __FILE__, __LINE__);
6523 free(data->values);
6524 data->values = 0;
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
6541 * double).
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,
6556 int *offset,
6557 const char datatype,
6558 const int64_t first_frame_with_data,
6559 const int64_t stride_length,
6560 int64_t n_frames,
6561 const int64_t n_values,
6562 const int64_t codec_id,
6563 const double multiplier)
6565 int64_t i, j, n_frames_div;
6566 int size, len;
6567 #ifdef USE_ZLIB
6568 unsigned long data_size;
6569 #endif
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);*/
6579 switch(datatype)
6581 case TNG_CHAR_DATA:
6582 size = 1;
6583 break;
6584 case TNG_INT_DATA:
6585 size = sizeof(int64_t);
6586 break;
6587 case TNG_FLOAT_DATA:
6588 size = sizeof(float);
6589 break;
6590 case TNG_DOUBLE_DATA:
6591 default:
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;
6602 else
6604 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
6607 if(tng_data_block_create(tng_data, block_type_flag) !=
6608 TNG_SUCCESS)
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];
6618 else
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;
6635 data->values = 0;
6636 /* FIXME: Memory leak from strings. */
6637 data->strings = 0;
6638 data->n_frames = 0;
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)
6648 switch(codec_id)
6650 #ifdef USE_ZLIB
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__,
6659 __LINE__);
6660 return(TNG_CRITICAL);
6662 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6663 break;
6664 #endif
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,
6673 n_values) !=
6674 TNG_SUCCESS)
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,
6691 TNG_MAX_STR_LEN);
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,
6704 len);
6705 *offset += len;
6709 else
6711 memcpy(data->values, block->block_contents + *offset,
6712 block->block_contents_size - *offset);
6713 switch(datatype)
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))
6722 != TNG_SUCCESS)
6724 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6725 __FILE__, __LINE__);
6729 break;
6730 case TNG_INT_DATA:
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))
6738 != TNG_SUCCESS)
6740 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6741 __FILE__, __LINE__);
6745 break;
6746 case TNG_CHAR_DATA:
6747 break;
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;
6769 int64_t i, j;
6770 int offset = 0, size;
6771 unsigned int len;
6772 #ifdef USE_ZLIB
6773 tng_function_status stat;
6774 #endif
6775 char temp, dependency, *temp_name;
6776 double multiplier;
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;
6789 else
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);
6812 else
6814 data = &tng_data->non_tr_data[block_index];
6815 stride_length = 1;
6818 switch(data->datatype)
6820 case TNG_CHAR_DATA:
6821 size = 1;
6822 break;
6823 case TNG_INT_DATA:
6824 size = sizeof(int64_t);
6825 break;
6826 case TNG_FLOAT_DATA:
6827 size = sizeof(float);
6828 break;
6829 case TNG_DOUBLE_DATA:
6830 default:
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);
6839 if(!temp_name)
6841 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
6842 __FILE__, __LINE__);
6843 free(block->name);
6844 block->name = 0;
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
6854 to be at least 1 */
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;
6887 else
6889 dependency = 0;
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)
6925 temp = 1;
6927 else
6929 temp = 0;
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)
6941 != TNG_SUCCESS)
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)
6955 != TNG_SUCCESS)
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)
6971 != TNG_SUCCESS)
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)
6993 != TNG_SUCCESS)
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)
7007 != TNG_SUCCESS)
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)
7018 if(data->strings)
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],
7026 len);
7027 offset += len;
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))
7048 != TNG_SUCCESS)
7050 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7051 __FILE__, __LINE__);
7056 else
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))
7068 != TNG_SUCCESS)
7070 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7071 __FILE__, __LINE__);
7076 break;
7077 case TNG_INT_DATA:
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))
7084 != TNG_SUCCESS)
7086 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7087 __FILE__, __LINE__);
7091 break;
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))
7102 != TNG_SUCCESS)
7104 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7105 __FILE__, __LINE__);
7110 else
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))
7122 != TNG_SUCCESS)
7124 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7125 __FILE__, __LINE__);
7130 break;
7131 case TNG_CHAR_DATA:
7132 break;
7135 else
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)
7147 #ifdef USE_ZLIB
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__,
7156 __LINE__);
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); */
7164 break;
7165 #endif
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,
7197 int *offset,
7198 char *datatype,
7199 char *dependency,
7200 char *sparse_data,
7201 int64_t *n_values,
7202 int64_t *codec_id,
7203 int64_t *first_frame_with_data,
7204 int64_t *stride_length,
7205 int64_t *n_frames,
7206 int64_t *num_first_particle,
7207 int64_t *block_n_particles,
7208 double *multiplier)
7210 int meta_size;
7211 char *contents;
7213 if(block->block_contents)
7215 contents = block->block_contents;
7217 else
7219 meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
7220 contents = malloc(meta_size);
7221 if(!contents)
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__);
7230 free(contents);
7231 return(TNG_CRITICAL);
7235 memcpy(datatype, contents+*offset,
7236 sizeof(*datatype));
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,
7251 sizeof(*n_values));
7252 if(tng_data->input_endianness_swap_func_64)
7254 if(tng_data->input_endianness_swap_func_64(tng_data,
7255 n_values)
7256 != TNG_SUCCESS)
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,
7265 sizeof(*codec_id));
7266 if(tng_data->input_endianness_swap_func_64)
7268 if(tng_data->input_endianness_swap_func_64(tng_data,
7269 codec_id)
7270 != TNG_SUCCESS)
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)
7286 != TNG_SUCCESS)
7288 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
7289 __FILE__, __LINE__);
7292 *offset += sizeof(*multiplier);
7294 else
7296 *multiplier = 1;
7299 if(*dependency & TNG_FRAME_DEPENDENT)
7301 if(*sparse_data)
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)
7309 != TNG_SUCCESS)
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,
7322 stride_length)
7323 != TNG_SUCCESS)
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);
7334 else
7336 *first_frame_with_data = 0;
7337 *stride_length = 1;
7338 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
7341 else
7343 *first_frame_with_data = 0;
7344 *stride_length = 1;
7345 *n_frames = 1;
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,
7355 num_first_particle)
7356 != TNG_SUCCESS)
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,
7369 block_n_particles)
7370 != TNG_SUCCESS)
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)
7381 free(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;
7403 double multiplier;
7404 char datatype, dependency, sparse_data;
7405 int offset = 0;
7406 tng_bool same_hash;
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,
7450 &offset, &datatype,
7451 &dependency, &sparse_data,
7452 &n_values, &codec_id,
7453 &first_frame_with_data,
7454 &stride_length, &n_frames,
7455 &num_first_particle,
7456 &block_n_particles,
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,
7467 &offset, datatype,
7468 num_first_particle,
7469 block_n_particles,
7470 first_frame_with_data,
7471 stride_length,
7472 n_frames, n_values,
7473 codec_id, multiplier));
7475 else
7477 return(tng_data_read(tng_data, block,
7478 &offset, datatype,
7479 first_frame_with_data,
7480 stride_length,
7481 n_frames, n_values,
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!!!
7496 // *
7497 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
7498 // {
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)
7507 // {
7508 // return(TNG_SUCCESS);
7509 // }
7511 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
7512 // tng_data->last_trajectory_frame_set_output_file_pos)
7513 // {
7514 // }
7516 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
7517 // {
7518 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
7519 // __FILE__, __LINE__);
7520 // return(TNG_CRITICAL);
7521 // }
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)
7532 // {
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);
7538 // }
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,
7546 // SEEK_SET);
7548 // while(pos < output_file_len)
7549 // {
7550 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
7551 // {
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);
7557 // }
7558 // pos += block->header_contents_size + block->block_contents_size;
7559 // fseek(tng_data->output_file, pos, SEEK_SET);
7560 // }
7562 // return(TNG_SUCCESS);
7563 // }
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
7567 * == TNG_USE_HASH).
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)
7673 // {
7674 // int len;
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)
7681 // {
7682 // free(block->name);
7683 // block->name = 0;
7684 // }
7685 // if(!block->name)
7686 // {
7687 // block->name = malloc(len);
7688 // if(!block->name)
7689 // {
7690 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
7691 // __FILE__, __LINE__);
7692 // return(TNG_CRITICAL);
7693 // }
7694 // }
7696 // strncpy(block->name, new_name, len);
7698 // return(TNG_SUCCESS);
7699 // }
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)
7706 (void) tng_data;
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,
7717 char *name,
7718 const int max_len)
7720 (void) tng_data;
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,
7735 tng_atom_t atom,
7736 const char *new_name)
7738 unsigned int len;
7739 (void)tng_data;
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)
7750 free(atom->name);
7751 atom->name = 0;
7753 if(!atom->name)
7755 atom->name = malloc(len);
7756 if(!atom->name)
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,
7771 char *type,
7772 const int max_len)
7774 (void) tng_data;
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,
7789 tng_atom_t atom,
7790 const char *new_type)
7792 unsigned int len;
7793 (void)tng_data;
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)
7829 atom->name = 0;
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)
7841 if(atom->name)
7843 free(atom->name);
7844 atom->name = 0;
7846 if(atom->atom_type)
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,
7857 int *version)
7859 (void)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,
7868 int *version)
7870 (void)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,
7879 int *patch_level)
7881 (void)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,
7890 char *version,
7891 const int max_len)
7893 (void)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,
7903 const char *name,
7904 tng_molecule_t *molecule)
7906 int64_t id;
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;
7916 else
7918 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,
7926 const char *name,
7927 const int64_t id,
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));
7941 if(!new_molecules)
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,
7952 sizeof(int64_t) *
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++;
7981 return(stat);
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;
7998 else
8000 id = 1;
8003 new_molecules = realloc(tng_data->molecules,
8004 sizeof(struct tng_molecule) *
8005 (tng_data->n_molecules + 1));
8007 if(!new_molecules)
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,
8018 sizeof(int64_t) *
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;
8041 free(*molecule_p);
8043 molecule = &new_molecules[tng_data->n_molecules];
8045 *molecule_p = molecule;
8047 molecule->id = id;
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,
8056 char *name,
8057 const int max_len)
8059 (void) tng_data;
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)
8078 unsigned int len;
8079 (void)tng_data;
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);
8091 molecule->name = 0;
8093 if(!molecule->name)
8095 molecule->name = malloc(len);
8096 if(!molecule->name)
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,
8112 int64_t *cnt)
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)
8123 index = i;
8124 break;
8127 if(index == -1)
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,
8139 const int64_t cnt)
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)
8149 index = i;
8150 break;
8153 if(index == -1)
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;
8167 else
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,
8181 const char *name,
8182 int64_t nr,
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);
8205 *molecule = 0;
8207 return(TNG_FAILURE);
8210 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
8211 (tng_trajectory_t tng_data,
8212 int64_t index,
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)
8220 *molecule = 0;
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);
8252 if(!molecule_temp)
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);
8263 if(!list_temp)
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,
8281 &molecule_temp);
8282 if(stat != TNG_SUCCESS)
8284 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
8285 __FILE__, __LINE__);
8286 return(stat);
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,
8294 &chain_temp);
8295 if(stat != TNG_SUCCESS)
8297 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
8298 __FILE__, __LINE__);
8299 return(stat);
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,
8306 &residue_temp);
8307 if(stat != TNG_SUCCESS)
8309 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
8310 __FILE__, __LINE__);
8311 return(stat);
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__);
8323 return(stat);
8328 molecule_temp->n_bonds = molecule->n_bonds;
8329 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
8330 molecule->n_bonds);
8331 if(!bond_temp)
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__);
8351 return(stat);
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,
8360 int64_t *n)
8362 (void) tng_data;
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,
8374 int64_t index,
8375 tng_chain_t *chain)
8377 (void) tng_data;
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)
8383 *chain = 0;
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,
8393 int64_t *n)
8395 (void) tng_data;
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)
8410 (void) tng_data;
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)
8416 *residue = 0;
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,
8426 int64_t *n)
8428 (void) tng_data;
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,
8441 tng_atom_t *atom)
8443 (void) tng_data;
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)
8449 *atom = 0;
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,
8459 const char *name,
8460 int64_t nr,
8461 tng_chain_t *chain)
8463 int64_t i, n_chains;
8464 (void)tng_data;
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);
8483 *chain = 0;
8485 return(TNG_FAILURE);
8488 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
8489 (tng_trajectory_t tng_data,
8490 tng_molecule_t molecule,
8491 const char *name,
8492 tng_chain_t *chain)
8494 int64_t id;
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;
8504 else
8506 id = 1;
8509 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
8510 id, chain));
8513 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
8514 (tng_trajectory_t tng_data,
8515 tng_molecule_t molecule,
8516 const char *name,
8517 const int64_t id,
8518 tng_chain_t *chain)
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));
8530 if(!new_chains)
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];
8543 (*chain)->name = 0;
8545 tng_chain_name_set(tng_data, *chain, name);
8547 (*chain)->molecule = molecule;
8548 (*chain)->n_residues = 0;
8550 molecule->n_chains++;
8552 (*chain)->id = id;
8554 return(stat);
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,
8562 tng_bond_t *bond)
8564 tng_bond_t new_bonds;
8565 (void)tng_data;
8567 new_bonds = realloc(molecule->bonds,
8568 sizeof(struct tng_bond) *
8569 (molecule->n_bonds + 1));
8571 if(!new_bonds)
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__);
8576 *bond = 0;
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,
8597 const char *name,
8598 int64_t id,
8599 tng_atom_t *atom)
8601 int64_t i, n_atoms;
8602 (void)tng_data;
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);
8620 *atom = 0;
8622 return(TNG_FAILURE);
8625 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
8626 const tng_chain_t chain,
8627 char *name,
8628 const int max_len)
8630 (void) tng_data;
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,
8646 tng_chain_t chain,
8647 const char *new_name)
8649 unsigned int len;
8650 (void)tng_data;
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)
8660 free(chain->name);
8661 chain->name = 0;
8663 if(!chain->name)
8665 chain->name = malloc(len);
8666 if(!chain->name)
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,
8682 int64_t *n)
8684 (void) tng_data;
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)
8699 (void) tng_data;
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)
8705 *residue = 0;
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,
8714 tng_chain_t chain,
8715 const char *name,
8716 int64_t id,
8717 tng_residue_t *residue)
8719 int64_t i, n_residues;
8720 (void)tng_data;
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);
8738 *residue = 0;
8740 return(TNG_FAILURE);
8743 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
8744 (tng_trajectory_t tng_data,
8745 tng_chain_t chain,
8746 const char *name,
8747 tng_residue_t *residue)
8749 int64_t id;
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;
8759 else
8761 id = 0;
8764 return(tng_chain_residue_w_id_add(tng_data, chain, name,
8765 id, residue));
8768 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
8769 (tng_trajectory_t tng_data,
8770 tng_chain_t chain,
8771 const char *name,
8772 const int64_t id,
8773 tng_residue_t *residue)
8775 int64_t curr_index;
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;
8787 else
8789 curr_index = -1;
8792 new_residues = realloc(molecule->residues,
8793 sizeof(struct tng_residue) *
8794 (molecule->n_residues + 1));
8796 if(!new_residues)
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)
8820 ++temp_residue;
8821 memmove(temp_residue + 1, temp_residue,
8822 last_residue - temp_residue);
8826 else
8828 curr_index = molecule->n_residues;
8831 *residue = &molecule->residues[curr_index + chain->n_residues];
8833 if(!chain->n_residues)
8835 chain->residues = *residue;
8837 else
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;
8854 return(stat);
8857 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
8858 const tng_residue_t residue,
8859 char *name,
8860 const int max_len)
8862 (void) tng_data;
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)
8880 unsigned int len;
8881 (void)tng_data;
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);
8893 residue->name = 0;
8895 if(!residue->name)
8897 residue->name = malloc(len);
8898 if(!residue->name)
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,
8914 int64_t *n)
8916 (void) tng_data;
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,
8929 tng_atom_t *atom)
8931 tng_chain_t chain;
8932 tng_molecule_t molecule;
8934 (void) tng_data;
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)
8940 *atom = 0;
8941 return(TNG_FAILURE);
8943 chain = residue->chain;
8944 molecule = chain->molecule;
8946 if(index + residue->atoms_offset >= molecule->n_atoms)
8948 *atom = 0;
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,
8961 tng_atom_t *atom)
8963 int64_t id;
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;
8974 else
8976 id = 0;
8979 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
8980 id, atom));
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,
8988 const int64_t id,
8989 tng_atom_t *atom)
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));
9008 if(!new_atoms)
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;
9028 residue->n_atoms++;
9029 molecule->n_atoms++;
9031 (*atom)->id = id;
9033 return(stat);
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));
9040 if(!*molecule_p)
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)
9055 if(!*molecule_p)
9057 return(TNG_SUCCESS);
9060 tng_molecule_destroy(tng_data, *molecule_p);
9062 free(*molecule_p);
9063 *molecule_p = 0;
9065 return(TNG_SUCCESS);
9068 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
9069 tng_molecule_t molecule)
9071 (void)tng_data;
9072 molecule->quaternary_str = 1;
9073 molecule->name = 0;
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)
9089 int64_t i;
9090 (void)tng_data;
9092 if(molecule->name)
9094 free(molecule->name);
9095 molecule->name = 0;
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;
9128 if(molecule->atoms)
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;
9139 if(molecule->bonds)
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,
9151 const int64_t nr,
9152 char *name,
9153 int max_len)
9155 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9156 tng_molecule_t mol;
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];
9175 continue;
9177 found = TNG_TRUE;
9178 break;
9180 if(!found)
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,
9197 const int64_t nr,
9198 int64_t *id)
9200 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9201 tng_molecule_t mol;
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];
9220 continue;
9222 found = TNG_TRUE;
9223 break;
9225 if(!found)
9227 return(TNG_FAILURE);
9230 *id = mol->id;
9232 return(TNG_SUCCESS);
9235 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
9236 (const tng_trajectory_t tng_data,
9237 int64_t *n_bonds,
9238 int64_t **from_atoms,
9239 int64_t **to_atoms)
9241 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
9242 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
9243 tng_molecule_t mol;
9244 tng_bond_t bond;
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);
9258 *n_bonds = 0;
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;
9266 if(*n_bonds == 0)
9268 return(TNG_SUCCESS);
9271 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
9272 if(!*from_atoms)
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));
9279 if(!*to_atoms)
9281 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
9282 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
9283 free(*from_atoms);
9284 *from_atoms = 0;
9285 return(TNG_CRITICAL);
9288 cnt = 0;
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,
9312 const int64_t nr,
9313 char *name,
9314 int max_len)
9316 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9317 tng_molecule_t mol;
9318 tng_atom_t atom;
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];
9337 continue;
9339 atom = &mol->atoms[nr % mol->n_atoms];
9340 found = TNG_TRUE;
9341 break;
9343 if(!found)
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,
9364 const int64_t nr,
9365 char *name,
9366 int max_len)
9368 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9369 tng_molecule_t mol;
9370 tng_atom_t atom;
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];
9389 continue;
9391 atom = &mol->atoms[nr % mol->n_atoms];
9392 found = TNG_TRUE;
9393 break;
9395 if(!found)
9397 return(TNG_FAILURE);
9399 if(!atom->residue)
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,
9416 const int64_t nr,
9417 int64_t *id)
9419 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9420 tng_molecule_t mol;
9421 tng_atom_t atom;
9422 tng_bool found = TNG_FALSE;
9424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9425 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
9427 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
9429 if(!molecule_cnt_list)
9431 return(TNG_FAILURE);
9434 for(i = 0; i < tng_data->n_molecules; i++)
9436 mol = &tng_data->molecules[i];
9437 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
9439 cnt += mol->n_atoms * molecule_cnt_list[i];
9440 continue;
9442 atom = &mol->atoms[nr % mol->n_atoms];
9443 found = TNG_TRUE;
9444 break;
9446 if(!found)
9448 return(TNG_FAILURE);
9450 if(!atom->residue)
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,
9462 const int64_t nr,
9463 int64_t *id)
9465 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
9466 tng_molecule_t mol;
9467 tng_atom_t atom;
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];
9487 continue;
9489 atom = &mol->atoms[nr % mol->n_atoms];
9490 found = TNG_TRUE;
9491 break;
9493 if(!found)
9495 return(TNG_FAILURE);
9497 if(!atom->residue)
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,
9511 const int64_t nr,
9512 char *name,
9513 int max_len)
9515 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9516 tng_molecule_t mol;
9517 tng_atom_t atom;
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];
9536 continue;
9538 atom = &mol->atoms[nr % mol->n_atoms];
9539 found = TNG_TRUE;
9540 break;
9542 if(!found)
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,
9559 const int64_t nr,
9560 char *type,
9561 int max_len)
9563 int64_t cnt = 0, i, *molecule_cnt_list = 0;
9564 tng_molecule_t mol;
9565 tng_atom_t atom;
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];
9584 continue;
9586 atom = &mol->atoms[nr % mol->n_atoms];
9587 found = TNG_TRUE;
9588 break;
9590 if(!found)
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)
9611 int64_t i;
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 +
9641 n_particles)
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);
9661 if(!mapping)
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;
9695 int64_t i;
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)
9722 time_t seconds;
9723 tng_trajectory_frame_set_t frame_set;
9724 tng_trajectory_t tng_data;
9726 *tng_data_p = malloc(sizeof(struct tng_trajectory));
9727 if(!*tng_data_p)
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;
9754 seconds = time(0);
9755 if ( seconds == -1)
9757 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
9759 else
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;
9820 /* 0x01234567 */
9821 if ( *(const unsigned char*)&endianness_32 == 0x01 )
9823 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
9826 /* 0x67452301 */
9827 else if( *(const unsigned char*)&endianness_32 == 0x67 )
9829 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
9833 /* 0x45670123 */
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
9875 * written. */
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)
9890 int64_t i, j, k, l;
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;
9895 if(!*tng_data_p)
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;
9999 else
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].
10027 strings[0][j][k])
10029 free(tng_data->non_tr_particle_data[i].
10030 strings[0][j][k]);
10031 tng_data->non_tr_particle_data[i].
10032 strings[0][j][k] = 0;
10035 free(tng_data->non_tr_particle_data[i].
10036 strings[0][j]);
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].
10133 strings[j][k])
10135 for(l = 0; l < n_values_per_frame; l++)
10137 if(frame_set->tr_particle_data[i].
10138 strings[j][k][l])
10140 free(frame_set->tr_particle_data[i].
10141 strings[j][k][l]);
10142 frame_set->tr_particle_data[i].
10143 strings[j][k][l] = 0;
10146 free(frame_set->tr_particle_data[i].
10147 strings[j][k]);
10148 frame_set->tr_particle_data[i].
10149 strings[j][k] = 0;
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;
10233 free(*tng_data_p);
10234 *tng_data_p = 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));
10248 if(!*dest_p)
10250 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
10251 sizeof(struct tng_trajectory), __FILE__, __LINE__);
10252 return(TNG_CRITICAL);
10255 dest = *dest_p;
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)
10377 unsigned int len;
10378 char *temp;
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,
10385 file_name) == 0)
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);
10397 if(!temp)
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)
10431 int len;
10432 char *temp;
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);
10450 if(!temp)
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)
10469 int len;
10470 char *temp;
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);
10488 if(!temp)
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;
10534 else
10536 return(TNG_FAILURE);
10539 else
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;
10557 else
10559 return(TNG_FAILURE);
10562 else
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;
10581 else
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;
10608 else
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;
10617 else
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;
10630 else
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;
10639 else
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
10648 * failure. */
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)
10672 unsigned int len;
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)
10721 unsigned int len;
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)
10770 unsigned int len;
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)
10821 unsigned int len;
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)
10872 unsigned int len;
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)
10923 unsigned int len;
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) <
10933 len)
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)
10975 unsigned int len;
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) <
10985 len)
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)
11027 unsigned int len;
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) <
11037 len)
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)
11079 unsigned int len;
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,
11111 int64_t *len)
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,
11123 const int64_t len)
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,
11138 int64_t *len)
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,
11150 const int64_t len)
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,
11165 double *time)
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,
11177 const double time)
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,
11205 int64_t *len)
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,
11217 int64_t *n)
11219 tng_gen_block_t block;
11220 tng_function_status stat;
11221 long file_pos;
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,
11239 SEEK_SET);
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,
11272 double *precision)
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,
11294 const int64_t n)
11296 tng_molecule_t mol;
11297 tng_chain_t chain;
11298 tng_residue_t res;
11299 tng_atom_t atom;
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;
11319 if(diff == 0)
11321 if(stat == TNG_SUCCESS)
11323 stat = tng_molecule_cnt_set(tng_data, mol, 0);
11324 return(stat);
11326 return(TNG_SUCCESS);
11328 else if(diff < 0)
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",
11342 &mol);
11343 if(stat != TNG_SUCCESS)
11345 return(stat);
11347 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
11348 if(stat != TNG_SUCCESS)
11350 return(stat);
11352 stat = tng_chain_residue_add(tng_data, chain, "", &res);
11353 if(stat != TNG_SUCCESS)
11355 return(stat);
11357 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
11358 if(stat != TNG_SUCCESS)
11360 return(stat);
11363 else
11365 if(mol->n_atoms > 1)
11367 n_mod = diff % mol->n_atoms;
11368 if(n_mod != 0)
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);
11381 return(stat);
11384 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
11385 (const tng_trajectory_t tng_data,
11386 int64_t *n)
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;
11395 else
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,
11405 char *variable)
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,
11417 int64_t *n)
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,
11429 int64_t *n)
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);
11438 if(!cnt_list)
11440 return(TNG_FAILURE);
11443 for(i = 0; i < tng_data->n_molecules; i++)
11445 cnt += cnt_list[i];
11448 *n = cnt;
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.
11462 molecule_cnt_list;
11464 else
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,
11477 int64_t *exp)
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,
11489 const int64_t exp)
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,
11500 int64_t *n)
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,
11512 const int64_t n)
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,
11523 int64_t *n)
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;
11531 int64_t cnt = 0;
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;
11543 if(file_pos < 0)
11545 *n = tng_data->n_trajectory_frame_sets = cnt;
11546 return(TNG_SUCCESS);
11549 tng_block_init(&block);
11550 fseek(tng_data->input_file,
11551 file_pos,
11552 SEEK_SET);
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);
11571 ++cnt;
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)
11581 if(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)
11610 if(file_pos > 0)
11612 cnt += medium_stride_length;
11613 fseek(tng_data->input_file,
11614 file_pos,
11615 SEEK_SET);
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)
11640 if(file_pos > 0)
11642 ++cnt;
11643 fseek(tng_data->input_file,
11644 file_pos,
11645 SEEK_SET);
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,
11674 SEEK_SET);
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,
11694 const int64_t nr)
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)
11711 return(stat);
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;
11729 else
11731 /* Start from the end */
11732 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11733 curr_nr = n_frame_sets - 1;
11735 if(file_pos <= 0)
11737 return(TNG_FAILURE);
11740 tng_block_init(&block);
11741 fseek(tng_data->input_file,
11742 (long)file_pos,
11743 SEEK_SET);
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);
11762 if(curr_nr == nr)
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;
11775 if(file_pos > 0)
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);
11795 if(curr_nr == nr)
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;
11808 if(file_pos > 0)
11810 curr_nr += medium_stride_length;
11811 fseek(tng_data->input_file,
11812 (long)file_pos,
11813 SEEK_SET);
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);
11830 if(curr_nr == nr)
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;
11843 if(file_pos > 0)
11845 ++curr_nr;
11846 fseek(tng_data->input_file,
11847 (long)file_pos,
11848 SEEK_SET);
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);
11865 if(curr_nr == nr)
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;
11878 if(file_pos > 0)
11880 curr_nr -= long_stride_length;
11881 fseek(tng_data->input_file,
11882 (long)file_pos,
11883 SEEK_SET);
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);
11900 if(curr_nr == nr)
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;
11913 if(file_pos > 0)
11915 curr_nr -= medium_stride_length;
11916 fseek(tng_data->input_file,
11917 (long)file_pos,
11918 SEEK_SET);
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);
11935 if(curr_nr == nr)
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;
11947 if(file_pos > 0)
11949 --curr_nr;
11950 fseek(tng_data->input_file,
11951 (long)file_pos,
11952 SEEK_SET);
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);
11969 if(curr_nr == nr)
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;
11982 if(file_pos > 0)
11984 ++curr_nr;
11985 fseek(tng_data->input_file,
11986 (long)file_pos,
11987 SEEK_SET);
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);
12004 if(curr_nr == nr)
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,
12038 (long)file_pos,
12039 SEEK_SET);
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) ==
12073 TNG_SUCCESS)
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;
12098 if(file_pos <= 0)
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 */
12113 else
12115 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
12118 if(file_pos > 0)
12120 fseek(tng_data->input_file,
12121 (long)file_pos,
12122 SEEK_SET);
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;
12160 if(file_pos > 0)
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;
12195 if(file_pos > 0)
12197 fseek(tng_data->input_file,
12198 (long)file_pos,
12199 SEEK_SET);
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;
12230 if(file_pos > 0)
12232 fseek(tng_data->input_file,
12233 (long)file_pos,
12234 SEEK_SET);
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;
12267 if(file_pos > 0)
12269 fseek(tng_data->input_file,
12270 (long)file_pos,
12271 SEEK_SET);
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;
12304 if(file_pos > 0)
12306 fseek(tng_data->input_file,
12307 (long)file_pos,
12308 SEEK_SET);
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;
12339 if(file_pos > 0)
12341 fseek(tng_data->input_file,
12342 (long)file_pos,
12343 SEEK_SET);
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;
12375 if(file_pos > 0)
12377 fseek(tng_data->input_file,
12378 (long)file_pos,
12379 SEEK_SET);
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,
12413 int64_t *pos)
12415 (void)tng_data;
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,
12428 int64_t *pos)
12430 (void)tng_data;
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)
12446 (void)tng_data;
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
12464 * cannot be found.
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,
12469 int64_t *real)
12471 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
12472 tng_particle_mapping_t mapping;
12473 if(n_blocks <= 0)
12475 *real = local;
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)
12485 continue;
12487 *real = mapping->real_particle_numbers[local-first];
12488 return(TNG_SUCCESS);
12490 *real = local;
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
12500 * cannot be found.
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,
12505 int64_t *local)
12507 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
12508 tng_particle_mapping_t mapping;
12509 if(n_blocks <= 0)
12511 *local = real;
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)
12521 *local = j;
12522 return(TNG_SUCCESS);
12526 return(TNG_FAILURE);
12530 static tng_function_status tng_file_headers_len_get
12531 (tng_trajectory_t tng_data,
12532 int64_t *len)
12534 int64_t orig_pos;
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);
12544 *len = 0;
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 &&
12560 block->id != -1 &&
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 &&
12602 block->id != -1 &&
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)
12624 int i;
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)
12641 return(stat);
12644 tng_block_init(&block);
12645 block->name = malloc(TNG_MAX_STR_LEN);
12646 if(!block->name)
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);
12655 tot_len += len;
12656 tng_general_info_block_len_calculate(tng_data, &len);
12657 tot_len += len;
12658 strcpy(block->name, "MOLECULES");
12659 tng_block_header_len_calculate(tng_data, block, &len);
12660 tot_len += len;
12661 tng_molecules_block_len_calculate(tng_data, &len);
12662 tot_len += 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);
12668 tot_len += 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,
12673 &len);
12674 tot_len += len;
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);
12680 tot_len += 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,
12685 &data_start_pos,
12686 &len);
12687 tot_len += len;
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)
12704 != TNG_SUCCESS)
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)
12712 != TNG_SUCCESS)
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,
12726 i, hash_mode);
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,
12733 i, 0, hash_mode);
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.");
12748 switch(block->id)
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));
12758 default:
12759 if(block->id >= TNG_TRAJ_BOX_SHAPE)
12761 return(tng_data_block_contents_read(tng_data, block, hash_mode));
12763 else
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)
12776 long file_pos;
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 ||
12801 block->id == -1)
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 &&
12821 block->id != -1)
12823 stat = tng_block_read_next(tng_data, block,
12824 hash_mode);
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);
12839 return(stat);
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)
12859 long file_pos;
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;
12873 if(file_pos < 0)
12875 /* No current frame set. This means that the first frame set must be
12876 * read */
12877 found_flag = 0;
12878 file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
12881 if(file_pos > 0)
12883 fseek(tng_data->input_file,
12884 file_pos,
12885 SEEK_SET);
12887 else
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 */
12911 if(found_flag)
12913 fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
12915 /* Otherwiese read the frame set block */
12916 else
12918 stat = tng_block_read_next(tng_data, block,
12919 hash_mode);
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);
12924 return(stat);
12927 file_pos = ftell(tng_data->input_file);
12929 found_flag = 0;
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 &&
12937 block->id != -1)
12939 if(block->id == block_id)
12941 stat = tng_block_read_next(tng_data, block,
12942 hash_mode);
12943 if(stat != TNG_CRITICAL)
12945 file_pos = ftell(tng_data->input_file);
12946 found_flag = 1;
12947 if(file_pos < tng_data->input_file_len)
12949 stat = tng_block_header_read(tng_data, block);
12953 else
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);
12968 return(stat);
12971 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12973 fseek(tng_data->input_file, file_pos, SEEK_SET);
12976 tng_block_destroy(&block);
12978 if(found_flag)
12980 return(TNG_SUCCESS);
12982 else
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)
12992 long file_pos;
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;
13008 if(file_pos > 0)
13010 fseek(tng_data->input_file,
13011 file_pos,
13012 SEEK_SET);
13014 else
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)
13027 long file_pos;
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;
13045 if(file_pos > 0)
13047 fseek(tng_data->input_file,
13048 file_pos,
13049 SEEK_SET);
13051 else
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);
13085 return(stat);
13088 tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
13089 const char hash_mode)
13091 int i, j;
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],
13149 hash_mode);
13154 else
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,
13160 i, 0, hash_mode);
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);
13179 return(stat);
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;
13209 int64_t curr_pos;
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);
13219 if(curr_pos <= 10)
13221 tng_file_headers_write(tng_data, TNG_USE_HASH);
13224 /* Set pointer to previous frame set to the one that was loaded
13225 * before.
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,
13258 SEEK_SET);
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)
13287 != TNG_SUCCESS)
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,
13314 SEEK_SET);
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)
13345 != TNG_SUCCESS)
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)
13403 return(stat);
13405 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
13407 return(stat);
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,
13424 int64_t *frame)
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;
13442 else
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,
13482 const int64_t id,
13483 const char *block_name,
13484 const char datatype,
13485 const char block_type_flag,
13486 int64_t n_frames,
13487 const int64_t n_values_per_frame,
13488 int64_t stride_length,
13489 const int64_t codec_id,
13490 void *new_data)
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)
13507 stride_length = 1;
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) !=
13514 TNG_SUCCESS)
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];
13524 else
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);
13539 data->values = 0;
13540 /* FIXME: Memory leak from strings. */
13541 data->strings = 0;
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;
13554 switch(datatype)
13556 case TNG_FLOAT_DATA:
13557 size = sizeof(float);
13558 break;
13559 case TNG_INT_DATA:
13560 size = sizeof(int64_t);
13561 break;
13562 case TNG_DOUBLE_DATA:
13563 default:
13564 size = sizeof(double);
13565 break;
13568 if(new_data_c)
13570 /* Allocate memory */
13571 if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
13572 n_values_per_frame) !=
13573 TNG_SUCCESS)
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,
13597 TNG_MAX_STR_LEN);
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],
13610 new_data_c, len);
13611 new_data_c += len;
13615 else
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,
13627 const int64_t id,
13628 const char *block_name,
13629 const char datatype,
13630 const char block_type_flag,
13631 int64_t n_frames,
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,
13637 void *new_data)
13639 int i, size, len;
13640 int64_t j, k;
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)
13658 stride_length = 1;
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) !=
13665 TNG_SUCCESS)
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];
13676 else
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;
13694 data->values = 0;
13695 /* FIXME: Memory leak from strings. */
13696 data->strings = 0;
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;
13712 else
13714 tot_n_particles = tng_data->n_particles;
13717 /* If data values are supplied add that data to the data block. */
13718 if(new_data_c)
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) !=
13724 TNG_SUCCESS)
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;
13746 j++)
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,
13752 TNG_MAX_STR_LEN);
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],
13765 new_data_c, len);
13766 new_data_c += len;
13771 else
13773 switch(datatype)
13775 case TNG_INT_DATA:
13776 size = sizeof(int64_t);
13777 break;
13778 case TNG_FLOAT_DATA:
13779 size = sizeof(float);
13780 break;
13781 case TNG_DOUBLE_DATA:
13782 default:
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,
13796 int64_t block_id,
13797 char *name,
13798 int max_len)
13800 int64_t i;
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;
13838 else
13840 stat = tng_data_find(tng_data, block_id, &np_data);
13841 if(stat == TNG_SUCCESS)
13843 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
13845 else
13847 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13848 if(stat != TNG_SUCCESS)
13850 return(stat);
13852 stat = tng_particle_data_find(tng_data, block_id, &p_data);
13853 if(stat == TNG_SUCCESS)
13855 block_type = TNG_PARTICLE_BLOCK_DATA;
13857 else
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,
13899 int64_t block_id,
13900 int *block_dependency)
13902 int64_t i;
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);
13935 else
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);
13943 else
13945 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13946 if(stat != TNG_SUCCESS)
13948 return(stat);
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);
13956 else
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,
13973 int64_t block_id,
13974 int64_t *n_values_per_frame)
13976 int64_t i;
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);
14009 else
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);
14017 else
14019 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
14020 if(stat != TNG_SUCCESS)
14022 return(stat);
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);
14030 else
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;
14056 long temp_current;
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;
14063 void *copy;
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,
14109 last_frame+1,
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 &&
14123 block->id != -1)
14125 if(block->id == TNG_PARTICLE_MAPPING)
14127 tng_trajectory_mapping_block_read(tng_data, block,
14128 hash_mode);
14130 else
14132 fseek(tng_data->output_file, (long)block->block_contents_size,
14133 SEEK_CUR);
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);
14150 else
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;
14156 return(stat);
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;
14180 return(stat);
14182 fseek(tng_data->output_file, (long)block->block_contents_size,
14183 SEEK_CUR);
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 &&
14192 block->id != -1)
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;
14210 return(stat);
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)
14263 != TNG_SUCCESS)
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,
14280 &data.codec_id)
14281 != TNG_SUCCESS)
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)
14292 == 0)
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)
14302 != TNG_SUCCESS)
14304 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14305 __FILE__, __LINE__);
14309 else
14311 data.compression_multiplier = 1;
14314 if(sparse_data)
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)
14327 != TNG_SUCCESS)
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)
14345 != TNG_SUCCESS)
14347 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14348 __FILE__, __LINE__);
14352 else
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);
14369 break;
14370 case(TNG_FLOAT_DATA):
14371 size = sizeof(float);
14372 break;
14373 case(TNG_DOUBLE_DATA):
14374 size = sizeof(double);
14375 break;
14376 default:
14377 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14378 __LINE__);
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__,
14393 __LINE__);
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,
14410 (int64_t *)copy+i)
14411 != TNG_SUCCESS)
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);
14419 free(copy);
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,
14429 (int32_t *)copy+i)
14430 != TNG_SUCCESS)
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);
14438 free(copy);
14441 else
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 +
14460 header_size);
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;
14482 long temp_current;
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;
14490 void *copy;
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,
14526 last_frame); */
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,
14538 last_frame+1,
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 &&
14553 block->id != -1)
14555 if(block->id == TNG_PARTICLE_MAPPING)
14557 tng_trajectory_mapping_block_read(tng_data, block,
14558 hash_mode);
14560 else
14562 fseek(tng_data->output_file, (long)block->block_contents_size,
14563 SEEK_CUR);
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__);
14577 exit(1);
14580 else
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;
14586 return(stat);
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;
14611 return(stat);
14613 fseek(tng_data->output_file, (long)block->block_contents_size,
14614 SEEK_CUR);
14616 if(tng_data->var_num_atoms_flag)
14618 tot_n_particles = frame_set->n_particles;
14620 else
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 &&
14633 block->id != -1)
14635 if(block->id == TNG_PARTICLE_MAPPING)
14637 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
14639 else
14641 fseek(tng_data->output_file, (long)block->block_contents_size,
14642 SEEK_CUR);
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;
14672 return(stat);
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 &&
14695 block->id != -1)
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;
14714 return(stat);
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)
14769 != TNG_SUCCESS)
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,
14786 &data.codec_id)
14787 != TNG_SUCCESS)
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)
14798 == 0)
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)
14809 != TNG_SUCCESS)
14811 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14812 __FILE__, __LINE__);
14816 else
14818 data.compression_multiplier = 1;
14821 if(sparse_data)
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)
14835 != TNG_SUCCESS)
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)
14853 != TNG_SUCCESS)
14855 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
14856 __FILE__, __LINE__);
14860 else
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)
14878 != TNG_SUCCESS)
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)
14896 != TNG_SUCCESS)
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);
14915 break;
14916 case(TNG_FLOAT_DATA):
14917 size = sizeof(float);
14918 break;
14919 case(TNG_DOUBLE_DATA):
14920 size = sizeof(double);
14921 break;
14922 default:
14923 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
14924 __LINE__);
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__,
14939 __LINE__);
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)
14957 != TNG_SUCCESS)
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);
14965 free(copy);
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)
14976 != TNG_SUCCESS)
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);
14984 free(copy);
14987 else
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 +
15006 header_size);
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,
15018 const char type)
15020 int64_t i;
15021 tng_function_status stat;
15023 if(n_frames <= 0 || n_values_per_frame <= 0)
15025 return(TNG_FAILURE);
15028 if(*values)
15030 stat = tng_data_values_free(tng_data, *values, n_frames,
15031 n_values_per_frame,
15032 type);
15033 if(stat != TNG_SUCCESS)
15035 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15036 __FILE__, __LINE__);
15037 return(stat);
15040 *values = malloc(sizeof(union data_values *) * n_frames);
15041 if(!*values)
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);
15054 if(!(*values)[i])
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__);
15059 free(values);
15060 values = 0;
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,
15073 const char type)
15075 int64_t i, j;
15076 (void)tng_data;
15078 if(values)
15080 for(i = 0; i < n_frames; i++)
15082 if(values[i])
15084 if(type == TNG_CHAR_DATA)
15086 for(j = 0; j < n_values_per_frame; j++)
15088 if(values[i][j].c)
15090 free(values[i][j].c);
15091 values[i][j].c = 0;
15095 free(values[i]);
15096 values[i] = 0;
15099 free(values);
15100 values = 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,
15112 const char type)
15114 int64_t i, j;
15115 tng_function_status stat;
15117 if(n_particles == 0 || n_values_per_frame == 0)
15119 return(TNG_FAILURE);
15122 if(*values)
15124 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
15125 n_particles, n_values_per_frame,
15126 type);
15127 if(stat != TNG_SUCCESS)
15129 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
15130 __FILE__, __LINE__);
15131 return(stat);
15134 *values = malloc(sizeof(union data_values **) * n_frames);
15135 if(!*values)
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 *) *
15147 n_particles);
15148 if(!(*values)[i])
15150 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15151 sizeof(union data_values *) * n_particles,
15152 __FILE__, __LINE__);
15153 free(*values);
15154 *values = 0;
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,
15168 type);
15169 *values = 0;
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,
15184 const char type)
15186 int64_t i, j, k;
15187 (void)tng_data;
15189 if(values)
15191 for(i = 0; i < n_frames; i++)
15193 if(values[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]);
15209 values[i][j] = 0;
15211 free(values[i]);
15212 values[i] = 0;
15215 free(values);
15216 values = 0;
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,
15227 int64_t *n_frames,
15228 int64_t *n_values_per_frame,
15229 char *type)
15231 int64_t i, j, file_pos, block_index;
15232 int size;
15233 size_t len;
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;
15246 block_index = -1;
15247 data = 0;
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 &&
15258 block->id != -1)
15260 /* Use hash by default */
15261 stat = tng_block_read_next(tng_data, block,
15262 TNG_USE_HASH);
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__);
15277 return(stat);
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)
15285 block_index = i;
15286 break;
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;
15299 if(*values == 0)
15301 if(tng_data_values_alloc(tng_data, values, *n_frames,
15302 *n_values_per_frame,
15303 *type)
15304 != TNG_SUCCESS)
15306 return(TNG_CRITICAL);
15310 switch(*type)
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);
15322 break;
15323 case TNG_INT_DATA:
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));
15333 break;
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));
15344 break;
15345 case TNG_DOUBLE_DATA:
15346 default:
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,
15365 void **values,
15366 int64_t *n_frames,
15367 int64_t *stride_length,
15368 int64_t *n_values_per_frame,
15369 char *type)
15371 int64_t file_pos, data_size, n_frames_div, block_index;
15372 int i, size;
15373 tng_non_particle_data_t data;
15374 tng_trajectory_frame_set_t frame_set;
15375 tng_gen_block_t block;
15376 void *temp;
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;
15387 block_index = -1;
15388 data = 0;
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 &&
15399 block->id != -1)
15401 /* Use hash by default */
15402 stat = tng_block_read_next(tng_data, block,
15403 TNG_USE_HASH);
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__);
15418 return(stat);
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)
15426 block_index = i;
15427 break;
15430 if(block_index < 0)
15432 return(TNG_FAILURE);
15436 *type = data->datatype;
15438 switch(*type)
15440 case TNG_CHAR_DATA:
15441 return(TNG_FAILURE);
15442 case TNG_INT_DATA:
15443 size = sizeof(int64_t);
15444 break;
15445 case TNG_FLOAT_DATA:
15446 size = sizeof(float);
15447 break;
15448 case TNG_DOUBLE_DATA:
15449 default:
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);
15463 if(!temp)
15465 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15466 data_size, __FILE__, __LINE__);
15467 free(*values);
15468 *values = 0;
15469 return(TNG_CRITICAL);
15472 *values = temp;
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,
15489 char *type)
15491 int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
15492 int64_t block_index;
15493 int size;
15494 size_t len;
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.");
15505 block_index = -1;
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)
15513 return(stat);
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 &&
15528 block->id != -1)
15530 stat = tng_block_read_next(tng_data, block,
15531 hash_mode);
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__);
15546 return(stat);
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)
15558 block_index = i;
15559 break;
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;
15574 if(*values == 0)
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. */
15588 switch(*type)
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)
15598 return(stat);
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++;
15610 break;
15611 case TNG_INT_DATA:
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)
15620 return(stat);
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++;
15632 break;
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)
15642 return(stat);
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++;
15654 break;
15655 case TNG_DOUBLE_DATA:
15656 default:
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)
15665 return(stat);
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,
15690 void **values,
15691 int64_t *stride_length,
15692 int64_t *n_values_per_frame,
15693 char *type)
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;
15698 int size;
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)
15717 return(stat);
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,
15731 SEEK_SET);
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__);
15737 return(stat);
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 &&
15748 block->id != -1)
15750 if(block->id == block_id)
15752 stat = tng_block_read_next(tng_data, block,
15753 hash_mode);
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);
15763 else
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__);
15778 return(stat);
15782 stat = tng_data_find(tng_data, block_id, &np_data);
15783 if(stat != TNG_SUCCESS)
15785 return(stat);
15788 stat = tng_data_vector_get(tng_data, block_id, &current_values,
15789 &n_frames, stride_length,
15790 n_values_per_frame, type);
15792 if(stat != TNG_SUCCESS)
15794 if(current_values)
15796 free(current_values);
15798 return(stat);
15801 if(n_frames == 1 && n_frames < frame_set->n_frames)
15803 tot_n_frames = 1;
15805 else
15807 tot_n_frames = end_frame_nr - start_frame_nr + 1;
15810 switch(*type)
15812 case TNG_CHAR_DATA:
15813 return(TNG_FAILURE);
15814 case TNG_INT_DATA:
15815 size = sizeof(int64_t);
15816 break;
15817 case TNG_FLOAT_DATA:
15818 size = sizeof(float);
15819 break;
15820 case TNG_DOUBLE_DATA:
15821 default:
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);
15834 if(!temp)
15836 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15837 data_size, __FILE__, __LINE__);
15838 free(*values);
15839 *values = 0;
15840 return(TNG_CRITICAL);
15843 *values = temp;
15845 if( n_frames == 1 && n_frames < frame_set->n_frames)
15847 memcpy(*values, current_values, size * (*n_values_per_frame));
15849 else
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)
15874 if(current_values)
15876 free(current_values);
15878 free(*values);
15879 *values = 0;
15880 return(stat);
15883 stat = tng_data_vector_get(tng_data, block_id, &current_values,
15884 &n_frames, stride_length,
15885 n_values_per_frame, type);
15887 if(stat != TNG_SUCCESS)
15889 if(current_values)
15891 free(current_values);
15893 free(*values);
15894 *values = 0;
15895 return(stat);
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,
15908 current_values,
15909 n_frames_div_2 * frame_size);
15911 current_frame_pos += n_frames;
15915 if(current_values)
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,
15929 int64_t *n_frames,
15930 int64_t *n_particles,
15931 int64_t *n_values_per_frame,
15932 char *type)
15934 int64_t i, j, k, mapping, file_pos, i_step, block_index;
15935 int size;
15936 size_t len;
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;
15951 block_index = -1;
15952 data = 0;
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;
15960 else
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 &&
15972 block->id != -1)
15974 /* Use hash by default */
15975 stat = tng_block_read_next(tng_data, block,
15976 TNG_USE_HASH);
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__);
15991 return(stat);
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)
15999 block_index = i;
16000 block_type_flag = TNG_TRAJECTORY_BLOCK;
16001 break;
16004 if(block_index < 0)
16006 return(TNG_FAILURE);
16009 else
16011 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
16013 block_type_flag = TNG_TRAJECTORY_BLOCK;
16015 else
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;
16026 else
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;
16035 if(*values == 0)
16037 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
16038 *n_particles, *n_values_per_frame,
16039 *type)
16040 != TNG_SUCCESS)
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. */
16049 switch(*type)
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);
16066 break;
16067 case TNG_INT_DATA:
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 *
16079 (i * i_step + j *
16080 (*n_values_per_frame) + k));
16084 break;
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 *
16097 (i * i_step + j *
16098 (*n_values_per_frame) + k));
16102 break;
16103 case TNG_DOUBLE_DATA:
16104 default:
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 *
16116 (i * i_step + j *
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,
16131 void **values,
16132 int64_t *n_frames,
16133 int64_t *stride_length,
16134 int64_t *n_particles,
16135 int64_t *n_values_per_frame,
16136 char *type)
16138 int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
16139 int64_t block_index;
16140 int size;
16141 tng_particle_data_t data;
16142 tng_trajectory_frame_set_t frame_set;
16143 tng_gen_block_t block;
16144 void *temp;
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;
16156 block_index = -1;
16157 data = 0;
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 &&
16168 block->id != -1)
16170 /* Use hash by default */
16171 stat = tng_block_read_next(tng_data, block,
16172 TNG_USE_HASH);
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__);
16187 return(stat);
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)
16195 block_index = i;
16196 break;
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;
16209 else
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;
16219 else
16221 *n_particles = tng_data->n_particles;
16224 *type = data->datatype;
16226 switch(*type)
16228 case TNG_CHAR_DATA:
16229 return(TNG_FAILURE);
16230 case TNG_INT_DATA:
16231 size = sizeof(int64_t);
16232 break;
16233 case TNG_FLOAT_DATA:
16234 size = sizeof(float);
16235 break;
16236 case TNG_DOUBLE_DATA:
16237 default:
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);
16253 if(!temp)
16255 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16256 data_size, __FILE__, __LINE__);
16257 free(*values);
16258 *values = 0;
16259 return(TNG_CRITICAL);
16262 *values = temp;
16264 if(frame_set->n_mapping_blocks <= 0)
16266 memcpy(*values, data->values, data_size);
16268 else
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,
16299 char *type)
16301 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
16302 int64_t first_frame, block_index;
16303 int size;
16304 size_t len;
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.");
16317 block_index = -1;
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)
16325 return(stat);
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 &&
16339 block->id != -1)
16341 stat = tng_block_read_next(tng_data, block,
16342 hash_mode);
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__);
16357 return(stat);
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)
16368 block_index = i;
16369 block_type_flag = TNG_TRAJECTORY_BLOCK;
16370 break;
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;
16386 else
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;
16395 if(*values == 0)
16397 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
16398 *n_particles, *n_values_per_frame,
16399 *type)
16400 != TNG_SUCCESS)
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. */
16410 switch(*type)
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)
16420 return(stat);
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++;
16436 break;
16437 case TNG_INT_DATA:
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)
16447 return(stat);
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 *
16459 i_step + j *
16460 (*n_values_per_frame) + k));
16463 current_frame_pos++;
16465 break;
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)
16476 return(stat);
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 *
16488 i_step + j *
16489 (*n_values_per_frame) + k));
16492 current_frame_pos++;
16494 break;
16495 case TNG_DOUBLE_DATA:
16496 default:
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)
16506 return(stat);
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 *
16518 i_step + j *
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,
16537 void **values,
16538 int64_t *n_particles,
16539 int64_t *stride_length,
16540 int64_t *n_values_per_frame,
16541 char *type)
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;
16545 int 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)
16565 return(stat);
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,
16579 SEEK_SET);
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__);
16585 return(stat);
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 &&
16596 block->id != -1)
16598 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
16600 stat = tng_block_read_next(tng_data, block,
16601 hash_mode);
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);
16611 else
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__);
16626 return(stat);
16629 stat = tng_particle_data_find(tng_data, block_id, &p_data);
16630 if(stat != TNG_SUCCESS)
16632 return(stat);
16635 stat = tng_particle_data_vector_get(tng_data, block_id, &current_values,
16636 &n_frames, stride_length, n_particles,
16637 n_values_per_frame, type);
16639 if(stat != TNG_SUCCESS || *n_particles == 0)
16641 if(current_values)
16643 free(current_values);
16645 return(stat);
16648 if(n_frames == 1 && n_frames < frame_set->n_frames)
16650 tot_n_frames = 1;
16652 else
16654 tot_n_frames = end_frame_nr - start_frame_nr + 1;
16657 switch(*type)
16659 case TNG_CHAR_DATA:
16660 return(TNG_FAILURE);
16661 case TNG_INT_DATA:
16662 size = sizeof(int64_t);
16663 break;
16664 case TNG_FLOAT_DATA:
16665 size = sizeof(float);
16666 break;
16667 case TNG_DOUBLE_DATA:
16668 default:
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);
16680 if(!temp)
16682 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
16683 data_size, __FILE__, __LINE__);
16684 free(*values);
16685 *values = 0;
16686 return(TNG_CRITICAL);
16689 *values = temp;
16691 if( n_frames == 1 && n_frames < frame_set->n_frames)
16693 memcpy(*values, current_values, size * (*n_particles) *
16694 (*n_values_per_frame));
16696 else
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)
16721 if(current_values)
16723 free(current_values);
16725 free(*values);
16726 *values = 0;
16727 return(stat);
16730 stat = tng_particle_data_vector_get(tng_data, block_id, &current_values,
16731 &n_frames, stride_length, n_particles,
16732 n_values_per_frame, type);
16734 if(stat != TNG_SUCCESS)
16736 if(current_values)
16738 free(current_values);
16740 free(*values);
16741 *values = 0;
16742 return(stat);
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,
16755 current_values,
16756 n_frames_div_2 * frame_size);
16758 current_frame_pos += n_frames;
16762 if(current_values)
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,
16775 int64_t frame,
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)
16786 frame = 0;
16789 if(frame >= 0)
16791 stat = tng_frame_set_of_frame_find(tng_data, frame);
16792 if(stat != TNG_SUCCESS)
16794 return(stat);
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 */
16806 if(frame < 0)
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);
16819 return(stat);
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);
16829 return(stat);
16831 else
16833 is_particle_data = 1;
16836 else
16838 is_particle_data = 0;
16841 else
16843 is_particle_data = 1;
16846 else
16848 is_particle_data = 0;
16850 if(is_particle_data)
16852 *stride_length = p_data->stride_length;
16854 else
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,
16865 char *time)
16867 struct tm *time_data;
16868 time_t secs;
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,
16887 const char mode,
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)
16916 return(stat);
16920 if(mode == 'w')
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,
16933 SEEK_SET);
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,
16998 double *time)
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__);
17012 return(stat);
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,
17031 int64_t *n_mols,
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;
17047 else
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,
17060 const char *name,
17061 const int64_t cnt,
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)
17072 return(stat);
17074 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
17076 return(stat);
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,
17083 char ***names,
17084 char ***types,
17085 char ***res_names,
17086 int64_t **res_ids,
17087 char ***chain_names,
17088 int64_t **chain_ids)
17090 tng_atom_t atom;
17091 tng_residue_t res;
17092 tng_chain_t chain;
17093 int64_t i;
17094 (void)tng_data;
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)
17136 int64_t i;
17137 tng_chain_t chain;
17138 tng_residue_t residue;
17139 tng_atom_t atom;
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],
17156 &chain);
17157 if(stat != TNG_SUCCESS)
17159 return(stat);
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],
17166 &residue);
17167 if(stat != TNG_SUCCESS)
17169 return(stat);
17172 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
17173 if(stat != TNG_SUCCESS)
17175 return(stat);
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;
17186 char type;
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)
17196 return(stat);
17199 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
17200 0, n_frames - 1, TNG_USE_HASH,
17201 (void **)positions,
17202 &n_particles,
17203 stride_length,
17204 &n_values_per_frame,
17205 &type);
17207 return(stat);
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;
17215 char type;
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)
17225 return(stat);
17228 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
17229 0, n_frames - 1, TNG_USE_HASH,
17230 (void **)velocities,
17231 &n_particles,
17232 stride_length,
17233 &n_values_per_frame,
17234 &type);
17236 return(stat);
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;
17244 char type;
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)
17254 return(stat);
17257 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
17258 0, n_frames - 1, TNG_USE_HASH,
17259 (void **)forces,
17260 &n_particles,
17261 stride_length,
17262 &n_values_per_frame,
17263 &type);
17265 return(stat);
17268 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
17269 (tng_trajectory_t tng_data,
17270 float **box_shape,
17271 int64_t *stride_length)
17273 int64_t n_frames, n_values_per_frame;
17274 char type;
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)
17284 return(stat);
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,
17290 stride_length,
17291 &n_values_per_frame,
17292 &type);
17294 return(stat);
17297 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
17298 (tng_trajectory_t tng_data,
17299 const int64_t block_id,
17300 void **values,
17301 char *data_type,
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;
17308 int size;
17309 int64_t i, data_size, n_particles;
17310 void *temp;
17311 long file_pos;
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)
17333 return(stat);
17335 stat = tng_particle_data_find(tng_data, block_id, &data);
17336 if(stat != TNG_SUCCESS)
17338 return(stat);
17341 if(data->last_retrieved_frame < 0)
17343 fseek(tng_data->input_file,
17344 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17345 SEEK_SET);
17346 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17347 if(stat != TNG_SUCCESS)
17349 return(stat);
17351 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17352 if(stat != TNG_SUCCESS)
17354 return(stat);
17357 i = data->first_frame_with_data;
17359 else
17361 if(data->n_frames == 1)
17363 i = data->last_retrieved_frame + 1;
17365 else
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
17377 * frame set. */
17378 if(stat == TNG_CRITICAL)
17380 return(stat);
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)
17394 return(stat);
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;
17406 else
17408 *retrieved_time = 0;
17411 if(data->stride_length > 1)
17413 i = (i - data->first_frame_with_data) / data->stride_length;
17415 else
17417 i = (i - frame_set->first_frame);
17420 tng_num_particles_get(tng_data, &n_particles);
17422 *data_type = data->datatype;
17424 switch(*data_type)
17426 case TNG_CHAR_DATA:
17427 return(TNG_FAILURE);
17428 case TNG_INT_DATA:
17429 size = sizeof(int64_t);
17430 break;
17431 case TNG_FLOAT_DATA:
17432 size = sizeof(float);
17433 break;
17434 case TNG_DOUBLE_DATA:
17435 default:
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);
17445 if(!temp)
17447 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17448 data_size, __FILE__, __LINE__);
17449 free(*values);
17450 *values = 0;
17451 return(TNG_CRITICAL);
17454 *values = temp;
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,
17464 void **values,
17465 char *data_type,
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;
17472 int size;
17473 int64_t i, data_size;
17474 void *temp;
17475 long file_pos;
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)
17497 return(stat);
17499 stat = tng_data_find(tng_data, block_id, &data);
17500 if(stat != TNG_SUCCESS)
17502 return(stat);
17505 if(data->last_retrieved_frame < 0)
17507 fseek(tng_data->input_file,
17508 (long)tng_data->first_trajectory_frame_set_input_file_pos,
17509 SEEK_SET);
17510 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
17511 if(stat != TNG_SUCCESS)
17513 return(stat);
17515 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17516 if(stat != TNG_SUCCESS)
17518 return(stat);
17521 i = data->first_frame_with_data;
17523 else
17525 if(data->n_frames == 1)
17527 i = data->last_retrieved_frame + 1;
17529 else
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
17541 * frame set. */
17542 if(stat == TNG_CRITICAL)
17544 return(stat);
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)
17558 return(stat);
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;
17570 else
17572 *retrieved_time = 0;
17575 if(data->stride_length > 1)
17577 i = (i - data->first_frame_with_data) / data->stride_length;
17579 else
17581 i = (i - frame_set->first_frame);
17584 *data_type = data->datatype;
17586 switch(*data_type)
17588 case TNG_CHAR_DATA:
17589 return(TNG_FAILURE);
17590 case TNG_INT_DATA:
17591 size = sizeof(int64_t);
17592 break;
17593 case TNG_FLOAT_DATA:
17594 size = sizeof(float);
17595 break;
17596 case TNG_DOUBLE_DATA:
17597 default:
17598 size = sizeof(double);
17601 data_size = size * data->n_values_per_frame;
17603 temp = realloc(*values, data_size);
17604 if(!temp)
17606 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
17607 data_size, __FILE__, __LINE__);
17608 free(*values);
17609 *values = 0;
17610 return(TNG_CRITICAL);
17613 *values = temp;
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,
17624 float **positions,
17625 int64_t *stride_length)
17627 int64_t n_particles, n_values_per_frame;
17628 char type;
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,
17638 TNG_USE_HASH,
17639 (void **)positions,
17640 &n_particles,
17641 stride_length,
17642 &n_values_per_frame,
17643 &type);
17645 return(stat);
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;
17656 char type;
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,
17666 TNG_USE_HASH,
17667 (void **)velocities,
17668 &n_particles,
17669 stride_length,
17670 &n_values_per_frame,
17671 &type);
17673 return(stat);
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,
17680 float **forces,
17681 int64_t *stride_length)
17683 int64_t n_particles, n_values_per_frame;
17684 char type;
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,
17694 TNG_USE_HASH,
17695 (void **)forces,
17696 &n_particles,
17697 stride_length,
17698 &n_values_per_frame,
17699 &type);
17701 return(stat);
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,
17708 float **box_shape,
17709 int64_t *stride_length)
17711 int64_t n_values_per_frame;
17712 char type;
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,
17722 TNG_USE_HASH,
17723 (void **)box_shape,
17724 stride_length,
17725 &n_values_per_frame,
17726 &type);
17728 return(stat);
17731 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
17732 (tng_trajectory_t tng_data,
17733 const int64_t i,
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.");
17749 if(i <= 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__,
17766 __LINE__);
17767 return(stat);
17770 else
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)
17784 != TNG_SUCCESS)
17786 stat = tng_particle_data_block_add(tng_data, block_id,
17787 block_name,
17788 TNG_FLOAT_DATA,
17789 TNG_TRAJECTORY_BLOCK,
17790 n_frames, n_values_per_frame, i,
17791 0, n_particles,
17792 compression, 0);
17793 if(stat != TNG_SUCCESS)
17795 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17796 __FILE__, __LINE__);
17797 return(stat);
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,
17802 i, n_particles,
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__);
17808 return(stat);
17811 else
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,
17817 i, n_particles,
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__);
17823 return(stat);
17828 else
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__);
17840 return(stat);
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__);
17850 return(stat);
17853 else
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__);
17864 return(stat);
17870 return(TNG_SUCCESS);
17873 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
17874 (tng_trajectory_t tng_data,
17875 const int64_t i,
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.");
17891 if(i <= 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__,
17908 __LINE__);
17909 return(stat);
17912 else
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)
17927 != TNG_SUCCESS)
17929 stat = tng_particle_data_block_add(tng_data, block_id,
17930 block_name,
17931 TNG_DOUBLE_DATA,
17932 TNG_TRAJECTORY_BLOCK,
17933 n_frames, n_values_per_frame, i,
17934 0, n_particles,
17935 compression, 0);
17936 if(stat != TNG_SUCCESS)
17938 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
17939 __FILE__, __LINE__);
17940 return(stat);
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,
17945 i, n_particles,
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__);
17951 return(stat);
17954 else
17956 p_data->stride_length = i;
17959 else
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__);
17971 return(stat);
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__);
17981 return(stat);
17984 else
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,
17995 const int64_t i,
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,
18007 compression));
18009 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
18010 (tng_trajectory_t tng_data,
18011 const int64_t i)
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,
18018 "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,
18025 const int64_t i)
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,
18032 "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,
18039 const int64_t i)
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,
18048 const int64_t i)
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,
18055 "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,
18062 const int64_t i)
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,
18069 "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,
18076 const int64_t i)
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,
18085 const int64_t i)
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,
18091 TNG_TRAJ_FORCES,
18092 "FORCES",
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,
18099 const int64_t i)
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,
18105 TNG_TRAJ_FORCES,
18106 "FORCES",
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,
18113 const int64_t i)
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,
18122 const int64_t i)
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,
18129 "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,
18136 const int64_t i)
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,
18143 "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,
18150 const int64_t i)
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.");
18186 if(values == 0)
18188 return(TNG_FAILURE);
18191 frame_set = &tng_data->current_trajectory_frame_set;
18193 if(frame_nr < 0)
18195 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18196 n_frames = stride_length = 1;
18198 else
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__,
18208 __LINE__);
18209 return(stat);
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__,
18220 __LINE__);
18221 return(stat);
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__,
18232 __LINE__);
18233 return(stat);
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)
18249 != TNG_SUCCESS)
18251 stat = tng_particle_data_block_add(tng_data, block_id,
18252 block_name,
18253 TNG_FLOAT_DATA,
18254 block_type_flag,
18255 n_frames, n_values_per_frame,
18256 stride_length,
18257 0, n_particles,
18258 compression, 0);
18259 if(stat != TNG_SUCCESS)
18261 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18262 __FILE__, __LINE__);
18263 return(stat);
18265 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18267 p_data = &frame_set->tr_particle_data[frame_set->
18268 n_particle_data_blocks - 1];
18270 else
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__);
18282 return(stat);
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;
18293 frame_pos = 0;
18295 else
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);
18304 else
18306 memcpy(p_data->values, values, sizeof(float) * n_particles *
18307 n_values_per_frame);
18310 else
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__);
18322 return(stat);
18324 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18326 np_data = &frame_set->tr_data[frame_set->
18327 n_data_blocks - 1];
18329 else
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__);
18340 return(stat);
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;
18351 frame_pos = 0;
18353 else
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);
18362 else
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.");
18400 if(values == 0)
18402 return(TNG_FAILURE);
18405 frame_set = &tng_data->current_trajectory_frame_set;
18407 if(frame_nr < 0)
18409 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
18410 n_frames = stride_length = 1;
18412 else
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__,
18424 __LINE__);
18425 return(stat);
18428 else
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__,
18440 __LINE__);
18441 return(stat);
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__,
18451 __LINE__);
18452 return(stat);
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)
18466 != TNG_SUCCESS)
18468 stat = tng_particle_data_block_add(tng_data, block_id,
18469 block_name,
18470 TNG_DOUBLE_DATA,
18471 block_type_flag,
18472 n_frames, n_values_per_frame,
18473 stride_length,
18474 0, n_particles,
18475 compression, 0);
18476 if(stat != TNG_SUCCESS)
18478 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
18479 __FILE__, __LINE__);
18480 return(stat);
18482 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18484 p_data = &frame_set->tr_particle_data[frame_set->
18485 n_particle_data_blocks - 1];
18487 else
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__);
18499 return(stat);
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;
18510 frame_pos = 0;
18512 else
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);
18521 else
18523 memcpy(p_data->values, values, sizeof(double) * n_particles *
18524 n_values_per_frame);
18527 else
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__);
18539 return(stat);
18541 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
18543 np_data = &frame_set->tr_data[frame_set->
18544 n_data_blocks - 1];
18546 else
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__);
18557 return(stat);
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;
18568 frame_pos = 0;
18570 else
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);
18579 else
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,
18711 const double time,
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,
18730 compression);
18732 if(stat != TNG_SUCCESS)
18734 return(stat);
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,
18745 time -
18746 (frame_nr -
18747 frame_set->first_frame) *
18748 tng_data->time_per_frame);
18750 else
18752 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18755 return(stat);
18758 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
18759 (tng_trajectory_t tng_data,
18760 const int64_t frame_nr,
18761 const double time,
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,
18780 compression);
18782 if(stat != TNG_SUCCESS)
18784 return(stat);
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,
18795 time -
18796 (frame_nr -
18797 frame_set->first_frame) *
18798 tng_data->time_per_frame);
18800 else
18802 stat = tng_frame_set_first_frame_time_set(tng_data, time);
18805 return(stat);
18808 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
18809 (tng_trajectory_t tng_data,
18810 const int64_t frame_nr,
18811 const double time,
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,
18828 const double time,
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,
18837 positions, 3,
18838 TNG_TRAJ_POSITIONS,
18839 "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,
18847 const double time,
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,
18856 velocities, 3,
18857 TNG_TRAJ_VELOCITIES,
18858 "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,
18866 const double time,
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,
18875 velocities, 3,
18876 TNG_TRAJ_VELOCITIES,
18877 "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,
18885 const double time,
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,
18902 const double time,
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,
18911 forces, 3,
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,
18920 const double time,
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,
18937 const double time,
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,
18948 "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,
18956 int64_t *codec_id,
18957 double *factor)
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;
18963 int64_t i;
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;
18977 else
18979 stat = tng_data_find(tng_data, block_id, &np_data);
18980 if(stat == TNG_SUCCESS)
18982 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
18984 else
18986 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
18987 if(stat != TNG_SUCCESS)
18989 return(stat);
18991 stat = tng_particle_data_find(tng_data, block_id, &p_data);
18992 if(stat == TNG_SUCCESS)
18994 block_type = TNG_PARTICLE_BLOCK_DATA;
18996 else
18998 stat = tng_data_find(tng_data, block_id, &np_data);
18999 if(stat == TNG_SUCCESS)
19001 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
19003 else
19005 return(stat);
19010 if(block_type == TNG_PARTICLE_BLOCK_DATA)
19012 if(p_data->last_retrieved_frame < 0)
19014 i = p_data->first_frame_with_data;
19016 else
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;
19027 else
19029 i = np_data->last_retrieved_frame;
19032 else
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)
19041 return(stat);
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__);
19048 return(stat);
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;
19082 long file_pos;
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);
19094 if(!temp)
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
19120 * frame set. */
19121 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
19122 frame_set_file_pos)
19124 return(stat);
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 &&
19141 block->id != -1)
19143 stat = tng_block_read_next(tng_data, block,
19144 TNG_USE_HASH);
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__);
19159 return(stat);
19162 read_all = 1;
19165 min_diff = -1;
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)
19176 found = 0;
19177 for(j = 0; j < n_requested_data_block_ids; j++)
19179 if(block_id == requested_data_block_ids[j])
19181 found = 1;
19182 break;
19185 if(!found)
19187 continue;
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__);
19201 return(stat);
19203 if(stat == TNG_FAILURE)
19205 continue;
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;
19213 else
19215 data_frame = p_data->first_frame_with_data;
19217 frame_diff = data_frame - current_frame;
19218 if(frame_diff < 0)
19220 continue;
19222 if(min_diff == -1 || frame_diff <= min_diff)
19224 if(frame_diff < min_diff)
19226 *n_data_blocks_in_next_frame = 1;
19228 else
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);
19236 if(!temp)
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;
19247 else
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)
19263 found = 0;
19264 for(j = 0; j < n_requested_data_block_ids; j++)
19266 if(block_id == requested_data_block_ids[j])
19268 found = 1;
19269 break;
19272 if(!found)
19274 continue;
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__);
19288 return(stat);
19290 if(stat == TNG_FAILURE)
19292 continue;
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;
19300 else
19302 data_frame = np_data->first_frame_with_data;
19304 frame_diff = data_frame - current_frame;
19305 if(frame_diff < 0)
19307 continue;
19309 if(min_diff == -1 || frame_diff <= min_diff)
19311 if(frame_diff < min_diff)
19313 *n_data_blocks_in_next_frame = 1;
19315 else
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);
19323 if(!temp)
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;
19334 else
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;
19343 if(min_diff < 0)
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);
19382 file_pos = 0;
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)
19419 return(stat);
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);