Reimplement constant acceleration groups
[alexxy/gromacs.git] / src / gromacs / topology / topology.h
index c9a226bd3e8f4ecb663f2f2de5c283ccb8d09d76..9278a2a8644e0f4a49a55c4c3be83a8b59b76651 100644 (file)
@@ -3,7 +3,8 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2016,2018, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2016,2018, The GROMACS development team.
+ * Copyright (c) 2019,2020,2021, 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.
 
 #include <cstdio>
 
+#include <vector>
+
 #include "gromacs/math/vectypes.h"
 #include "gromacs/topology/atoms.h"
 #include "gromacs/topology/block.h"
+#include "gromacs/topology/forcefieldparameters.h"
 #include "gromacs/topology/idef.h"
 #include "gromacs/topology/symtab.h"
+#include "gromacs/utility/enumerationhelpers.h"
+#include "gromacs/utility/listoflists.h"
+#include "gromacs/utility/unique_cptr.h"
 
-enum {
-    egcTC,    egcENER,   egcACC, egcFREEZE,
-    egcUser1, egcUser2,  egcVCM, egcCompressedX,
-    egcORFIT, egcQMMM,
-    egcNR
+enum class SimulationAtomGroupType : int
+{
+    TemperatureCoupling,
+    EnergyOutput,
+    Acceleration,
+    Freeze,
+    User1,
+    User2,
+    MassCenterVelocityRemoval,
+    CompressedPositionOutput,
+    OrientationRestraintsFit,
+    QuantumMechanics,
+    Count
 };
-/* Names corresponding to groups */
-extern const char *gtypes[egcNR+1];
 
-typedef struct gmx_moltype_t
+//! Short strings used for describing atom groups in log and energy files
+const char* shortName(SimulationAtomGroupType type);
+
+// const char *shortName(int type); // if necessary
+
+/*! \brief Molecules type data: atoms, interactions and exclusions */
+struct gmx_moltype_t
 {
-    char          **name;         /* Name of the molecule type            */
-    t_atoms         atoms;        /* The atoms in this molecule           */
-    t_ilist         ilist[F_NRE]; /* Interaction list with local indices  */
-    t_block         cgs;          /* The charge groups                    */
-    t_blocka        excls;        /* The exclusions                       */
-} gmx_moltype_t;
+    gmx_moltype_t();
+
+    ~gmx_moltype_t();
+
+    /*! \brief Deleted copy assignment operator to avoid (not) freeing pointers */
+    gmx_moltype_t& operator=(const gmx_moltype_t&) = delete;
+
+    /*! \brief Default copy constructor */
+    gmx_moltype_t(const gmx_moltype_t&) = default;
+
+    char**                name;  /**< Name of the molecule type            */
+    t_atoms               atoms; /**< The atoms in this molecule           */
+    InteractionLists      ilist; /**< Interaction list with local indices  */
+    gmx::ListOfLists<int> excls; /**< The exclusions                       */
+};
 
 /*! \brief Block of molecules of the same type, used in gmx_mtop_t */
