Consolidate files supporting TNG file I/O
authorMark Abraham <mark.j.abraham@gmail.com>
Sat, 19 Nov 2016 16:46:56 +0000 (17:46 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Thu, 8 Dec 2016 01:16:05 +0000 (12:16 +1100)
The distinction between mdrun and tools in supporting TNG file formats
isn't useful, and makes it difficult to implement a wrapper type that
will mean GROMACS code depends on tng_trajectory_t only in one
source file.

Change-Id: Iea0d337b6f11599a33c6c8ba3857a31a839f8d59

src/gromacs/fileio/tngio.cpp
src/gromacs/fileio/tngio.h
src/gromacs/fileio/tngio_for_tools.cpp [deleted file]
src/gromacs/fileio/tngio_for_tools.h [deleted file]
src/gromacs/fileio/trxio.cpp
src/gromacs/gmxana/gmx_trjcat.cpp
src/gromacs/gmxana/gmx_trjconv.cpp
src/gromacs/tools/dump.cpp

index 13d9cbd70ed14ce4a7b9be4a3ed84de68641c3bc..8c4052a210681814235e49cef1ac1cd64ae21581 100644 (file)
 
 #include "config.h"
 
+#include <cmath>
+
+#include <memory>
+
 #if GMX_USE_TNG
 #include "tng/tng_io.h"
 #endif
 #include "gromacs/mdtypes/inputrec.h"
 #include "gromacs/topology/ifunc.h"
 #include "gromacs/topology/topology.h"
+#include "gromacs/trajectory/trajectoryframe.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/baseversion.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/futil.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/programcontext.h"
+#include "gromacs/utility/smalloc.h"
 #include "gromacs/utility/sysinfo.h"
 
 static const char *modeToVerb(char mode)
@@ -868,3 +874,835 @@ float gmx_tng_get_time_of_final_frame(tng_trajectory_t tng)
     return -1.0;
 #endif
 }
