Create separate module for trajectory data
[gromacs.git] / src / gromacs / fileio / tngio_for_tools.cpp
blobec99e120ae2a17a73235e50662d264a9882b5640
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 #include "gmxpre.h"
37 #include "tngio_for_tools.h"
39 #include "config.h"
41 #include <cmath>
43 #ifdef GMX_USE_TNG
44 #include "tng/tng_io.h"
45 #endif
47 #include "gromacs/fileio/tngio.h"
48 #include "gromacs/math/units.h"
49 #include "gromacs/trajectory/trajectoryframe.h"
50 #include "gromacs/utility/basedefinitions.h"
51 #include "gromacs/utility/fatalerror.h"
52 #include "gromacs/utility/smalloc.h"
54 void gmx_prepare_tng_writing(const char *filename,
55 char mode,
56 tng_trajectory_t *input,
57 tng_trajectory_t *output,
58 int nAtoms,
59 const gmx_mtop_t *mtop,
60 const int *index,
61 const char *indexGroupName)
63 #ifdef GMX_USE_TNG
64 /* FIXME after 5.0: Currently only standard block types are read */
65 const int defaultNumIds = 5;
66 static gmx_int64_t fallbackIds[defaultNumIds] =
68 TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
69 TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
70 TNG_GMX_LAMBDA
72 static char fallbackNames[defaultNumIds][32] =
74 "BOX SHAPE", "POSITIONS", "VELOCITIES",
75 "FORCES", "LAMBDAS"
78 typedef tng_function_status (*set_writing_interval_func_pointer)(tng_trajectory_t,
79 const gmx_int64_t,
80 const gmx_int64_t,
81 const gmx_int64_t,
82 const char*,
83 const char,
84 const char);
85 #ifdef GMX_DOUBLE
86 set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_double_set;
87 #else
88 set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_set;
89 #endif
91 gmx_tng_open(filename, mode, output);
93 /* Do we have an input file in TNG format? If so, then there's
94 more data we can copy over, rather than having to improvise. */
95 if (*input)
97 /* Set parameters (compression, time per frame, molecule
98 * information, number of frames per frame set and writing
99 * intervals of positions, box shape and lambdas) of the
100 * output tng container based on their respective values int
101 * the input tng container */
102 double time, compression_precision;
103 gmx_int64_t n_frames_per_frame_set, interval = -1;
105 tng_compression_precision_get(*input, &compression_precision);
106 tng_compression_precision_set(*output, compression_precision);
107 // TODO make this configurable in a future version
108 char compression_type = TNG_TNG_COMPRESSION;
110 tng_molecule_system_copy(*input, *output);
112 tng_time_per_frame_get(*input, &time);
113 tng_time_per_frame_set(*output, time);
115 tng_num_frames_per_frame_set_get(*input, &n_frames_per_frame_set);
116 tng_num_frames_per_frame_set_set(*output, n_frames_per_frame_set);
118 for (int i = 0; i < defaultNumIds; i++)
120 if (tng_data_get_stride_length(*input, fallbackIds[i], -1, &interval)
121 == TNG_SUCCESS)
123 switch (fallbackIds[i])
125 case TNG_TRAJ_POSITIONS:
126 case TNG_TRAJ_VELOCITIES:
127 set_writing_interval(*output, interval, 3, fallbackIds[i],
128 fallbackNames[i], TNG_PARTICLE_BLOCK_DATA,
129 compression_type);
130 break;
131 case TNG_TRAJ_FORCES:
132 set_writing_interval(*output, interval, 3, fallbackIds[i],
133 fallbackNames[i], TNG_PARTICLE_BLOCK_DATA,
134 TNG_GZIP_COMPRESSION);
135 break;
136 case TNG_TRAJ_BOX_SHAPE:
137 set_writing_interval(*output, interval, 9, fallbackIds[i],
138 fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA,
139 TNG_GZIP_COMPRESSION);
140 break;
141 case TNG_GMX_LAMBDA:
142 set_writing_interval(*output, interval, 1, fallbackIds[i],
143 fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA,
144 TNG_GZIP_COMPRESSION);
145 default:
146 continue;
152 else
154 /* TODO after trjconv is modularized: fix this so the user can
155 change precision when they are doing an operation where
156 this makes sense, and not otherwise.
158 char compression = bUseLossyCompression ? TNG_TNG_COMPRESSION : TNG_GZIP_COMPRESSION;
159 gmx_tng_set_compression_precision(*output, ndec2prec(nDecimalsOfPrecision));
161 gmx_tng_add_mtop(*output, mtop);
162 tng_num_frames_per_frame_set_set(*output, 1);
165 if (index && nAtoms > 0)
167 gmx_tng_setup_atom_subgroup(*output, nAtoms, index, indexGroupName);
170 /* If for some reason there are more requested atoms than there are atoms in the
171 * molecular system create a number of implicit atoms (without atom data) to
172 * compensate for that. */
173 if (nAtoms >= 0)
175 tng_implicit_num_particles_set(*output, nAtoms);
177 #else
178 GMX_UNUSED_VALUE(filename);
179 GMX_UNUSED_VALUE(mode);
180 GMX_UNUSED_VALUE(input);
181 GMX_UNUSED_VALUE(output);
182 GMX_UNUSED_VALUE(nAtoms);
183 GMX_UNUSED_VALUE(mtop);
184 GMX_UNUSED_VALUE(index);
185 GMX_UNUSED_VALUE(indexGroupName);
186 #endif
189 void gmx_write_tng_from_trxframe(tng_trajectory_t output,
190 t_trxframe *frame,
191 int natoms)
193 #ifdef GMX_USE_TNG
194 if (frame->step > 0)
196 double timePerFrame = frame->time * PICO / frame->step;
197 tng_time_per_frame_set(output, timePerFrame);
199 if (natoms < 0)
201 natoms = frame->natoms;
203 gmx_fwrite_tng(output,
204 TRUE,
205 frame->step,
206 frame->time,
208 frame->box,
209 natoms,
210 frame->x,
211 frame->v,
212 frame->f);
213 #else
214 GMX_UNUSED_VALUE(output);
215 GMX_UNUSED_VALUE(frame);
216 GMX_UNUSED_VALUE(natoms);
217 #endif
220 #ifdef GMX_USE_TNG
221 static void
222 convert_array_to_real_array(void *from,
223 real *to,
224 const float fact,
225 const int nAtoms,
226 const int nValues,
227 const char datatype)
229 int i, j;
231 switch (datatype)
233 case TNG_FLOAT_DATA:
234 if (sizeof(real) == sizeof(float))
236 if (fact == 1)
238 memcpy(to, from, nValues * sizeof(real) * nAtoms);
240 else
242 for (i = 0; i < nAtoms; i++)
244 for (j = 0; j < nValues; j++)
246 to[i*nValues+j] = reinterpret_cast<float *>(from)[i*nValues+j] * fact;
251 else
253 for (i = 0; i < nAtoms; i++)
255 for (j = 0; j < nValues; j++)
257 to[i*nValues+j] = reinterpret_cast<float *>(from)[i*nValues+j] * fact;
261 break;
262 case TNG_INT_DATA:
263 for (i = 0; i < nAtoms; i++)
265 for (j = 0; j < nValues; j++)
267 to[i*nValues+j] = reinterpret_cast<gmx_int64_t *>(from)[i*nValues+j] * fact;
270 break;
271 case TNG_DOUBLE_DATA:
272 if (sizeof(real) == sizeof(double))
274 if (fact == 1)
276 memcpy(to, from, nValues * sizeof(real) * nAtoms);
278 else
280 for (i = 0; i < nAtoms; i++)
282 for (j = 0; j < nValues; j++)
284 to[i*nValues+j] = reinterpret_cast<double *>(from)[i*nValues+j] * fact;
289 else
291 for (i = 0; i < nAtoms; i++)
293 for (j = 0; j < nValues; j++)
295 to[i*nValues+j] = reinterpret_cast<double *>(from)[i*nValues+j] * fact;
299 break;
300 default:
301 gmx_incons("Illegal datatype when converting values to a real array!");
302 return;
304 return;
307 static real getDistanceScaleFactor(tng_trajectory_t in)
309 gmx_int64_t exp = -1;
310 real distanceScaleFactor;
312 // TODO Hopefully, TNG 2.0 will do this kind of thing for us
313 tng_distance_unit_exponential_get(in, &exp);
315 // GROMACS expects distances in nm
316 switch (exp)
318 case 9:
319 distanceScaleFactor = NANO/NANO;
320 break;
321 case 10:
322 distanceScaleFactor = NANO/ANGSTROM;
323 break;
324 default:
325 distanceScaleFactor = pow(10.0, exp + 9.0);
328 return distanceScaleFactor;
330 #endif
332 void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng,
333 const int nind,
334 const int *ind,
335 const char *name)
337 #ifdef GMX_USE_TNG
338 gmx_int64_t nAtoms, cnt, nMols;
339 tng_molecule_t mol, iterMol;
340 tng_chain_t chain;
341 tng_residue_t res;
342 tng_atom_t atom;
343 tng_function_status stat;
345 tng_num_particles_get(tng, &nAtoms);
347 if (nAtoms == nind)
349 return;
352 stat = tng_molecule_find(tng, name, -1, &mol);
353 if (stat == TNG_SUCCESS)
355 tng_molecule_num_atoms_get(tng, mol, &nAtoms);
356 tng_molecule_cnt_get(tng, mol, &cnt);
357 if (nAtoms == nind)
359 stat = TNG_SUCCESS;
361 else
363 stat = TNG_FAILURE;
366 if (stat == TNG_FAILURE)
368 /* The indexed atoms are added to one separate molecule. */
369 tng_molecule_alloc(tng, &mol);
370 tng_molecule_name_set(tng, mol, name);
371 tng_molecule_chain_add(tng, mol, "", &chain);
373 for (int i = 0; i < nind; i++)
375 char temp_name[256], temp_type[256];
377 /* Try to retrieve the residue name of the atom */
378 stat = tng_residue_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
379 if (stat != TNG_SUCCESS)
381 temp_name[0] = '\0';
383 /* Check if the molecule of the selection already contains this residue */
384 if (tng_chain_residue_find(tng, chain, temp_name, -1, &res)
385 != TNG_SUCCESS)
387 tng_chain_residue_add(tng, chain, temp_name, &res);
389 /* Try to find the original name and type of the atom */
390 stat = tng_atom_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
391 if (stat != TNG_SUCCESS)
393 temp_name[0] = '\0';
395 stat = tng_atom_type_of_particle_nr_get(tng, ind[i], temp_type, 256);
396 if (stat != TNG_SUCCESS)
398 temp_type[0] = '\0';
400 tng_residue_atom_w_id_add(tng, res, temp_name, temp_type, ind[i], &atom);
402 tng_molecule_existing_add(tng, &mol);
404 /* Set the count of the molecule containing the selected atoms to 1 and all
405 * other molecules to 0 */
406 tng_molecule_cnt_set(tng, mol, 1);
407 tng_num_molecule_types_get(tng, &nMols);
408 for (gmx_int64_t k = 0; k < nMols; k++)
410 tng_molecule_of_index_get(tng, k, &iterMol);
411 if (iterMol == mol)
413 continue;
415 tng_molecule_cnt_set(tng, iterMol, 0);
417 #else
418 GMX_UNUSED_VALUE(tng);
419 GMX_UNUSED_VALUE(nind);
420 GMX_UNUSED_VALUE(ind);
421 GMX_UNUSED_VALUE(name);
422 #endif
425 /* TODO: If/when TNG acquires the ability to copy data blocks without
426 * uncompressing them, then this implemenation should be reconsidered.
427 * Ideally, gmx trjconv -f a.tng -o b.tng -b 10 -e 20 would be fast
428 * and lose no information. */
429 gmx_bool gmx_read_next_tng_frame(tng_trajectory_t input,
430 t_trxframe *fr,
431 gmx_int64_t *requestedIds,
432 int numRequestedIds)
434 #ifdef GMX_USE_TNG
435 gmx_bool bOK = TRUE;
436 tng_function_status stat;
437 gmx_int64_t numberOfAtoms = -1, frameNumber = -1;
438 gmx_int64_t nBlocks, blockId, *blockIds = NULL, codecId;
439 char datatype = -1;
440 void *values = NULL;
441 double frameTime = -1.0;
442 int size, blockDependency;
443 double prec;
444 const int defaultNumIds = 5;
445 static gmx_int64_t fallbackRequestedIds[defaultNumIds] =
447 TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
448 TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
449 TNG_GMX_LAMBDA
453 fr->bStep = FALSE;
454 fr->bTime = FALSE;
455 fr->bLambda = FALSE;
456 fr->bAtoms = FALSE;
457 fr->bPrec = FALSE;
458 fr->bX = FALSE;
459 fr->bV = FALSE;
460 fr->bF = FALSE;
461 fr->bBox = FALSE;
463 /* If no specific IDs were requested read all block types that can
464 * currently be interpreted */
465 if (!requestedIds || numRequestedIds == 0)
467 numRequestedIds = defaultNumIds;
468 requestedIds = fallbackRequestedIds;
471 stat = tng_num_particles_get(input, &numberOfAtoms);
472 if (stat != TNG_SUCCESS)
474 gmx_file("Cannot determine number of atoms from TNG file.");
476 fr->natoms = numberOfAtoms;
478 if (!gmx_get_tng_data_block_types_of_next_frame(input,
479 fr->step,
480 numRequestedIds,
481 requestedIds,
482 &frameNumber,
483 &nBlocks,
484 &blockIds))
486 return FALSE;
489 if (nBlocks == 0)
491 return FALSE;
494 for (gmx_int64_t i = 0; i < nBlocks; i++)
496 blockId = blockIds[i];
497 tng_data_block_dependency_get(input, blockId, &blockDependency);
498 if (blockDependency & TNG_PARTICLE_DEPENDENT)
500 stat = tng_util_particle_data_next_frame_read(input,
501 blockId,
502 &values,
503 &datatype,
504 &frameNumber,
505 &frameTime);
507 else
509 stat = tng_util_non_particle_data_next_frame_read(input,
510 blockId,
511 &values,
512 &datatype,
513 &frameNumber,
514 &frameTime);
516 if (stat == TNG_CRITICAL)
518 gmx_file("Cannot read positions from TNG file.");
519 return FALSE;
521 else if (stat == TNG_FAILURE)
523 continue;
525 switch (blockId)
527 case TNG_TRAJ_BOX_SHAPE:
528 switch (datatype)
530 case TNG_INT_DATA:
531 size = sizeof(gmx_int64_t);
532 break;
533 case TNG_FLOAT_DATA:
534 size = sizeof(float);
535 break;
536 case TNG_DOUBLE_DATA:
537 size = sizeof(double);
538 break;
539 default:
540 gmx_incons("Illegal datatype of box shape values!");
542 for (int i = 0; i < DIM; i++)
544 convert_array_to_real_array(reinterpret_cast<char *>(values) + size * i * DIM,
545 reinterpret_cast<real *>(fr->box[i]),
546 getDistanceScaleFactor(input),
548 DIM,
549 datatype);
551 fr->bBox = TRUE;
552 break;
553 case TNG_TRAJ_POSITIONS:
554 srenew(fr->x, fr->natoms);
555 convert_array_to_real_array(values,
556 reinterpret_cast<real *>(fr->x),
557 getDistanceScaleFactor(input),
558 fr->natoms,
559 DIM,
560 datatype);
561 fr->bX = TRUE;
562 tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
563 /* This must be updated if/when more lossy compression methods are added */
564 if (codecId == TNG_TNG_COMPRESSION)
566 fr->prec = prec;
567 fr->bPrec = TRUE;
569 break;
570 case TNG_TRAJ_VELOCITIES:
571 srenew(fr->v, fr->natoms);
572 convert_array_to_real_array(values,
573 (real *) fr->v,
574 getDistanceScaleFactor(input),
575 fr->natoms,
576 DIM,
577 datatype);
578 fr->bV = TRUE;
579 tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
580 /* This must be updated if/when more lossy compression methods are added */
581 if (codecId == TNG_TNG_COMPRESSION)
583 fr->prec = prec;
584 fr->bPrec = TRUE;
586 break;
587 case TNG_TRAJ_FORCES:
588 srenew(fr->f, fr->natoms);
589 convert_array_to_real_array(values,
590 reinterpret_cast<real *>(fr->f),
591 getDistanceScaleFactor(input),
592 fr->natoms,
593 DIM,
594 datatype);
595 fr->bF = TRUE;
596 break;
597 case TNG_GMX_LAMBDA:
598 switch (datatype)
600 case TNG_FLOAT_DATA:
601 fr->lambda = *(reinterpret_cast<float *>(values));
602 break;
603 case TNG_DOUBLE_DATA:
604 fr->lambda = *(reinterpret_cast<double *>(values));
605 break;
606 default:
607 gmx_incons("Illegal datatype lambda value!");
609 fr->bLambda = TRUE;
610 break;
611 default:
612 gmx_warning("Illegal block type! Currently GROMACS tools can only handle certain data types. Skipping block.");
614 /* values does not have to be freed before reading next frame. It will
615 * be reallocated if it is not NULL. */
618 fr->step = static_cast<int>(frameNumber);
619 fr->bStep = TRUE;
620 // Convert the time to ps
621 fr->time = frameTime / PICO;
622 fr->bTime = TRUE;
624 /* values must be freed before leaving this function */
625 sfree(values);
627 return bOK;
628 #else
629 GMX_UNUSED_VALUE(input);
630 GMX_UNUSED_VALUE(fr);
631 GMX_UNUSED_VALUE(requestedIds);
632 GMX_UNUSED_VALUE(numRequestedIds);
633 return FALSE;
634 #endif
637 void gmx_print_tng_molecule_system(tng_trajectory_t input,
638 FILE *stream)
640 #ifdef GMX_USE_TNG
641 gmx_int64_t nMolecules, nChains, nResidues, nAtoms, *molCntList;
642 tng_molecule_t molecule;
643 tng_chain_t chain;
644 tng_residue_t residue;
645 tng_atom_t atom;
646 char str[256], varNAtoms;
648 tng_num_molecule_types_get(input, &nMolecules);
649 tng_molecule_cnt_list_get(input, &molCntList);
650 /* Can the number of particles change in the trajectory or is it constant? */
651 tng_num_particles_variable_get(input, &varNAtoms);
653 for (gmx_int64_t i = 0; i < nMolecules; i++)
655 tng_molecule_of_index_get(input, i, &molecule);
656 tng_molecule_name_get(input, molecule, str, 256);
657 if (varNAtoms == TNG_CONSTANT_N_ATOMS)
659 if ((int)molCntList[i] == 0)
661 continue;
663 fprintf(stream, "Molecule: %s, count: %d\n", str, (int)molCntList[i]);
665 else
667 fprintf(stream, "Molecule: %s\n", str);
669 tng_molecule_num_chains_get(input, molecule, &nChains);
670 if (nChains > 0)
672 for (gmx_int64_t j = 0; j < nChains; j++)
674 tng_molecule_chain_of_index_get(input, molecule, j, &chain);
675 tng_chain_name_get(input, chain, str, 256);
676 fprintf(stream, "\tChain: %s\n", str);
677 tng_chain_num_residues_get(input, chain, &nResidues);
678 for (gmx_int64_t k = 0; k < nResidues; k++)
680 tng_chain_residue_of_index_get(input, chain, k, &residue);
681 tng_residue_name_get(input, residue, str, 256);
682 fprintf(stream, "\t\tResidue: %s\n", str);
683 tng_residue_num_atoms_get(input, residue, &nAtoms);
684 for (gmx_int64_t l = 0; l < nAtoms; l++)
686 tng_residue_atom_of_index_get(input, residue, l, &atom);
687 tng_atom_name_get(input, atom, str, 256);
688 fprintf(stream, "\t\t\tAtom: %s", str);
689 tng_atom_type_get(input, atom, str, 256);
690 fprintf(stream, " (%s)\n", str);
695 /* It is possible to have a molecule without chains, in which case
696 * residues in the molecule can be iterated through without going
697 * through chains. */
698 else
700 tng_molecule_num_residues_get(input, molecule, &nResidues);
701 if (nResidues > 0)
703 for (gmx_int64_t k = 0; k < nResidues; k++)
705 tng_molecule_residue_of_index_get(input, molecule, k, &residue);
706 tng_residue_name_get(input, residue, str, 256);
707 fprintf(stream, "\t\tResidue: %s\n", str);
708 tng_residue_num_atoms_get(input, residue, &nAtoms);
709 for (gmx_int64_t l = 0; l < nAtoms; l++)
711 tng_residue_atom_of_index_get(input, residue, l, &atom);
712 tng_atom_name_get(input, atom, str, 256);
713 fprintf(stream, "\t\t\tAtom: %s", str);
714 tng_atom_type_get(input, atom, str, 256);
715 fprintf(stream, " (%s)\n", str);
719 else
721 tng_molecule_num_atoms_get(input, molecule, &nAtoms);
722 for (gmx_int64_t l = 0; l < nAtoms; l++)
724 tng_molecule_atom_of_index_get(input, molecule, l, &atom);
725 tng_atom_name_get(input, atom, str, 256);
726 fprintf(stream, "\t\t\tAtom: %s", str);
727 tng_atom_type_get(input, atom, str, 256);
728 fprintf(stream, " (%s)\n", str);
733 #else
734 GMX_UNUSED_VALUE(input);
735 GMX_UNUSED_VALUE(stream);
736 #endif
739 gmx_bool gmx_get_tng_data_block_types_of_next_frame(tng_trajectory_t input,
740 int frame,
741 int nRequestedIds,
742 gmx_int64_t *requestedIds,
743 gmx_int64_t *nextFrame,
744 gmx_int64_t *nBlocks,
745 gmx_int64_t **blockIds)
747 #ifdef GMX_USE_TNG
748 tng_function_status stat;
750 stat = tng_util_trajectory_next_frame_present_data_blocks_find(input, frame,
751 nRequestedIds, requestedIds,
752 nextFrame,
753 nBlocks, blockIds);
755 if (stat == TNG_CRITICAL)
757 gmx_file("Cannot read TNG file. Cannot find data blocks of next frame.");
759 else if (stat == TNG_FAILURE)
761 return FALSE;
763 return TRUE;
764 #else
765 GMX_UNUSED_VALUE(input);
766 GMX_UNUSED_VALUE(frame);
767 GMX_UNUSED_VALUE(nRequestedIds);
768 GMX_UNUSED_VALUE(requestedIds);
769 GMX_UNUSED_VALUE(nextFrame);
770 GMX_UNUSED_VALUE(nBlocks);
771 GMX_UNUSED_VALUE(blockIds);
772 return FALSE;
773 #endif
776 gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t input,
777 gmx_int64_t blockId,
778 real **values,
779 gmx_int64_t *frameNumber,
780 double *frameTime,
781 gmx_int64_t *nValuesPerFrame,
782 gmx_int64_t *nAtoms,
783 real *prec,
784 char *name,
785 int maxLen,
786 gmx_bool *bOK)
788 #ifdef GMX_USE_TNG
789 tng_function_status stat;
790 char datatype = -1;
791 gmx_int64_t codecId;
792 int blockDependency;
793 void *data = 0;
794 double localPrec;
796 stat = tng_data_block_name_get(input, blockId, name, maxLen);
797 if (stat != TNG_SUCCESS)
799 gmx_file("Cannot read next frame of TNG file");
801 stat = tng_data_block_dependency_get(input, blockId, &blockDependency);
802 if (stat != TNG_SUCCESS)
804 gmx_file("Cannot read next frame of TNG file");
806 if (blockDependency & TNG_PARTICLE_DEPENDENT)
808 tng_num_particles_get(input, nAtoms);
809 stat = tng_util_particle_data_next_frame_read(input,
810 blockId,
811 &data,
812 &datatype,
813 frameNumber,
814 frameTime);
816 else
818 *nAtoms = 1; /* There are not actually any atoms, but it is used for
819 allocating memory */
820 stat = tng_util_non_particle_data_next_frame_read(input,
821 blockId,
822 &data,
823 &datatype,
824 frameNumber,
825 frameTime);
827 if (stat == TNG_CRITICAL)
829 gmx_file("Cannot read next frame of TNG file");
831 if (stat == TNG_FAILURE)
833 *bOK = TRUE;
834 return FALSE;
837 stat = tng_data_block_num_values_per_frame_get(input, blockId, nValuesPerFrame);
838 if (stat != TNG_SUCCESS)
840 gmx_file("Cannot read next frame of TNG file");
842 snew(*values, sizeof(real) * *nValuesPerFrame * *nAtoms);
843 convert_array_to_real_array(data,
844 *values,
845 getDistanceScaleFactor(input),
846 *nAtoms,
847 *nValuesPerFrame,
848 datatype);
850 tng_util_frame_current_compression_get(input, blockId, &codecId, &localPrec);
852 /* This must be updated if/when more lossy compression methods are added */
853 if (codecId != TNG_TNG_COMPRESSION)
855 *prec = -1.0;
857 else
859 *prec = localPrec;
862 *bOK = TRUE;
863 return TRUE;
864 #else
865 GMX_UNUSED_VALUE(input);
866 GMX_UNUSED_VALUE(blockId);
867 GMX_UNUSED_VALUE(values);
868 GMX_UNUSED_VALUE(frameNumber);
869 GMX_UNUSED_VALUE(frameTime);
870 GMX_UNUSED_VALUE(nValuesPerFrame);
871 GMX_UNUSED_VALUE(nAtoms);
872 GMX_UNUSED_VALUE(prec);
873 GMX_UNUSED_VALUE(name);
874 GMX_UNUSED_VALUE(maxLen);
875 GMX_UNUSED_VALUE(bOK);
876 return FALSE;
877 #endif