-typedef struct gmx_molblock_t
+struct gmx_molblock_t
+{
+    int                    type = -1; /**< The molecule type index in mtop.moltype  */
+    int                    nmol = 0;  /**< The number of molecules in this block    */
+    std::vector<gmx::RVec> posres_xA; /**< Position restraint coordinates for top A */
+    std::vector<gmx::RVec> posres_xB; /**< Position restraint coordinates for top B */
+};
+
+/*! \brief Indices for a gmx_molblock_t, derived from other gmx_mtop_t contents */
+struct MoleculeBlockIndices
 {
-    int     type;               /**< The molecule type index in mtop.moltype  */
-    int     nmol;               /**< The number of molecules in this block    */
-    int     nposres_xA;         /**< The number of posres coords for top A    */
-    rvec   *posres_xA;          /**< Position restraint coordinates for top A */
-    int     nposres_xB;         /**< The number of posres coords for top B    */
-    rvec   *posres_xB;          /**< Position restraint coordinates for top B */
-
-    /* Convenience information, derived from other gmx_mtop_t contents     */
-    int     natoms_mol;         /**< The number of atoms in one molecule      */
-    int     globalAtomStart;    /**< Global atom index of the first atom in the block */
-    int     globalAtomEnd;      /**< Global atom index + 1 of the last atom in the block */
-    int     globalResidueStart; /**< Global residue index of the first residue in the block */
-    int     residueNumberStart; /**< Residue numbers start from this value if the number of residues per molecule is <= maxres_renum */
-    int     moleculeIndexStart; /**< Global molecule indexing starts from this value */
-} gmx_molblock_t;
-
-typedef struct gmx_groups_t
+    int numAtomsPerMolecule; /**< Number of atoms in a molecule in the block */
+    int globalAtomStart;     /**< Global atom index of the first atom in the block */
+    int globalAtomEnd;       /**< Global atom index + 1 of the last atom in the block */
+    int globalResidueStart;  /**< Global residue index of the first residue in the block */
+    int residueNumberStart; /**< Residue numbers start from this value if the number of residues per molecule is <= maxres_renum */
+    int moleculeIndexStart; /**< Global molecule indexing starts from this value */
+};
+
+/*! \brief Contains the simulation atom groups.
+ *
+ * Organized as containers for the different
+ * SimulationAtomGroupTypes
+ */
+struct SimulationGroups
 {
-    t_grps            grps[egcNR];  /* Groups of things                     */
-    int               ngrpname;     /* Number of groupnames                 */
-    char           ***grpname;      /* Names of the groups                  */
-    int               ngrpnr[egcNR];
-    unsigned char    *grpnr[egcNR]; /* Group numbers or NULL                */
-} gmx_groups_t;
-
-/* This macro gives the group number of group type egc for atom i.
- * This macro is useful, since the grpnr pointers are NULL
- * for group types that have all entries 0.
+    // TODO: collect groups and groupNumbers in a struct for each group type
+    //! Group numbers for each of the different SimulationAtomGroupType groups.
+    gmx::EnumerationArray<SimulationAtomGroupType, AtomGroupIndices> groups;
+    //! Names of groups, stored as pointer to the entries in the symbol table.
+    std::vector<char**> groupNames;
+    //! Indices into groups for each atom for each of the different SimulationAtomGroupType groups.
+    gmx::EnumerationArray<SimulationAtomGroupType, std::vector<unsigned char>> groupNumbers;
+
+    /*! \brief
+     * Number of atoms for which group numbers are stored for a single SimulationGroup.
+     *
+     * \param[in] group  The group type.
+     */
+    int numberOfGroupNumbers(SimulationAtomGroupType group) const
+    {
+        return static_cast<int>(groupNumbers[group].size());
+    }
+};
+
+/*! \brief
+ * Returns group number of an input group for a given atom.
+ *
+ * Returns the group \p type for \p atom in \p group, or 0 if the
+ * entries for all atoms in the group are 0 and the pointer is thus null.
+ *
+ * \param[in] group Group to check.
+ * \param[in] type  Type of group to check.
+ * \param[in] atom  Atom to check if it has an entry.
  */