+
+void gmx_prepare_tng_writing(const char              *filename,
+                             char                     mode,
+                             tng_trajectory_t        *input,
+                             tng_trajectory_t        *output,
+                             int                      nAtoms,
+                             const gmx_mtop_t        *mtop,
+                             const int               *index,
+                             const char              *indexGroupName)
+{
+#if GMX_USE_TNG
+    /* FIXME after 5.0: Currently only standard block types are read */
+    const int           defaultNumIds              = 5;
+    static gmx_int64_t  fallbackIds[defaultNumIds] =
+    {
+        TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
+        TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
+        TNG_GMX_LAMBDA
+    };
+    static char         fallbackNames[defaultNumIds][32] =
+    {
+        "BOX SHAPE", "POSITIONS", "VELOCITIES",
+        "FORCES", "LAMBDAS"
+    };
+
+    typedef tng_function_status (*set_writing_interval_func_pointer)(tng_trajectory_t,
+                                                                     const gmx_int64_t,
+                                                                     const gmx_int64_t,
+                                                                     const gmx_int64_t,
+                                                                     const char*,
+                                                                     const char,
+                                                                     const char);
+#if GMX_DOUBLE
+    set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_double_set;
+#else
+    set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_set;
+#endif
+
+    gmx_tng_open(filename, mode, output);
+
+    /* Do we have an input file in TNG format? If so, then there's
+       more data we can copy over, rather than having to improvise. */
+    if (*input)
+    {
+        /* Set parameters (compression, time per frame, molecule
+         * information, number of frames per frame set and writing
+         * intervals of positions, box shape and lambdas) of the
+         * output tng container based on their respective values int
+         * the input tng container */
+        double      time, compression_precision;
+        gmx_int64_t n_frames_per_frame_set, interval = -1;
+
+        tng_compression_precision_get(*input, &compression_precision);
+        tng_compression_precision_set(*output, compression_precision);
+        // TODO make this configurable in a future version
+        char compression_type = TNG_TNG_COMPRESSION;
+
+        tng_molecule_system_copy(*input, *output);
+
+        tng_time_per_frame_get(*input, &time);
+        tng_time_per_frame_set(*output, time);
+
+        tng_num_frames_per_frame_set_get(*input, &n_frames_per_frame_set);
+        tng_num_frames_per_frame_set_set(*output, n_frames_per_frame_set);
+
+        for (int i = 0; i < defaultNumIds; i++)
+        {
+            if (tng_data_get_stride_length(*input, fallbackIds[i], -1, &interval)
+                == TNG_SUCCESS)
+            {
+                switch (fallbackIds[i])
+                {
+                    case TNG_TRAJ_POSITIONS:
+                    case TNG_TRAJ_VELOCITIES:
+                        set_writing_interval(*output, interval, 3, fallbackIds[i],
+                                             fallbackNames[i], TNG_PARTICLE_BLOCK_DATA,
+                                             compression_type);
+                        break;
+                    case TNG_TRAJ_FORCES:
+                        set_writing_interval(*output, interval, 3, fallbackIds[i],
+                                             fallbackNames[i], TNG_PARTICLE_BLOCK_DATA,
+                                             TNG_GZIP_COMPRESSION);
+                        break;
+                    case TNG_TRAJ_BOX_SHAPE:
+                        set_writing_interval(*output, interval, 9, fallbackIds[i],
+                                             fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA,
+                                             TNG_GZIP_COMPRESSION);
+                        break;
+                    case TNG_GMX_LAMBDA:
+                        set_writing_interval(*output, interval, 1, fallbackIds[i],
+                                             fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA,
+                                             TNG_GZIP_COMPRESSION);
+                    default:
+                        continue;
+                }
+            }
+        }
+
+    }
+    else
+    {
+        /* TODO after trjconv is modularized: fix this so the user can
+           change precision when they are doing an operation where
+           this makes sense, and not otherwise.
+
+           char compression = bUseLossyCompression ? TNG_TNG_COMPRESSION : TNG_GZIP_COMPRESSION;
+           gmx_tng_set_compression_precision(*output, ndec2prec(nDecimalsOfPrecision));
+         */
+        gmx_tng_add_mtop(*output, mtop);
+        tng_num_frames_per_frame_set_set(*output, 1);
+    }
+
+    if (index && nAtoms > 0)
+    {
+        gmx_tng_setup_atom_subgroup(*output, nAtoms, index, indexGroupName);
+    }
+
+    /* If for some reason there are more requested atoms than there are atoms in the
+     * molecular system create a number of implicit atoms (without atom data) to
+     * compensate for that. */
+    if (nAtoms >= 0)
+    {
+        tng_implicit_num_particles_set(*output, nAtoms);
+    }
+#else
+    GMX_UNUSED_VALUE(filename);
+    GMX_UNUSED_VALUE(mode);
+    GMX_UNUSED_VALUE(input);
+    GMX_UNUSED_VALUE(output);
+    GMX_UNUSED_VALUE(nAtoms);
+    GMX_UNUSED_VALUE(mtop);
+    GMX_UNUSED_VALUE(index);
+    GMX_UNUSED_VALUE(indexGroupName);
+#endif
+}
+
+void gmx_write_tng_from_trxframe(tng_trajectory_t        output,
+                                 const t_trxframe       *frame,
+                                 int                     natoms)
+{
+#if GMX_USE_TNG
+    if (frame->step > 0)
+    {
+        double timePerFrame = frame->time * PICO / frame->step;
+        tng_time_per_frame_set(output, timePerFrame);
+    }
+    if (natoms < 0)
+    {
+        natoms = frame->natoms;
+    }
+    gmx_fwrite_tng(output,
+                   TRUE,
+                   frame->step,
+                   frame->time,
+                   0,
+                   frame->box,
+                   natoms,
+                   frame->x,
+                   frame->v,
+                   frame->f);
+#else
+    GMX_UNUSED_VALUE(output);
+    GMX_UNUSED_VALUE(frame);
+    GMX_UNUSED_VALUE(natoms);
+#endif
+}
+
+namespace
+{
+
+#if GMX_USE_TNG
+void
+convert_array_to_real_array(void       *from,
+                            real       *to,
+                            const float fact,
+                            const int   nAtoms,
+                            const int   nValues,
+                            const char  datatype)
+{
+    int        i, j;
+
+    const bool useDouble = GMX_DOUBLE;
+    switch (datatype)
+    {
+        case TNG_FLOAT_DATA:
+            if (!useDouble)
+            {
+                if (fact == 1)
+                {
+                    memcpy(to, from, nValues * sizeof(real) * nAtoms);
+                }
+                else
+                {
+                    for (i = 0; i < nAtoms; i++)
+                    {
+                        for (j = 0; j < nValues; j++)
+                        {
+                            to[i*nValues+j] = reinterpret_cast<float *>(from)[i*nValues+j] * fact;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (i = 0; i < nAtoms; i++)
+                {
+                    for (j = 0; j < nValues; j++)
+                    {
+                        to[i*nValues+j] = reinterpret_cast<float *>(from)[i*nValues+j] * fact;
+                    }
+                }
+            }
+            break;
+        case TNG_INT_DATA:
+            for (i = 0; i < nAtoms; i++)
+            {
+                for (j = 0; j < nValues; j++)
+                {
+                    to[i*nValues+j] = reinterpret_cast<gmx_int64_t *>(from)[i*nValues+j] * fact;
+                }
+            }
+            break;
+        case TNG_DOUBLE_DATA:
+            if (sizeof(real) == sizeof(double))
+            {
+                if (fact == 1)
+                {
+                    memcpy(to, from, nValues * sizeof(real) * nAtoms);
+                }
+                else
+                {
+                    for (i = 0; i < nAtoms; i++)
+                    {
+                        for (j = 0; j < nValues; j++)
+                        {
+                            to[i*nValues+j] = reinterpret_cast<double *>(from)[i*nValues+j] * fact;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (i = 0; i < nAtoms; i++)
+                {
+                    for (j = 0; j < nValues; j++)
+                    {
+                        to[i*nValues+j] = reinterpret_cast<double *>(from)[i*nValues+j] * fact;
+                    }
+                }
+            }
+            break;
+        default:
+            gmx_incons("Illegal datatype when converting values to a real array!");
+            return;
+    }
+    return;
+}
+
+real getDistanceScaleFactor(tng_trajectory_t in)
+{
+    gmx_int64_t exp = -1;
+    real        distanceScaleFactor;
+
+    // TODO Hopefully, TNG 2.0 will do this kind of thing for us
+    tng_distance_unit_exponential_get(in, &exp);
+
+    // GROMACS expects distances in nm
+    switch (exp)
+    {
+        case 9:
+            distanceScaleFactor = NANO/NANO;
+            break;
+        case 10:
+            distanceScaleFactor = NANO/ANGSTROM;
+            break;
+        default:
+            distanceScaleFactor = pow(10.0, exp + 9.0);
+    }
+
+    return distanceScaleFactor;
+}
+#endif
+
+} // namespace
+
+void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng,
+                                 const int        nind,
+                                 const int       *ind,
+                                 const char      *name)
+{
+#if GMX_USE_TNG
+    gmx_int64_t              nAtoms, cnt, nMols;
+    tng_molecule_t           mol, iterMol;
+    tng_chain_t              chain;
+    tng_residue_t            res;
+    tng_atom_t               atom;
+    tng_function_status      stat;
+
+    tng_num_particles_get(tng, &nAtoms);
+
+    if (nAtoms == nind)
+    {
+        return;
+    }
+
+    stat = tng_molecule_find(tng, name, -1, &mol);
+    if (stat == TNG_SUCCESS)
+    {
+        tng_molecule_num_atoms_get(tng, mol, &nAtoms);
+        tng_molecule_cnt_get(tng, mol, &cnt);
+        if (nAtoms == nind)
+        {
+            stat = TNG_SUCCESS;
+        }
+        else
+        {
+            stat = TNG_FAILURE;
+        }
+    }
+    if (stat == TNG_FAILURE)
+    {
+        /* The indexed atoms are added to one separate molecule. */
+        tng_molecule_alloc(tng, &mol);
+        tng_molecule_name_set(tng, mol, name);
+        tng_molecule_chain_add(tng, mol, "", &chain);
+
+        for (int i = 0; i < nind; i++)
+        {
+            char        temp_name[256], temp_type[256];
+
+            /* Try to retrieve the residue name of the atom */
+            stat = tng_residue_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
+            if (stat != TNG_SUCCESS)
+            {
+                temp_name[0] = '\0';
+            }
+            /* Check if the molecule of the selection already contains this residue */
+            if (tng_chain_residue_find(tng, chain, temp_name, -1, &res)
+                != TNG_SUCCESS)
+            {
+                tng_chain_residue_add(tng, chain, temp_name, &res);
+            }
+            /* Try to find the original name and type of the atom */
+            stat = tng_atom_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
+            if (stat != TNG_SUCCESS)
+            {
+                temp_name[0] = '\0';
+            }
+            stat = tng_atom_type_of_particle_nr_get(tng, ind[i], temp_type, 256);
+            if (stat != TNG_SUCCESS)
+            {
+                temp_type[0] = '\0';
+            }
+            tng_residue_atom_w_id_add(tng, res, temp_name, temp_type, ind[i], &atom);
+        }
+        tng_molecule_existing_add(tng, &mol);
+    }
+    /* Set the count of the molecule containing the selected atoms to 1 and all
+     * other molecules to 0 */
+    tng_molecule_cnt_set(tng, mol, 1);
+    tng_num_molecule_types_get(tng, &nMols);
+    for (gmx_int64_t k = 0; k < nMols; k++)
+    {
+        tng_molecule_of_index_get(tng, k, &iterMol);
+        if (iterMol == mol)
+        {
+            continue;
+        }
+        tng_molecule_cnt_set(tng, iterMol, 0);
+    }
+#else
+    GMX_UNUSED_VALUE(tng);
+    GMX_UNUSED_VALUE(nind);
+    GMX_UNUSED_VALUE(ind);
+    GMX_UNUSED_VALUE(name);
+#endif
+}
+
+/* TODO: If/when TNG acquires the ability to copy data blocks without
+ * uncompressing them, then this implemenation should be reconsidered.
+ * Ideally, gmx trjconv -f a.tng -o b.tng -b 10 -e 20 would be fast
+ * and lose no information. */
+gmx_bool gmx_read_next_tng_frame(tng_trajectory_t            input,
+                                 t_trxframe                 *fr,
+                                 gmx_int64_t                *requestedIds,
+                                 int                         numRequestedIds)
+{
+#if GMX_USE_TNG
+    gmx_bool                bOK = TRUE;
+    tng_function_status     stat;
+    gmx_int64_t             numberOfAtoms = -1, frameNumber = -1;
+    gmx_int64_t             nBlocks, blockId, *blockIds = NULL, codecId;
+    char                    datatype      = -1;
+    void                   *values        = NULL;
+    double                  frameTime     = -1.0;
+    int                     size, blockDependency;
+    double                  prec;
+    const int               defaultNumIds = 5;
+    static gmx_int64_t      fallbackRequestedIds[defaultNumIds] =
+    {
+        TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
+        TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
+        TNG_GMX_LAMBDA
+    };
+
+
+    fr->bStep     = FALSE;
+    fr->bTime     = FALSE;
+    fr->bLambda   = FALSE;
+    fr->bAtoms    = FALSE;
+    fr->bPrec     = FALSE;
+    fr->bX        = FALSE;
+    fr->bV        = FALSE;
+    fr->bF        = FALSE;
+    fr->bBox      = FALSE;
+
+    /* If no specific IDs were requested read all block types that can
+     * currently be interpreted */
+    if (!requestedIds || numRequestedIds == 0)
+    {
+        numRequestedIds = defaultNumIds;
+        requestedIds    = fallbackRequestedIds;
+    }
+
+    stat = tng_num_particles_get(input, &numberOfAtoms);
+    if (stat != TNG_SUCCESS)
+    {
+        gmx_file("Cannot determine number of atoms from TNG file.");
+    }
+    fr->natoms = numberOfAtoms;
+
+    if (!gmx_get_tng_data_block_types_of_next_frame(input,
+                                                    fr->step,
+                                                    numRequestedIds,
+                                                    requestedIds,
+                                                    &frameNumber,
+                                                    &nBlocks,
+                                                    &blockIds))
+    {
+        return FALSE;
+    }
+
+    if (nBlocks == 0)
+    {
+        return FALSE;
+    }
+
+    for (gmx_int64_t i = 0; i < nBlocks; i++)
+    {
+        blockId = blockIds[i];
+        tng_data_block_dependency_get(input, blockId, &blockDependency);
+        if (blockDependency & TNG_PARTICLE_DEPENDENT)
+        {
+            stat = tng_util_particle_data_next_frame_read(input,
+                                                          blockId,
+                                                          &values,
+                                                          &datatype,
+                                                          &frameNumber,
+                                                          &frameTime);
+        }
+        else
+        {
+            stat = tng_util_non_particle_data_next_frame_read(input,
+                                                              blockId,
+                                                              &values,
+                                                              &datatype,
+                                                              &frameNumber,
+                                                              &frameTime);
+        }
+        if (stat == TNG_CRITICAL)
+        {
+            gmx_file("Cannot read positions from TNG file.");
+            return FALSE;
+        }
+        else if (stat == TNG_FAILURE)
+        {
+            continue;
+        }
+        switch (blockId)
+        {
+            case TNG_TRAJ_BOX_SHAPE:
+                switch (datatype)
+                {
+                    case TNG_INT_DATA:
+                        size = sizeof(gmx_int64_t);
+                        break;
+                    case TNG_FLOAT_DATA:
+                        size = sizeof(float);
+                        break;
+                    case TNG_DOUBLE_DATA:
+                        size = sizeof(double);
+                        break;
+                    default:
+                        gmx_incons("Illegal datatype of box shape values!");
+                }
+                for (int i = 0; i < DIM; i++)
+                {
+                    convert_array_to_real_array(reinterpret_cast<char *>(values) + size * i * DIM,
+                                                reinterpret_cast<real *>(fr->box[i]),
+                                                getDistanceScaleFactor(input),
+                                                1,
+                                                DIM,
+                                                datatype);
+                }
+                fr->bBox = TRUE;
+                break;
+            case TNG_TRAJ_POSITIONS:
+                srenew(fr->x, fr->natoms);
+                convert_array_to_real_array(values,
+                                            reinterpret_cast<real *>(fr->x),
+                                            getDistanceScaleFactor(input),
+                                            fr->natoms,
+                                            DIM,
+                                            datatype);
+                fr->bX = TRUE;
+                tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
+                /* This must be updated if/when more lossy compression methods are added */
+                if (codecId == TNG_TNG_COMPRESSION)
+                {
+                    fr->prec  = prec;
+                    fr->bPrec = TRUE;
+                }
+                break;
+            case TNG_TRAJ_VELOCITIES:
+                srenew(fr->v, fr->natoms);
+                convert_array_to_real_array(values,
+                                            (real *) fr->v,
+                                            getDistanceScaleFactor(input),
+                                            fr->natoms,
+                                            DIM,
+                                            datatype);
+                fr->bV = TRUE;
+                tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
+                /* This must be updated if/when more lossy compression methods are added */
+                if (codecId == TNG_TNG_COMPRESSION)
+                {
+                    fr->prec  = prec;
+                    fr->bPrec = TRUE;
+                }
+                break;
+            case TNG_TRAJ_FORCES:
+                srenew(fr->f, fr->natoms);
+                convert_array_to_real_array(values,
+                                            reinterpret_cast<real *>(fr->f),
+                                            getDistanceScaleFactor(input),
+                                            fr->natoms,
+                                            DIM,
+                                            datatype);
+                fr->bF = TRUE;
+                break;
+            case TNG_GMX_LAMBDA:
+                switch (datatype)
+                {
+                    case TNG_FLOAT_DATA:
+                        fr->lambda = *(reinterpret_cast<float *>(values));
+                        break;
+                    case TNG_DOUBLE_DATA:
+                        fr->lambda = *(reinterpret_cast<double *>(values));
+                        break;
+                    default:
+                        gmx_incons("Illegal datatype lambda value!");
+                }
+                fr->bLambda = TRUE;
+                break;
+            default:
+                gmx_warning("Illegal block type! Currently GROMACS tools can only handle certain data types. Skipping block.");
+        }
+        /* values does not have to be freed before reading next frame. It will
+         * be reallocated if it is not NULL. */
+    }
+
+    fr->step  = frameNumber;
+    fr->bStep = TRUE;
+    // Convert the time to ps
+    fr->time  = frameTime / PICO;
+    fr->bTime = TRUE;
+
+    /* values must be freed before leaving this function */
+    sfree(values);
+
+    return bOK;
+#else
+    GMX_UNUSED_VALUE(input);
+    GMX_UNUSED_VALUE(fr);
+    GMX_UNUSED_VALUE(requestedIds);
+    GMX_UNUSED_VALUE(numRequestedIds);
+    return FALSE;
+#endif
+}
+
+void gmx_print_tng_molecule_system(tng_trajectory_t input,
+                                   FILE            *stream)
+{
+#if GMX_USE_TNG
+    gmx_int64_t        nMolecules, nChains, nResidues, nAtoms, *molCntList;
+    tng_molecule_t     molecule;
+    tng_chain_t        chain;
+    tng_residue_t      residue;
+    tng_atom_t         atom;
+    char               str[256], varNAtoms;
+
+    tng_num_molecule_types_get(input, &nMolecules);
+    tng_molecule_cnt_list_get(input, &molCntList);
+    /* Can the number of particles change in the trajectory or is it constant? */
+    tng_num_particles_variable_get(input, &varNAtoms);
+
+    for (gmx_int64_t i = 0; i < nMolecules; i++)
+    {
+        tng_molecule_of_index_get(input, i, &molecule);
+        tng_molecule_name_get(input, molecule, str, 256);
+        if (varNAtoms == TNG_CONSTANT_N_ATOMS)
+        {
+            if ((int)molCntList[i] == 0)
+            {
+                continue;
+            }
+            fprintf(stream, "Molecule: %s, count: %d\n", str, (int)molCntList[i]);
+        }
+        else
+        {
+            fprintf(stream, "Molecule: %s\n", str);
+        }
+        tng_molecule_num_chains_get(input, molecule, &nChains);
+        if (nChains > 0)
+        {
+            for (gmx_int64_t j = 0; j < nChains; j++)
+            {
+                tng_molecule_chain_of_index_get(input, molecule, j, &chain);
+                tng_chain_name_get(input, chain, str, 256);
+                fprintf(stream, "\tChain: %s\n", str);
+                tng_chain_num_residues_get(input, chain, &nResidues);
+                for (gmx_int64_t k = 0; k < nResidues; k++)
+                {
+                    tng_chain_residue_of_index_get(input, chain, k, &residue);
+                    tng_residue_name_get(input, residue, str, 256);
+                    fprintf(stream, "\t\tResidue: %s\n", str);
+                    tng_residue_num_atoms_get(input, residue, &nAtoms);
+                    for (gmx_int64_t l = 0; l < nAtoms; l++)
+                    {
+                        tng_residue_atom_of_index_get(input, residue, l, &atom);
+                        tng_atom_name_get(input, atom, str, 256);
+                        fprintf(stream, "\t\t\tAtom: %s", str);
+                        tng_atom_type_get(input, atom, str, 256);
+                        fprintf(stream, " (%s)\n", str);
+                    }
+                }
+            }
+        }
+        /* It is possible to have a molecule without chains, in which case
+         * residues in the molecule can be iterated through without going
+         * through chains. */
+        else
+        {
+            tng_molecule_num_residues_get(input, molecule, &nResidues);
+            if (nResidues > 0)
+            {
+                for (gmx_int64_t k = 0; k < nResidues; k++)
+                {
+                    tng_molecule_residue_of_index_get(input, molecule, k, &residue);
+                    tng_residue_name_get(input, residue, str, 256);
+                    fprintf(stream, "\t\tResidue: %s\n", str);
+                    tng_residue_num_atoms_get(input, residue, &nAtoms);
+                    for (gmx_int64_t l = 0; l < nAtoms; l++)
+                    {
+                        tng_residue_atom_of_index_get(input, residue, l, &atom);
+                        tng_atom_name_get(input, atom, str, 256);
+                        fprintf(stream, "\t\t\tAtom: %s", str);
+                        tng_atom_type_get(input, atom, str, 256);
+                        fprintf(stream, " (%s)\n", str);
+                    }
+                }
+            }
+            else
+            {
+                tng_molecule_num_atoms_get(input, molecule, &nAtoms);
+                for (gmx_int64_t l = 0; l < nAtoms; l++)
+                {
+                    tng_molecule_atom_of_index_get(input, molecule, l, &atom);
+                    tng_atom_name_get(input, atom, str, 256);
+                    fprintf(stream, "\t\t\tAtom: %s", str);
+                    tng_atom_type_get(input, atom, str, 256);
+                    fprintf(stream, " (%s)\n", str);
+                }
+            }
+        }
+    }
+#else
+    GMX_UNUSED_VALUE(input);
+    GMX_UNUSED_VALUE(stream);
+#endif
+}
+
+gmx_bool gmx_get_tng_data_block_types_of_next_frame(tng_trajectory_t     input,
+                                                    int                  frame,
+                                                    int                  nRequestedIds,
+                                                    gmx_int64_t         *requestedIds,
+                                                    gmx_int64_t         *nextFrame,
+                                                    gmx_int64_t         *nBlocks,
+                                                    gmx_int64_t        **blockIds)
+{
+#if GMX_USE_TNG
+    tng_function_status stat;
+
+    stat = tng_util_trajectory_next_frame_present_data_blocks_find(input, frame,
+                                                                   nRequestedIds, requestedIds,
+                                                                   nextFrame,
+                                                                   nBlocks, blockIds);
+
+    if (stat == TNG_CRITICAL)
+    {
+        gmx_file("Cannot read TNG file. Cannot find data blocks of next frame.");
+    }
+    else if (stat == TNG_FAILURE)
+    {
+        return FALSE;
+    }
+    return TRUE;
+#else
+    GMX_UNUSED_VALUE(input);
+    GMX_UNUSED_VALUE(frame);
+    GMX_UNUSED_VALUE(nRequestedIds);
+    GMX_UNUSED_VALUE(requestedIds);
+    GMX_UNUSED_VALUE(nextFrame);
+    GMX_UNUSED_VALUE(nBlocks);
+    GMX_UNUSED_VALUE(blockIds);
+    return FALSE;
+#endif
+}
+
+gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t     input,
+                                                   gmx_int64_t          blockId,
+                                                   real               **values,
+                                                   gmx_int64_t         *frameNumber,
+                                                   double              *frameTime,
+                                                   gmx_int64_t         *nValuesPerFrame,
+                                                   gmx_int64_t         *nAtoms,
+                                                   real                *prec,
+                                                   char                *name,
+                                                   int                  maxLen,
+                                                   gmx_bool            *bOK)
+{
+#if GMX_USE_TNG
+    tng_function_status stat;
+    char                datatype = -1;
+    gmx_int64_t         codecId;
+    int                 blockDependency;
+    void               *data = 0;
+    double              localPrec;
+
+    stat = tng_data_block_name_get(input, blockId, name, maxLen);
+    if (stat != TNG_SUCCESS)
+    {
+        gmx_file("Cannot read next frame of TNG file");
+    }
+    stat = tng_data_block_dependency_get(input, blockId, &blockDependency);
+    if (stat != TNG_SUCCESS)
+    {
+        gmx_file("Cannot read next frame of TNG file");
+    }
+    if (blockDependency & TNG_PARTICLE_DEPENDENT)
+    {
+        tng_num_particles_get(input, nAtoms);
+        stat = tng_util_particle_data_next_frame_read(input,
+                                                      blockId,
+                                                      &data,
+                                                      &datatype,
+                                                      frameNumber,
+                                                      frameTime);
+    }
+    else
+    {
+        *nAtoms = 1; /* There are not actually any atoms, but it is used for
+                        allocating memory */
+        stat    = tng_util_non_particle_data_next_frame_read(input,
+                                                             blockId,
+                                                             &data,
+                                                             &datatype,
+                                                             frameNumber,
+                                                             frameTime);
+    }
+    if (stat == TNG_CRITICAL)
+    {
+        gmx_file("Cannot read next frame of TNG file");
+    }
+    if (stat == TNG_FAILURE)
+    {
+        *bOK = TRUE;
+        return FALSE;
+    }
+
+    stat = tng_data_block_num_values_per_frame_get(input, blockId, nValuesPerFrame);
+    if (stat != TNG_SUCCESS)
+    {
+        gmx_file("Cannot read next frame of TNG file");
+    }
+    srenew(*values, sizeof(real) * *nValuesPerFrame * *nAtoms);
+    convert_array_to_real_array(data,
+                                *values,
+                                getDistanceScaleFactor(input),
+                                *nAtoms,
+                                *nValuesPerFrame,
+                                datatype);
+
+    tng_util_frame_current_compression_get(input, blockId, &codecId, &localPrec);
+
+    /* This must be updated if/when more lossy compression methods are added */
+    if (codecId != TNG_TNG_COMPRESSION)
+    {
+        *prec = -1.0;
+    }
+    else
+    {
+        *prec = localPrec;
+    }
+
+    *bOK = TRUE;
+    return TRUE;
+#else
+    GMX_UNUSED_VALUE(input);
+    GMX_UNUSED_VALUE(blockId);
+    GMX_UNUSED_VALUE(values);
+    GMX_UNUSED_VALUE(frameNumber);
+    GMX_UNUSED_VALUE(frameTime);
+    GMX_UNUSED_VALUE(nValuesPerFrame);
+    GMX_UNUSED_VALUE(nAtoms);
+    GMX_UNUSED_VALUE(prec);
+    GMX_UNUSED_VALUE(name);
+    GMX_UNUSED_VALUE(maxLen);
+    GMX_UNUSED_VALUE(bOK);
+    return FALSE;
+#endif
+}
index 4fb0851ca4333c9c72a9e30352ed06507e13fcc5..4881f2d8d9c4a0d463546e8fe3a0d7426da80869 100644 (file)
@@ -36,6 +36,8 @@
 #ifndef GMX_FILEIO_TNGIO_H
 #define GMX_FILEIO_TNGIO_H
 
+#include <cstdio>
+
 #include "gromacs/math/vectypes.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/real.h"
@@ -44,6 +46,7 @@ struct gmx_mtop_t;
 struct t_inputrec;
 struct tng_trajectory;
 typedef struct tng_trajectory *tng_trajectory_t;
+struct t_trxframe;
 
 /*! \brief Open a TNG trajectory file
  *
@@ -138,4 +141,69 @@ void fflush_tng(tng_trajectory_t tng);
  */
 float gmx_tng_get_time_of_final_frame(tng_trajectory_t tng);
 
+/*! \brief Prepare to write TNG output from trajectory conversion tools */
+void gmx_prepare_tng_writing(const char              *filename,
+                             char                     mode,
+                             tng_trajectory_t        *in,
+                             tng_trajectory_t        *out,
+                             int                      nAtoms,
+                             const struct gmx_mtop_t *mtop,
+                             const int               *index,
+                             const char              *indexGroupName);
+
+/*! \brief Write a trxframe to a TNG file
+ *
+ * \param output Trajectory to write to
+ * \param frame  Frame data to write
+ * \param natoms Number of atoms to actually write
+ *
+ * The natoms field in frame is the number of atoms in the system. The
+ * parameter natoms supports writing an index-group subset of the
+ * atoms.
+ */
+void gmx_write_tng_from_trxframe(tng_trajectory_t        output,
+                                 const t_trxframe       *frame,
+                                 int                     natoms);
+
+/*! \brief Creates a molecule containing only the indexed atoms and sets
+ * the number of all other molecules to 0. Works similar to a
+ * selection group. */
+void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng,
+                                 const int        nind,
+                                 const int       *ind,
+                                 const char      *name);
+
+/*! \brief Read the first/next TNG frame. */
+gmx_bool gmx_read_next_tng_frame(tng_trajectory_t            input,
+                                 struct t_trxframe          *fr,
+                                 gmx_int64_t                *requestedIds,
+                                 int                         numRequestedIds);
+
+/*! \brief Print the molecule system to stream */
+void gmx_print_tng_molecule_system(tng_trajectory_t input,
+                                   FILE            *stream);
+
+/*! \brief Get a list of block IDs present in the next frame with data. */
+gmx_bool gmx_get_tng_data_block_types_of_next_frame(tng_trajectory_t     input,
+                                                    int                  frame,
+                                                    int                  nRequestedIds,
+                                                    gmx_int64_t         *requestedIds,
+                                                    gmx_int64_t         *nextFrame,
+                                                    gmx_int64_t         *nBlocks,
+                                                    gmx_int64_t        **blockIds);
+
+/*! \brief Get data of the next frame with data from the data block
+ * with the specified block ID. */
+gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t     input,
+                                                   gmx_int64_t          blockId,
+                                                   real               **values,
+                                                   gmx_int64_t         *frameNumber,
+                                                   double              *frameTime,
+                                                   gmx_int64_t         *nValuesPerFrame,
+                                                   gmx_int64_t         *nAtoms,
+                                                   real                *prec,
+                                                   char                *name,
+                                                   int                  maxLen,
+                                                   gmx_bool            *bOK);
+
 #endif /* GMX_FILEIO_TNGIO_H */
diff --git a/src/gromacs/fileio/tngio_for_tools.cpp b/src/gromacs/fileio/tngio_for_tools.cpp
deleted file mode 100644 (file)
index 51839aa..0000000
+++ /dev/null
@@ -1,879 +0,0 @@
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2013,2014,2015,2016, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "tngio_for_tools.h"
-
-#include "config.h"
-
-#include <cmath>
-
-#if GMX_USE_TNG
-#include "tng/tng_io.h"
-#endif
-
-#include "gromacs/fileio/tngio.h"
-#include "gromacs/math/units.h"
-#include "gromacs/trajectory/trajectoryframe.h"
-#include "gromacs/utility/basedefinitions.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
-
-void gmx_prepare_tng_writing(const char              *filename,
-                             char                     mode,
-                             tng_trajectory_t        *input,
-                             tng_trajectory_t        *output,
-                             int                      nAtoms,
-                             const gmx_mtop_t        *mtop,
-                             const int               *index,
-                             const char              *indexGroupName)
-{
-#if GMX_USE_TNG
-    /* FIXME after 5.0: Currently only standard block types are read */
-    const int           defaultNumIds              = 5;
-    static gmx_int64_t  fallbackIds[defaultNumIds] =
-    {
-        TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
-        TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
-        TNG_GMX_LAMBDA
-    };
-    static char         fallbackNames[defaultNumIds][32] =
-    {
-        "BOX SHAPE", "POSITIONS", "VELOCITIES",
-        "FORCES", "LAMBDAS"
-    };
-
-    typedef tng_function_status (*set_writing_interval_func_pointer)(tng_trajectory_t,
-                                                                     const gmx_int64_t,
-                                                                     const gmx_int64_t,
-                                                                     const gmx_int64_t,
-                                                                     const char*,
-                                                                     const char,
-                                                                     const char);
-#if GMX_DOUBLE
-    set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_double_set;
-#else
-    set_writing_interval_func_pointer set_writing_interval = tng_util_generic_write_interval_set;
-#endif
-
-    gmx_tng_open(filename, mode, output);
-
-    /* Do we have an input file in TNG format? If so, then there's
-       more data we can copy over, rather than having to improvise. */
-    if (*input)
-    {
-        /* Set parameters (compression, time per frame, molecule
-         * information, number of frames per frame set and writing
-         * intervals of positions, box shape and lambdas) of the
-         * output tng container based on their respective values int
-         * the input tng container */
-        double      time, compression_precision;
-        gmx_int64_t n_frames_per_frame_set, interval = -1;
-
-        tng_compression_precision_get(*input, &compression_precision);
-        tng_compression_precision_set(*output, compression_precision);
-        // TODO make this configurable in a future version
-        char compression_type = TNG_TNG_COMPRESSION;
-
-        tng_molecule_system_copy(*input, *output);
-
-        tng_time_per_frame_get(*input, &time);
-        tng_time_per_frame_set(*output, time);
-
-        tng_num_frames_per_frame_set_get(*input, &n_frames_per_frame_set);
-        tng_num_frames_per_frame_set_set(*output, n_frames_per_frame_set);
-
-        for (int i = 0; i < defaultNumIds; i++)
-        {
-            if (tng_data_get_stride_length(*input, fallbackIds[i], -1, &interval)
-                == TNG_SUCCESS)
-            {
-                switch (fallbackIds[i])
-                {
-                    case TNG_TRAJ_POSITIONS:
-                    case TNG_TRAJ_VELOCITIES:
-                        set_writing_interval(*output, interval, 3, fallbackIds[i],
-                                             fallbackNames[i], TNG_PARTICLE_BLOCK_DATA,
-                                             compression_type);
-                        break;
-                    case TNG_TRAJ_FORCES:
-                        set_writing_interval(*output, interval, 3, fallbackIds[i],
-                                             fallbackNames[i], TNG_PARTICLE_BLOCK_DATA,
-                                             TNG_GZIP_COMPRESSION);
-                        break;
-                    case TNG_TRAJ_BOX_SHAPE:
-                        set_writing_interval(*output, interval, 9, fallbackIds[i],
-                                             fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA,
-                                             TNG_GZIP_COMPRESSION);
-                        break;
-                    case TNG_GMX_LAMBDA:
-                        set_writing_interval(*output, interval, 1, fallbackIds[i],
-                                             fallbackNames[i], TNG_NON_PARTICLE_BLOCK_DATA,
-                                             TNG_GZIP_COMPRESSION);
-                    default:
-                        continue;
-                }
-            }
-        }
-
-    }
-    else
-    {
-        /* TODO after trjconv is modularized: fix this so the user can
-           change precision when they are doing an operation where
-           this makes sense, and not otherwise.
-
-           char compression = bUseLossyCompression ? TNG_TNG_COMPRESSION : TNG_GZIP_COMPRESSION;
-           gmx_tng_set_compression_precision(*output, ndec2prec(nDecimalsOfPrecision));
-         */
-        gmx_tng_add_mtop(*output, mtop);
-        tng_num_frames_per_frame_set_set(*output, 1);
-    }
-
-    if (index && nAtoms > 0)
-    {
-        gmx_tng_setup_atom_subgroup(*output, nAtoms, index, indexGroupName);
-    }
-
-    /* If for some reason there are more requested atoms than there are atoms in the
-     * molecular system create a number of implicit atoms (without atom data) to
-     * compensate for that. */
-    if (nAtoms >= 0)
-    {
-        tng_implicit_num_particles_set(*output, nAtoms);
-    }
-#else
-    GMX_UNUSED_VALUE(filename);
-    GMX_UNUSED_VALUE(mode);
-    GMX_UNUSED_VALUE(input);
-    GMX_UNUSED_VALUE(output);
-    GMX_UNUSED_VALUE(nAtoms);
-    GMX_UNUSED_VALUE(mtop);
-    GMX_UNUSED_VALUE(index);
-    GMX_UNUSED_VALUE(indexGroupName);
-#endif
-}
-
-void gmx_write_tng_from_trxframe(tng_trajectory_t        output,
-                                 const t_trxframe       *frame,
-                                 int                     natoms)
-{
-#if GMX_USE_TNG
-    if (frame->step > 0)
-    {
-        double timePerFrame = frame->time * PICO / frame->step;
-        tng_time_per_frame_set(output, timePerFrame);
-    }
-    if (natoms < 0)
-    {
-        natoms = frame->natoms;
-    }
-    gmx_fwrite_tng(output,
-                   TRUE,
-                   frame->step,
-                   frame->time,
-                   0,
-                   frame->box,
-                   natoms,
-                   frame->x,
-                   frame->v,
-                   frame->f);
-#else
-    GMX_UNUSED_VALUE(output);
-    GMX_UNUSED_VALUE(frame);
-    GMX_UNUSED_VALUE(natoms);
-#endif
-}
-
-#if GMX_USE_TNG
-static void
-convert_array_to_real_array(void       *from,
-                            real       *to,
-                            const float fact,
-                            const int   nAtoms,
-                            const int   nValues,
-                            const char  datatype)
-{
-    int        i, j;
-
-    const bool useDouble = GMX_DOUBLE;
-    switch (datatype)
-    {
-        case TNG_FLOAT_DATA:
-            if (!useDouble)
-            {
-                if (fact == 1)
-                {
-                    memcpy(to, from, nValues * sizeof(real) * nAtoms);
-                }
-                else
-                {
-                    for (i = 0; i < nAtoms; i++)
-                    {
-                        for (j = 0; j < nValues; j++)
-                        {
-                            to[i*nValues+j] = reinterpret_cast<float *>(from)[i*nValues+j] * fact;
-                        }
-                    }
-                }
-            }
-            else
-            {
-                for (i = 0; i < nAtoms; i++)
-                {
-                    for (j = 0; j < nValues; j++)
-                    {
-                        to[i*nValues+j] = reinterpret_cast<float *>(from)[i*nValues+j] * fact;
-                    }
-                }
-            }
-            break;
-        case TNG_INT_DATA:
-            for (i = 0; i < nAtoms; i++)
-            {
-                for (j = 0; j < nValues; j++)
-                {
-                    to[i*nValues+j] = reinterpret_cast<gmx_int64_t *>(from)[i*nValues+j] * fact;
-                }
-            }
-            break;
-        case TNG_DOUBLE_DATA:
-            if (sizeof(real) == sizeof(double))
-            {
-                if (fact == 1)
-                {
-                    memcpy(to, from, nValues * sizeof(real) * nAtoms);
-                }
-                else
-                {
-                    for (i = 0; i < nAtoms; i++)
-                    {
-                        for (j = 0; j < nValues; j++)
-                        {
-                            to[i*nValues+j] = reinterpret_cast<double *>(from)[i*nValues+j] * fact;
-                        }
-                    }
-                }
-            }
-            else
-            {
-                for (i = 0; i < nAtoms; i++)
-                {
-                    for (j = 0; j < nValues; j++)
-                    {
-                        to[i*nValues+j] = reinterpret_cast<double *>(from)[i*nValues+j] * fact;
-                    }
-                }
-            }
-            break;
-        default:
-            gmx_incons("Illegal datatype when converting values to a real array!");
-            return;
-    }
-    return;
-}
-
-static real getDistanceScaleFactor(tng_trajectory_t in)
-{
-    gmx_int64_t exp = -1;
-    real        distanceScaleFactor;
-
-    // TODO Hopefully, TNG 2.0 will do this kind of thing for us
-    tng_distance_unit_exponential_get(in, &exp);
-
-    // GROMACS expects distances in nm
-    switch (exp)
-    {
-        case 9:
-            distanceScaleFactor = NANO/NANO;
-            break;
-        case 10:
-            distanceScaleFactor = NANO/ANGSTROM;
-            break;
-        default:
-            distanceScaleFactor = pow(10.0, exp + 9.0);
-    }
-
-    return distanceScaleFactor;
-}
-#endif
-
-void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng,
-                                 const int        nind,
-                                 const int       *ind,
-                                 const char      *name)
-{
-#if GMX_USE_TNG
-    gmx_int64_t              nAtoms, cnt, nMols;
-    tng_molecule_t           mol, iterMol;
-    tng_chain_t              chain;
-    tng_residue_t            res;
-    tng_atom_t               atom;
-    tng_function_status      stat;
-
-    tng_num_particles_get(tng, &nAtoms);
-
-    if (nAtoms == nind)
-    {
-        return;
-    }
-
-    stat = tng_molecule_find(tng, name, -1, &mol);
-    if (stat == TNG_SUCCESS)
-    {
-        tng_molecule_num_atoms_get(tng, mol, &nAtoms);
-        tng_molecule_cnt_get(tng, mol, &cnt);
-        if (nAtoms == nind)
-        {
-            stat = TNG_SUCCESS;
-        }
-        else
-        {
-            stat = TNG_FAILURE;
-        }
-    }
-    if (stat == TNG_FAILURE)
-    {
-        /* The indexed atoms are added to one separate molecule. */
-        tng_molecule_alloc(tng, &mol);
-        tng_molecule_name_set(tng, mol, name);
-        tng_molecule_chain_add(tng, mol, "", &chain);
-
-        for (int i = 0; i < nind; i++)
-        {
-            char        temp_name[256], temp_type[256];
-
-            /* Try to retrieve the residue name of the atom */
-            stat = tng_residue_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
-            if (stat != TNG_SUCCESS)
-            {
-                temp_name[0] = '\0';
-            }
-            /* Check if the molecule of the selection already contains this residue */
-            if (tng_chain_residue_find(tng, chain, temp_name, -1, &res)
-                != TNG_SUCCESS)
-            {
-                tng_chain_residue_add(tng, chain, temp_name, &res);
-            }
-            /* Try to find the original name and type of the atom */
-            stat = tng_atom_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
-            if (stat != TNG_SUCCESS)
-            {
-                temp_name[0] = '\0';
-            }
-            stat = tng_atom_type_of_particle_nr_get(tng, ind[i], temp_type, 256);
-            if (stat != TNG_SUCCESS)
-            {
-                temp_type[0] = '\0';
-            }
-            tng_residue_atom_w_id_add(tng, res, temp_name, temp_type, ind[i], &atom);
-        }
-        tng_molecule_existing_add(tng, &mol);
-    }
-    /* Set the count of the molecule containing the selected atoms to 1 and all
-     * other molecules to 0 */
-    tng_molecule_cnt_set(tng, mol, 1);
-    tng_num_molecule_types_get(tng, &nMols);
-    for (gmx_int64_t k = 0; k < nMols; k++)
-    {
-        tng_molecule_of_index_get(tng, k, &iterMol);
-        if (iterMol == mol)
-        {
-            continue;
-        }
-        tng_molecule_cnt_set(tng, iterMol, 0);
-    }
-#else
-    GMX_UNUSED_VALUE(tng);
-    GMX_UNUSED_VALUE(nind);
-    GMX_UNUSED_VALUE(ind);
-    GMX_UNUSED_VALUE(name);
-#endif
-}
-
-/* TODO: If/when TNG acquires the ability to copy data blocks without
- * uncompressing them, then this implemenation should be reconsidered.
- * Ideally, gmx trjconv -f a.tng -o b.tng -b 10 -e 20 would be fast
- * and lose no information. */
-gmx_bool gmx_read_next_tng_frame(tng_trajectory_t            input,
-                                 t_trxframe                 *fr,
-                                 gmx_int64_t                *requestedIds,
-                                 int                         numRequestedIds)
-{
-#if GMX_USE_TNG
-    gmx_bool                bOK = TRUE;
-    tng_function_status     stat;
-    gmx_int64_t             numberOfAtoms = -1, frameNumber = -1;
-    gmx_int64_t             nBlocks, blockId, *blockIds = NULL, codecId;
-    char                    datatype      = -1;
-    void                   *values        = NULL;
-    double                  frameTime     = -1.0;
-    int                     size, blockDependency;
-    double                  prec;
-    const int               defaultNumIds = 5;
-    static gmx_int64_t      fallbackRequestedIds[defaultNumIds] =
-    {
-        TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
-        TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
-        TNG_GMX_LAMBDA
-    };
-
-
-    fr->bStep     = FALSE;
-    fr->bTime     = FALSE;
-    fr->bLambda   = FALSE;
-    fr->bAtoms    = FALSE;
-    fr->bPrec     = FALSE;
-    fr->bX        = FALSE;
-    fr->bV        = FALSE;
-    fr->bF        = FALSE;
-    fr->bBox      = FALSE;
-
-    /* If no specific IDs were requested read all block types that can
-     * currently be interpreted */
-    if (!requestedIds || numRequestedIds == 0)
-    {
-        numRequestedIds = defaultNumIds;
-        requestedIds    = fallbackRequestedIds;
-    }
-
-    stat = tng_num_particles_get(input, &numberOfAtoms);
-    if (stat != TNG_SUCCESS)
-    {
-        gmx_file("Cannot determine number of atoms from TNG file.");
-    }
-    fr->natoms = numberOfAtoms;
-
-    if (!gmx_get_tng_data_block_types_of_next_frame(input,
-                                                    fr->step,
-                                                    numRequestedIds,
-                                                    requestedIds,
-                                                    &frameNumber,
-                                                    &nBlocks,
-                                                    &blockIds))
-    {
-        return FALSE;
-    }
-
-    if (nBlocks == 0)
-    {
-        return FALSE;
-    }
-
-    for (gmx_int64_t i = 0; i < nBlocks; i++)
-    {
-        blockId = blockIds[i];
-        tng_data_block_dependency_get(input, blockId, &blockDependency);
-        if (blockDependency & TNG_PARTICLE_DEPENDENT)
-        {
-            stat = tng_util_particle_data_next_frame_read(input,
-                                                          blockId,
-                                                          &values,
-                                                          &datatype,
-                                                          &frameNumber,
-                                                          &frameTime);
-        }
-        else
-        {
-            stat = tng_util_non_particle_data_next_frame_read(input,
-                                                              blockId,
-                                                              &values,
-                                                              &datatype,
-                                                              &frameNumber,
-                                                              &frameTime);
-        }
-        if (stat == TNG_CRITICAL)
-        {
-            gmx_file("Cannot read positions from TNG file.");
-            return FALSE;
-        }
-        else if (stat == TNG_FAILURE)
-        {
-            continue;
-        }
-        switch (blockId)
-        {
-            case TNG_TRAJ_BOX_SHAPE:
-                switch (datatype)
-                {
-                    case TNG_INT_DATA:
-                        size = sizeof(gmx_int64_t);
-                        break;
-                    case TNG_FLOAT_DATA:
-                        size = sizeof(float);
-                        break;
-                    case TNG_DOUBLE_DATA:
-                        size = sizeof(double);
-                        break;
-                    default:
-                        gmx_incons("Illegal datatype of box shape values!");
-                }
-                for (int i = 0; i < DIM; i++)
-                {
-                    convert_array_to_real_array(reinterpret_cast<char *>(values) + size * i * DIM,
-                                                reinterpret_cast<real *>(fr->box[i]),
-                                                getDistanceScaleFactor(input),
-                                                1,
-                                                DIM,
-                                                datatype);
-                }
-                fr->bBox = TRUE;
-                break;
-            case TNG_TRAJ_POSITIONS:
-                srenew(fr->x, fr->natoms);
-                convert_array_to_real_array(values,
-                                            reinterpret_cast<real *>(fr->x),
-                                            getDistanceScaleFactor(input),
-                                            fr->natoms,
-                                            DIM,
-                                            datatype);
-                fr->bX = TRUE;
-                tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
-                /* This must be updated if/when more lossy compression methods are added */
-                if (codecId == TNG_TNG_COMPRESSION)
-                {
-                    fr->prec  = prec;
-                    fr->bPrec = TRUE;
-                }
-                break;
-            case TNG_TRAJ_VELOCITIES:
-                srenew(fr->v, fr->natoms);
-                convert_array_to_real_array(values,
-                                            (real *) fr->v,
-                                            getDistanceScaleFactor(input),
-                                            fr->natoms,
-                                            DIM,
-                                            datatype);
-                fr->bV = TRUE;
-                tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
-                /* This must be updated if/when more lossy compression methods are added */
-                if (codecId == TNG_TNG_COMPRESSION)
-                {
-                    fr->prec  = prec;
-                    fr->bPrec = TRUE;
-                }
-                break;
-            case TNG_TRAJ_FORCES:
-                srenew(fr->f, fr->natoms);
-                convert_array_to_real_array(values,
-                                            reinterpret_cast<real *>(fr->f),
-                                            getDistanceScaleFactor(input),
-                                            fr->natoms,
-                                            DIM,
-                                            datatype);
-                fr->bF = TRUE;
-                break;
-            case TNG_GMX_LAMBDA:
-                switch (datatype)
-                {
-                    case TNG_FLOAT_DATA:
-                        fr->lambda = *(reinterpret_cast<float *>(values));
-                        break;
-                    case TNG_DOUBLE_DATA:
-                        fr->lambda = *(reinterpret_cast<double *>(values));
-                        break;
-                    default:
-                        gmx_incons("Illegal datatype lambda value!");
-                }
-                fr->bLambda = TRUE;
-                break;
-            default:
-                gmx_warning("Illegal block type! Currently GROMACS tools can only handle certain data types. Skipping block.");
-        }
-        /* values does not have to be freed before reading next frame. It will
-         * be reallocated if it is not NULL. */
-    }
-
-    fr->step  = frameNumber;
-    fr->bStep = TRUE;
-    // Convert the time to ps
-    fr->time  = frameTime / PICO;
-    fr->bTime = TRUE;
-
-    /* values must be freed before leaving this function */
-    sfree(values);
-
-    return bOK;
-#else
-    GMX_UNUSED_VALUE(input);
-    GMX_UNUSED_VALUE(fr);
-    GMX_UNUSED_VALUE(requestedIds);
-    GMX_UNUSED_VALUE(numRequestedIds);
-    return FALSE;
-#endif
-}
-
-void gmx_print_tng_molecule_system(tng_trajectory_t input,
-                                   FILE            *stream)
-{
-#if GMX_USE_TNG
-    gmx_int64_t        nMolecules, nChains, nResidues, nAtoms, *molCntList;
-    tng_molecule_t     molecule;
-    tng_chain_t        chain;
-    tng_residue_t      residue;
-    tng_atom_t         atom;
-    char               str[256], varNAtoms;
-
-    tng_num_molecule_types_get(input, &nMolecules);
-    tng_molecule_cnt_list_get(input, &molCntList);
-    /* Can the number of particles change in the trajectory or is it constant? */
-    tng_num_particles_variable_get(input, &varNAtoms);
-
-    for (gmx_int64_t i = 0; i < nMolecules; i++)
-    {
-        tng_molecule_of_index_get(input, i, &molecule);
-        tng_molecule_name_get(input, molecule, str, 256);
-        if (varNAtoms == TNG_CONSTANT_N_ATOMS)
-        {
-            if ((int)molCntList[i] == 0)
-            {
-                continue;
-            }
-            fprintf(stream, "Molecule: %s, count: %d\n", str, (int)molCntList[i]);
-        }
-        else
-        {
-            fprintf(stream, "Molecule: %s\n", str);
-        }
-        tng_molecule_num_chains_get(input, molecule, &nChains);
-        if (nChains > 0)
-        {
-            for (gmx_int64_t j = 0; j < nChains; j++)
-            {
-                tng_molecule_chain_of_index_get(input, molecule, j, &chain);
-                tng_chain_name_get(input, chain, str, 256);
-                fprintf(stream, "\tChain: %s\n", str);
-                tng_chain_num_residues_get(input, chain, &nResidues);
-                for (gmx_int64_t k = 0; k < nResidues; k++)
-                {
-                    tng_chain_residue_of_index_get(input, chain, k, &residue);
-                    tng_residue_name_get(input, residue, str, 256);
-                    fprintf(stream, "\t\tResidue: %s\n", str);
-                    tng_residue_num_atoms_get(input, residue, &nAtoms);
-                    for (gmx_int64_t l = 0; l < nAtoms; l++)
-                    {
-                        tng_residue_atom_of_index_get(input, residue, l, &atom);
-                        tng_atom_name_get(input, atom, str, 256);
-                        fprintf(stream, "\t\t\tAtom: %s", str);
-                        tng_atom_type_get(input, atom, str, 256);
-                        fprintf(stream, " (%s)\n", str);
-                    }
-                }
-            }
-        }
-        /* It is possible to have a molecule without chains, in which case
-         * residues in the molecule can be iterated through without going
-         * through chains. */
-        else
-        {
-            tng_molecule_num_residues_get(input, molecule, &nResidues);
-            if (nResidues > 0)
-            {
-                for (gmx_int64_t k = 0; k < nResidues; k++)
-                {
-                    tng_molecule_residue_of_index_get(input, molecule, k, &residue);
-                    tng_residue_name_get(input, residue, str, 256);
-                    fprintf(stream, "\t\tResidue: %s\n", str);
-                    tng_residue_num_atoms_get(input, residue, &nAtoms);
-                    for (gmx_int64_t l = 0; l < nAtoms; l++)
-                    {
-                        tng_residue_atom_of_index_get(input, residue, l, &atom);
-                        tng_atom_name_get(input, atom, str, 256);
-                        fprintf(stream, "\t\t\tAtom: %s", str);
-                        tng_atom_type_get(input, atom, str, 256);
-                        fprintf(stream, " (%s)\n", str);
-                    }
-                }
-            }
-            else
-            {
-                tng_molecule_num_atoms_get(input, molecule, &nAtoms);
-                for (gmx_int64_t l = 0; l < nAtoms; l++)
-                {
-                    tng_molecule_atom_of_index_get(input, molecule, l, &atom);
-                    tng_atom_name_get(input, atom, str, 256);
-                    fprintf(stream, "\t\t\tAtom: %s", str);
-                    tng_atom_type_get(input, atom, str, 256);
-                    fprintf(stream, " (%s)\n", str);
-                }
-            }
-        }
-    }
-#else
-    GMX_UNUSED_VALUE(input);
-    GMX_UNUSED_VALUE(stream);
-#endif
-}
-
-gmx_bool gmx_get_tng_data_block_types_of_next_frame(tng_trajectory_t     input,
-                                                    int                  frame,
-                                                    int                  nRequestedIds,
-                                                    gmx_int64_t         *requestedIds,
-                                                    gmx_int64_t         *nextFrame,
-                                                    gmx_int64_t         *nBlocks,
-                                                    gmx_int64_t        **blockIds)
-{
-#if GMX_USE_TNG
-    tng_function_status stat;
-
-    stat = tng_util_trajectory_next_frame_present_data_blocks_find(input, frame,
-                                                                   nRequestedIds, requestedIds,
-                                                                   nextFrame,
-                                                                   nBlocks, blockIds);
-
-    if (stat == TNG_CRITICAL)
-    {
-        gmx_file("Cannot read TNG file. Cannot find data blocks of next frame.");
-    }
-    else if (stat == TNG_FAILURE)
-    {
-        return FALSE;
-    }
-    return TRUE;
-#else
-    GMX_UNUSED_VALUE(input);
-    GMX_UNUSED_VALUE(frame);
-    GMX_UNUSED_VALUE(nRequestedIds);
-    GMX_UNUSED_VALUE(requestedIds);
-    GMX_UNUSED_VALUE(nextFrame);
-    GMX_UNUSED_VALUE(nBlocks);
-    GMX_UNUSED_VALUE(blockIds);
-    return FALSE;
-#endif
-}
-
-gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t     input,
-                                                   gmx_int64_t          blockId,
-                                                   real               **values,
-                                                   gmx_int64_t         *frameNumber,
-                                                   double              *frameTime,
-                                                   gmx_int64_t         *nValuesPerFrame,
-                                                   gmx_int64_t         *nAtoms,
-                                                   real                *prec,
-                                                   char                *name,
-                                                   int                  maxLen,
-                                                   gmx_bool            *bOK)
-{
-#if GMX_USE_TNG
-    tng_function_status stat;
-    char                datatype = -1;
-    gmx_int64_t         codecId;
-    int                 blockDependency;
-    void               *data = 0;
-    double              localPrec;
-
-    stat = tng_data_block_name_get(input, blockId, name, maxLen);
-    if (stat != TNG_SUCCESS)
-    {
-        gmx_file("Cannot read next frame of TNG file");
-    }
-    stat = tng_data_block_dependency_get(input, blockId, &blockDependency);
-    if (stat != TNG_SUCCESS)
-    {
-        gmx_file("Cannot read next frame of TNG file");
-    }
-    if (blockDependency & TNG_PARTICLE_DEPENDENT)
-    {
-        tng_num_particles_get(input, nAtoms);
-        stat = tng_util_particle_data_next_frame_read(input,
-                                                      blockId,
-                                                      &data,
-                                                      &datatype,
-                                                      frameNumber,
-                                                      frameTime);
-    }
-    else
-    {
-        *nAtoms = 1; /* There are not actually any atoms, but it is used for
-                        allocating memory */
-        stat    = tng_util_non_particle_data_next_frame_read(input,
-                                                             blockId,
-                                                             &data,
-                                                             &datatype,
-                                                             frameNumber,
-                                                             frameTime);
-    }
-    if (stat == TNG_CRITICAL)
-    {
-        gmx_file("Cannot read next frame of TNG file");
-    }
-    if (stat == TNG_FAILURE)
-    {
-        *bOK = TRUE;
-        return FALSE;
-    }
-
-    stat = tng_data_block_num_values_per_frame_get(input, blockId, nValuesPerFrame);
-    if (stat != TNG_SUCCESS)
-    {
-        gmx_file("Cannot read next frame of TNG file");
-    }
-    srenew(*values, sizeof(real) * *nValuesPerFrame * *nAtoms);
-    convert_array_to_real_array(data,
-                                *values,
-                                getDistanceScaleFactor(input),
-                                *nAtoms,
-                                *nValuesPerFrame,
-                                datatype);
-
-    tng_util_frame_current_compression_get(input, blockId, &codecId, &localPrec);
-
-    /* This must be updated if/when more lossy compression methods are added */
-    if (codecId != TNG_TNG_COMPRESSION)
-    {
-        *prec = -1.0;
-    }
-    else
-    {
-        *prec = localPrec;
-    }
-
-    *bOK = TRUE;
-    return TRUE;
-#else
-    GMX_UNUSED_VALUE(input);
-    GMX_UNUSED_VALUE(blockId);
-    GMX_UNUSED_VALUE(values);
-    GMX_UNUSED_VALUE(frameNumber);
-    GMX_UNUSED_VALUE(frameTime);
-    GMX_UNUSED_VALUE(nValuesPerFrame);
-    GMX_UNUSED_VALUE(nAtoms);
-    GMX_UNUSED_VALUE(prec);
-    GMX_UNUSED_VALUE(name);
-    GMX_UNUSED_VALUE(maxLen);
-    GMX_UNUSED_VALUE(bOK);
-    return FALSE;
-#endif
-}
diff --git a/src/gromacs/fileio/tngio_for_tools.h b/src/gromacs/fileio/tngio_for_tools.h
deleted file mode 100644 (file)
index c8da5d9..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2013,2014,2015,2016, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#ifndef GMX_FILEIO_TNGIO_FOR_TOOLS_H
-#define GMX_FILEIO_TNGIO_FOR_TOOLS_H
-
-#include <stdio.h>
-
-#include "gromacs/utility/basedefinitions.h"
-#include "gromacs/utility/real.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#if 0
-}
-#endif
-
-struct gmx_mtop_t;
-struct t_trxframe;
-struct tng_trajectory;
-typedef struct tng_trajectory *tng_trajectory_t;
-
-/*! \brief Prepare to write TNG output from trajectory conversion tools */
-void gmx_prepare_tng_writing(const char              *filename,
-                             char                     mode,
-                             tng_trajectory_t        *in,
-                             tng_trajectory_t        *out,
-                             int                      nAtoms,
-                             const struct gmx_mtop_t *mtop,
-                             const int               *index,
-                             const char              *indexGroupName);
-
-/*! \brief Write a trxframe to a TNG file
- *
- * \param output Trajectory to write to
- * \param frame  Frame data to write
- * \param natoms Number of atoms to actually write
- *
- * The natoms field in frame is the number of atoms in the system. The
- * parameter natoms supports writing an index-group subset of the
- * atoms.
- */
-void gmx_write_tng_from_trxframe(tng_trajectory_t        output,
-                                 const t_trxframe       *frame,
-                                 int                     natoms);
-
-/*! \brief Creates a molecule containing only the indexed atoms and sets
- * the number of all other molecules to 0. Works similar to a
- * selection group. */
-void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng,
-                                 const int        nind,
-                                 const int       *ind,
-                                 const char      *name);
-
-/*! \brief Read the first/next TNG frame. */
-gmx_bool gmx_read_next_tng_frame(tng_trajectory_t            input,
-                                 struct t_trxframe          *fr,
-                                 gmx_int64_t                *requestedIds,
-                                 int                         numRequestedIds);
-
-/*! \brief Print the molecule system to stream */
-void gmx_print_tng_molecule_system(tng_trajectory_t input,
-                                   FILE            *stream);
-
-/*! \brief Get a list of block IDs present in the next frame with data. */
-gmx_bool gmx_get_tng_data_block_types_of_next_frame(tng_trajectory_t     input,
-                                                    int                  frame,
-                                                    int                  nRequestedIds,
-                                                    gmx_int64_t         *requestedIds,
-                                                    gmx_int64_t         *nextFrame,
-                                                    gmx_int64_t         *nBlocks,
-                                                    gmx_int64_t        **blockIds);
-
-/*! \brief Get data of the next frame with data from the data block
- * with the specified block ID. */
-gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t     input,
-                                                   gmx_int64_t          blockId,
-                                                   real               **values,
-                                                   gmx_int64_t         *frameNumber,
-                                                   double              *frameTime,
-                                                   gmx_int64_t         *nValuesPerFrame,
-                                                   gmx_int64_t         *nAtoms,
-                                                   real                *prec,
-                                                   char                *name,
-                                                   int                  maxLen,
-                                                   gmx_bool            *bOK);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index 94432e65f9fc9e85a7c3fc4d25efded40d4fc565..b7fffd2594e4677335583d2d0ed4c10e74fd10ba 100644 (file)
@@ -55,7 +55,6 @@
 #include "gromacs/fileio/pdbio.h"
 #include "gromacs/fileio/timecontrol.h"
 #include "gromacs/fileio/tngio.h"