-#define ggrpnr(groups, egc, i) ((groups)->grpnr[egc] ? (groups)->grpnr[egc][i] : 0)
+int getGroupType(const SimulationGroups& group, SimulationAtomGroupType type, int atom);
 
 /* The global, complete system topology struct, based on molecule types.
-   This structure should contain no data that is O(natoms) in memory. */
-typedef struct gmx_mtop_t
+ * This structure should contain no data that is O(natoms) in memory.
+ *
+ * TODO: Find a solution for ensuring that the derived data is in sync
+ *       with the primary data, possibly by converting to a class.
+ */
+struct gmx_mtop_t //NOLINT(clang-analyzer-optin.performance.Padding)
 {
-    char           **name;      /* Name of the topology                 */
-    gmx_ffparams_t   ffparams;
-    int              nmoltype;
-    gmx_moltype_t   *moltype;
-    int              nmolblock;
-    gmx_molblock_t  *molblock;
-    gmx_bool         bIntermolecularInteractions; /* Are there intermolecular
-                                                   * interactions?            */
-    t_ilist         *intermolecular_ilist;        /* List of intermolecular interactions
-                                                   * using system wide atom indices,
-                                                   * either NULL or size F_NRE           */
-    int              natoms;
-    int              maxres_renum;                /* Parameter for residue numbering      */
-    int              maxresnr;                    /* The maximum residue number in moltype */
-    t_atomtypes      atomtypes;                   /* Atomtype properties                  */
-    gmx_groups_t     groups;
-    t_symtab         symtab;                      /* The symbol table                     */
-    bool             haveMoleculeIndices;         /* Tells whether we have valid molecule indices */
-} gmx_mtop_t;
-
-/* The mdrun node-local topology struct, completely written out */
-typedef struct gmx_localtop_t
+    gmx_mtop_t();
+
+    ~gmx_mtop_t();
+
+    //! Name of the topology.
+    char** name = nullptr;
+    //! Force field parameters used.
+    gmx_ffparams_t ffparams;
+    //! Vector of different molecule types.
+    std::vector<gmx_moltype_t> moltype;
+    //! Vector of different molecule blocks.
+    std::vector<gmx_molblock_t> molblock;
+    //! Are there intermolecular interactions?
+    bool bIntermolecularInteractions = false;
+    /* \brief
+     * List of intermolecular interactions using system wide
+     * atom indices, either NULL or size F_NRE
+     */
+    std::unique_ptr<InteractionLists> intermolecular_ilist = nullptr;
+    //! Number of global atoms.
+    int natoms = 0;
+    //! Atomtype properties
+    t_atomtypes atomtypes;
+    //! Groups of atoms for different purposes
+    SimulationGroups groups;
+    //! The legacy symbol table
+    t_symtab symtab;
+    //! Tells whether we have valid molecule indices
+    bool haveMoleculeIndices = false;
+    /*! \brief List of global atom indices of atoms between which
+     * non-bonded interactions must be excluded.
+     */
+    std::vector<int> intermolecularExclusionGroup;
+
+    //! Maximum number of residues in molecule to trigger renumbering of residues
+    int maxResiduesPerMoleculeToTriggerRenumber() const
+    {
+        return maxResiduesPerMoleculeToTriggerRenumber_;
+    }
+    //! Maximum residue number that is not renumbered.
+    int maxResNumberNotRenumbered() const { return maxResNumberNotRenumbered_; }
+    /*! \brief Finalize this data structure.
+     *
+     * Should be called after generating or reading mtop, to set some compute
+     * intesive variables to avoid N^2 operations later on.
+     *
+     * \todo Move into a builder class, once available.
+     */
+    void finalize();
+
+    /* Derived data below */
+    //! Indices for each molblock entry for fast lookup of atom properties
+    std::vector<MoleculeBlockIndices> moleculeBlockIndices;
+
+private:
+    //! Build the molblock indices
+    void buildMolblockIndices();
+    //! Maximum number of residues in molecule to trigger renumbering of residues
+    int maxResiduesPerMoleculeToTriggerRenumber_ = 0;
+    //! The maximum residue number in moltype that is not renumbered
+    int maxResNumberNotRenumbered_ = -1;
+};
+
+/*! \brief
+ * The fully written out topology for a domain over its lifetime
+ *
+ * Also used in some analysis code.
+ */
+struct gmx_localtop_t
 {
-    t_idef        idef;         /* The interaction function definition  */
-    t_atomtypes   atomtypes;    /* Atomtype properties                  */
-    t_block       cgs;          /* The charge groups                    */
-    t_blocka      excls;        /* The exclusions                       */
-} gmx_localtop_t;
+    //! Constructor used for normal operation, manages own resources.
+    gmx_localtop_t(const gmx_ffparams_t& ffparams);
+
+    //! The interaction function definition
+    InteractionDefinitions idef;
+    //! The exclusions
+    gmx::ListOfLists<int> excls;
+};
 
 /* The old topology struct, completely written out, used in analysis tools */
 typedef struct t_topology
 {
-    char          **name;                        /* Name of the topology                 */
-    t_idef          idef;                        /* The interaction function definition  */
-    t_atoms         atoms;                       /* The atoms                            */
-    t_atomtypes     atomtypes;                   /* Atomtype properties                  */
-    t_block         cgs;                         /* The charge groups                    */
-    t_block         mols;                        /* The molecules                        */
-    gmx_bool        bIntermolecularInteractions; /* Inter.mol. int. ?   */
-    t_blocka        excls;                       /* The exclusions                       */
-    t_symtab        symtab;                      /* The symbol table                     */
+    char**      name;                        /* Name of the topology                 */
+    t_idef      idef;                        /* The interaction function definition  */
+    t_atoms     atoms;                       /* The atoms                            */
+    t_atomtypes atomtypes;                   /* Atomtype properties                  */
+    t_block     mols;                        /* The molecules                        */
+    gmx_bool    bIntermolecularInteractions; /* Inter.mol. int. ?   */
+    /* Note that the exclusions are not stored in t_topology */
+    t_symtab symtab; /* The symbol table                     */
 } t_topology;
 