-#include "gromacs/fileio/tngio_for_tools.h"
 #include "gromacs/fileio/tpxio.h"
 #include "gromacs/fileio/trrio.h"
 #include "gromacs/fileio/xdrf.h"
index dc7e521f3025a2dc5e40b3ac07e65985e5b67661..3b5427d5f3f62e6acfa9bc2bde0bc01334b7ee54 100644 (file)
@@ -47,7 +47,6 @@
 #include "gromacs/fileio/gmxfio.h"
 #include "gromacs/fileio/pdbio.h"
 #include "gromacs/fileio/tngio.h"
-#include "gromacs/fileio/tngio_for_tools.h"
 #include "gromacs/fileio/trxio.h"
 #include "gromacs/fileio/xtcio.h"
 #include "gromacs/fileio/xvgr.h"
index cf975601f976e91a632a23dfce5570a09025cef1..f5781ed25c4807156b6af24cca50f7a7711924bb 100644 (file)
@@ -49,7 +49,7 @@
 #include "gromacs/fileio/gmxfio.h"
 #include "gromacs/fileio/groio.h"
 #include "gromacs/fileio/pdbio.h"
-#include "gromacs/fileio/tngio_for_tools.h"
+#include "gromacs/fileio/tngio.h"
 #include "gromacs/fileio/tpxio.h"
 #include "gromacs/fileio/trrio.h"
 #include "gromacs/fileio/trxio.h"
index 17196243034a9236066579cf80beb25999c4a83a..0c421ffd83c54e8b9b06d743c96c7c0b6ab633cc 100644 (file)
@@ -49,7 +49,6 @@
 #include "gromacs/fileio/gmxfio.h"
 #include "gromacs/fileio/mtxio.h"
 #include "gromacs/fileio/tngio.h"
-#include "gromacs/fileio/tngio_for_tools.h"
 #include "gromacs/fileio/tpxio.h"
 #include "gromacs/fileio/trrio.h"
 #include "gromacs/fileio/xtcio.h"