-void init_mtop(gmx_mtop_t *mtop);
-void init_top(t_topology *top);
-void done_moltype(gmx_moltype_t *molt);
-void done_molblock(gmx_molblock_t *molb);
-void done_gmx_groups_t(gmx_groups_t *g);
-void done_mtop(gmx_mtop_t *mtop);
-void done_top(t_topology *top);
+void init_top(t_topology* top);
+void done_top(t_topology* top);
 // Frees both t_topology and gmx_mtop_t when the former has been created from
 // the latter.
-void done_top_mtop(t_topology *top, gmx_mtop_t *mtop);
+void done_top_mtop(t_topology* top, gmx_mtop_t* mtop);
+
+bool gmx_mtop_has_masses(const gmx_mtop_t* mtop);
+bool gmx_mtop_has_charges(const gmx_mtop_t* mtop);
+bool gmx_mtop_has_perturbed_charges(const gmx_mtop_t& mtop);
+bool gmx_mtop_has_atomtypes(const gmx_mtop_t* mtop);
+bool gmx_mtop_has_pdbinfo(const gmx_mtop_t* mtop);
+
+void pr_mtop(FILE* fp, int indent, const char* title, const gmx_mtop_t* mtop, gmx_bool bShowNumbers, gmx_bool bShowParameters);
+void pr_top(FILE* fp, int indent, const char* title, const t_topology* top, gmx_bool bShowNumbers, gmx_bool bShowParameters);
+
+/*! \brief Compare two mtop topologies.
+ *
+ * \param[in] fp File pointer to write to.
+ * \param[in] mtop1 First topology to compare.
+ * \param[in] mtop2 Second topology to compare.
+ * \param[in] relativeTolerance Relative tolerance for comparison.
+ * \param[in] absoluteTolerance Absolute tolerance for comparison.
+ */
+void compareMtop(FILE* fp, const gmx_mtop_t& mtop1, const gmx_mtop_t& mtop2, real relativeTolerance, real absoluteTolerance);
 
-bool gmx_mtop_has_masses(const gmx_mtop_t *mtop);
-bool gmx_mtop_has_charges(const gmx_mtop_t *mtop);
-bool gmx_mtop_has_atomtypes(const gmx_mtop_t *mtop);
-bool gmx_mtop_has_pdbinfo(const gmx_mtop_t *mtop);
+/*! \brief Check perturbation parameters in topology.
+ *
+ * \param[in] fp File pointer to write to.
+ * \param[in] mtop1 Topology to check perturbation parameters in.
+ * \param[in] relativeTolerance Relative tolerance for comparison.
+ * \param[in] absoluteTolerance Absolute tolerance for comparison.
+ */
+void compareMtopAB(FILE* fp, const gmx_mtop_t& mtop1, real relativeTolerance, real absoluteTolerance);
+
+/*! \brief Compare groups.
+ *
+ * \param[in] fp File pointer to write to.
+ * \param[in] g0 First group for comparison.
+ * \param[in] g1 Second group for comparison.
+ * \param[in] natoms0 Number of atoms for first group.
+ * \param[in] natoms1 Number of atoms for second group.
+ */
+void compareAtomGroups(FILE* fp, const SimulationGroups& g0, const SimulationGroups& g1, int natoms0, int natoms1);
 
-void pr_mtop(FILE *fp, int indent, const char *title, const gmx_mtop_t *mtop,
-             gmx_bool bShowNumbers, gmx_bool bShowParameters);
-void pr_top(FILE *fp, int indent, const char *title, const t_topology *top,
-            gmx_bool bShowNumbers, gmx_bool bShowParameters);
+//! Typedef for gmx_localtop in analysis tools.
+using ExpandedTopologyPtr = std::unique_ptr<gmx_localtop_t>;
 
-void cmp_top(FILE *fp, const t_topology *t1, const t_topology *t2, real ftol, real abstol);
-void cmp_groups(FILE *fp, const gmx_groups_t *g0, const gmx_groups_t *g1,
-                int natoms0, int natoms1);
+void copy_moltype(const gmx_moltype_t* src, gmx_moltype_t* dst);
 
 #endif