From: Artem Zhmurov Date: Mon, 19 Apr 2021 13:53:58 +0000 (+0300) Subject: Make .rtp/.tdb bond types into enum class X-Git-Url: http://biod.pnpi.spb.ru/gitweb/?a=commitdiff_plain;h=b75d0b5a6a858e689f88a69837aaaa18e6067fe5;p=alexxy%2Fgromacs.git Make .rtp/.tdb bond types into enum class --- diff --git a/src/gromacs/gmxpreprocess/gen_ad.cpp b/src/gromacs/gmxpreprocess/gen_ad.cpp index 36d11e2296..643963f73d 100644 --- a/src/gromacs/gmxpreprocess/gen_ad.cpp +++ b/src/gromacs/gmxpreprocess/gen_ad.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * Copyright (c) 2018,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. @@ -349,7 +349,7 @@ static std::vector get_impropers(t_atoms* { for (int i = 0; (i < atoms->nres); i++) { - BondedInteractionList* impropers = &globalPatches[i].rb[ebtsIDIHS]; + BondedInteractionList* impropers = &globalPatches[i].rb[BondedTypes::ImproperDihedrals]; for (const auto& bondeds : impropers->b) { bool bStop = false; @@ -453,7 +453,7 @@ static void gen_excls(t_atoms* atoms, int r = atoms->atom[a].resind; if (a == atoms->nr - 1 || atoms->atom[a + 1].resind != r) { - BondedInteractionList* hbexcl = &globalPatches[r].rb[ebtsEXCLS]; + BondedInteractionList* hbexcl = &globalPatches[r].rb[BondedTypes::Exclusions]; for (const auto& bondeds : hbexcl->b) { @@ -607,9 +607,9 @@ void gen_pad(t_atoms* atoms, /* mark all entries as not matched yet */ for (int i = 0; i < atoms->nres; i++) { - for (int j = 0; j < ebtsNR; j++) + for (auto bondedsList : globalPatches[i].rb) { - for (auto& bondeds : globalPatches[i].rb[j].b) + for (auto& bondeds : bondedsList.b) { bondeds.match = false; } @@ -651,7 +651,7 @@ void gen_pad(t_atoms* atoms, { res += maxres - minres; get_atomnames_min(3, anm, res, atoms, atomNumbers); - BondedInteractionList* hbang = &globalPatches[res].rb[ebtsANGLES]; + BondedInteractionList* hbang = &globalPatches[res].rb[BondedTypes::Angles]; for (auto& bondeds : hbang->b) { if (anm[1] == bondeds.aj()) @@ -702,7 +702,8 @@ void gen_pad(t_atoms* atoms, { res += maxres - minres; get_atomnames_min(4, anm, res, atoms, atomNumbers); - BondedInteractionList* hbdih = &globalPatches[res].rb[ebtsPDIHS]; + BondedInteractionList* hbdih = + &globalPatches[res].rb[BondedTypes::ProperDihedrals]; for (auto& bondeds : hbdih->b) { bool bFound = false; @@ -775,7 +776,7 @@ void gen_pad(t_atoms* atoms, for (int i = 0; i < atoms->nres; i++) { /* Add remaining angles from hackblock */ - BondedInteractionList* hbang = &globalPatches[i].rb[ebtsANGLES]; + BondedInteractionList* hbang = &globalPatches[i].rb[BondedTypes::Angles]; for (auto& bondeds : hbang->b) { if (bondeds.match) @@ -826,7 +827,7 @@ void gen_pad(t_atoms* atoms, } /* Add remaining dihedrals from hackblock */ - BondedInteractionList* hbdih = &globalPatches[i].rb[ebtsPDIHS]; + BondedInteractionList* hbdih = &globalPatches[i].rb[BondedTypes::ProperDihedrals]; for (auto& bondeds : hbdih->b) { if (bondeds.match) diff --git a/src/gromacs/gmxpreprocess/hackblock.cpp b/src/gromacs/gmxpreprocess/hackblock.cpp index 2459141ae6..5cbc9e3d9b 100644 --- a/src/gromacs/gmxpreprocess/hackblock.cpp +++ b/src/gromacs/gmxpreprocess/hackblock.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2011,2014,2015,2017,2018 by the GROMACS development team. - * Copyright (c) 2019,2020, by the GROMACS development team, led by + * 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. @@ -55,9 +55,20 @@ #include "gromacs/utility/smalloc.h" #include "gromacs/utility/stringcompare.h" -/* these MUST correspond to the enum in hackblock.h */ -const char* btsNames[ebtsNR] = { "bonds", "angles", "dihedrals", "impropers", "exclusions", "cmap" }; -const int btsNiatoms[ebtsNR] = { 2, 3, 4, 4, 2, 5 }; +const char* enumValueToString(BondedTypes enumValue) +{ + /* these MUST correspond to the enum in hackblock.h */ + constexpr gmx::EnumerationArray bondedTypeNames = { + "bonds", "angles", "dihedrals", "impropers", "exclusions", "cmap" + }; + return bondedTypeNames[enumValue]; +} + +int enumValueToNumIAtoms(BondedTypes enumValue) +{ + constexpr gmx::EnumerationArray bondedTypeIAtoms = { 2, 3, 4, 4, 2, 5 }; + return bondedTypeIAtoms[enumValue]; +} MoleculePatchType MoleculePatch::type() const { @@ -83,9 +94,9 @@ void clearModificationBlock(MoleculePatchDatabase* globalPatches) { globalPatches->name.clear(); globalPatches->hack.clear(); - for (int i = 0; i < ebtsNR; i++) + for (auto bondedsList : globalPatches->rb) { - globalPatches->rb[i].b.clear(); + bondedsList.b.clear(); } } @@ -152,9 +163,10 @@ bool mergeBondedInteractionList(gmx::ArrayRef s, bool bPlus) { bool bBondsRemoved = false; - for (int i = 0; i < ebtsNR; i++) + for (auto i : gmx::EnumerationWrapper{}) { - if (!s[i].b.empty()) + int value = static_cast(i); + if (!s[value].b.empty()) { /* Record how many bonds we have in the destination when we start. * @@ -171,15 +183,15 @@ bool mergeBondedInteractionList(gmx::ArrayRef s, * it is a hackblock entry meant to override the main rtp, and then * we don't add the main rtp one. */ - int nbHackblockStart = d[i].b.size(); + int nbHackblockStart = d[value].b.size(); - for (const auto& b : s[i].b) + for (const auto& b : s[value].b) { /* Check if this bonded string already exists before adding. * We are merging from the main RTP to the hackblocks, so this * will mean the hackblocks overwrite the man RTP, as intended. */ - int index = rbonded_find_atoms_in_list(b, d[i].b, btsNiatoms[i]); + int index = rbonded_find_atoms_in_list(b, d[value].b, enumValueToNumIAtoms(i)); /* - If we did not find this interaction at all, the index will be -1, * and then we should definitely add it to the merged hackblock and rtp. * @@ -200,9 +212,9 @@ bool mergeBondedInteractionList(gmx::ArrayRef s, { if (!(bMin && contains_char(b, '-')) && !(bPlus && contains_char(b, '+'))) { - d[i].b.push_back(b); + d[value].b.push_back(b); } - else if (i == ebtsBONDS) + else if (i == BondedTypes::Bonds) { bBondsRemoved = true; } @@ -237,7 +249,7 @@ void copyPreprocessResidues(const PreprocessResidue& s, PreprocessResidue* d, t_ { d->cgnr.push_back(c); } - for (int i = 0; i < ebtsNR; i++) + for (auto i : gmx::EnumerationWrapper{}) { d->rb[i].type = s.rb[i].type; d->rb[i].b.clear(); @@ -264,9 +276,9 @@ void copyModificationBlocks(const MoleculePatchDatabase& s, MoleculePatchDatabas *d = s; d->name = s.name; d->hack.clear(); - for (int i = 0; i < ebtsNR; i++) + for (auto bondedList : d->rb) { - d->rb[i].b.clear(); + bondedList.b.clear(); } mergeAtomAndBondModifications(s, d); } diff --git a/src/gromacs/gmxpreprocess/hackblock.h b/src/gromacs/gmxpreprocess/hackblock.h index 33613291bb..8e5e9c2722 100644 --- a/src/gromacs/gmxpreprocess/hackblock.h +++ b/src/gromacs/gmxpreprocess/hackblock.h @@ -3,7 +3,7 @@ * * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. - * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by + * Copyright (c) 2013,2014,2015,2018,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. @@ -49,6 +49,7 @@ #include "gromacs/gmxpreprocess/notset.h" #include "gromacs/topology/ifunc.h" +#include "gromacs/utility/enumerationhelpers.h" struct t_atom; struct t_symtab; @@ -61,23 +62,23 @@ class ArrayRef; /*! \brief * Used for reading .rtp/.tdb - * ebtsBONDS must be the first, new types can be added to the end + * BondedTypes::Bonds must be the first, new types can be added to the end * these *MUST* correspond to the arrays in hackblock.cpp */ -enum +enum class BondedTypes : int { - ebtsBONDS, - ebtsANGLES, - ebtsPDIHS, - ebtsIDIHS, - ebtsEXCLS, - ebtsCMAP, - ebtsNR + Bonds, + Angles, + ProperDihedrals, + ImproperDihedrals, + Exclusions, + Cmap, + Count }; //! Names for interaction type entries -extern const char* btsNames[ebtsNR]; +const char* enumValueToString(BondedTypes enumValue); //! Numbers for atoms in the interactions. -extern const int btsNiatoms[ebtsNR]; +int enumValueToNumIAtoms(BondedTypes enumValue); /* if changing any of these structs, make sure that all of the free/clear/copy/merge_t_* functions stay updated */ @@ -145,7 +146,7 @@ struct PreprocessResidue //! Delete dihedrals also defined by impropers. bool bRemoveDihedralIfWithImproper = false; //! List of bonded interactions to potentially add. - std::array rb; + gmx::EnumerationArray rb; //! Get number of atoms in residue. int natom() const { return atom.size(); } }; @@ -223,7 +224,7 @@ struct MoleculePatchDatabase //! List of changes to atoms. std::vector hack; //! List of bonded interactions to potentially add. - std::array rb; + gmx::EnumerationArray rb; //! Number of atoms to modify int nhack() const { return hack.size(); } }; diff --git a/src/gromacs/gmxpreprocess/pdb2gmx.cpp b/src/gromacs/gmxpreprocess/pdb2gmx.cpp index 87bbaa5e2c..5346f3804e 100644 --- a/src/gromacs/gmxpreprocess/pdb2gmx.cpp +++ b/src/gromacs/gmxpreprocess/pdb2gmx.cpp @@ -1365,7 +1365,7 @@ bool checkChainCyclicity(t_atoms* pdba, auto res = getDatabaseEntry(newName, rtpFFDB); const char *name_ai, *name_aj; - for (const auto& patch : res->rb[ebtsBONDS].b) + for (const auto& patch : res->rb[BondedTypes::Bonds].b) { /* Search backward bond for n/5' terminus */ name_ai = patch.ai().c_str(); name_aj = patch.aj().c_str(); @@ -1394,7 +1394,7 @@ bool checkChainCyclicity(t_atoms* pdba, newName = rtpname; } res = getDatabaseEntry(newName, rtpFFDB); - for (const auto& patch : res->rb[ebtsBONDS].b) + for (const auto& patch : res->rb[BondedTypes::Bonds].b) { /* Seach forward bond for c/3' terminus */ name_ai = patch.ai().c_str(); diff --git a/src/gromacs/gmxpreprocess/pdb2top.cpp b/src/gromacs/gmxpreprocess/pdb2top.cpp index a7526c5210..e31a25c967 100644 --- a/src/gromacs/gmxpreprocess/pdb2top.cpp +++ b/src/gromacs/gmxpreprocess/pdb2top.cpp @@ -697,7 +697,7 @@ void write_top(FILE* out, const char* molname, t_atoms* at, bool bRTPresname, - int bts[], + gmx::ArrayRef bts, gmx::ArrayRef plist, t_excls excls[], PreprocessingAtomTypes* atype, @@ -712,15 +712,27 @@ void write_top(FILE* out, fprintf(out, "%-15s %5d\n\n", molname ? molname : "Protein", nrexcl); print_atoms(out, atype, at, cgnr, bRTPresname); - print_bondeds(out, at->nr, Directive::d_bonds, F_BONDS, bts[ebtsBONDS], plist); + print_bondeds( + out, at->nr, Directive::d_bonds, F_BONDS, bts[static_cast(BondedTypes::Bonds)], plist); print_bondeds(out, at->nr, Directive::d_constraints, F_CONSTR, 0, plist); print_bondeds(out, at->nr, Directive::d_constraints, F_CONSTRNC, 0, plist); print_bondeds(out, at->nr, Directive::d_pairs, F_LJ14, 0, plist); print_excl(out, at->nr, excls); - print_bondeds(out, at->nr, Directive::d_angles, F_ANGLES, bts[ebtsANGLES], plist); - print_bondeds(out, at->nr, Directive::d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist); - print_bondeds(out, at->nr, Directive::d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist); - print_bondeds(out, at->nr, Directive::d_cmap, F_CMAP, bts[ebtsCMAP], plist); + print_bondeds( + out, at->nr, Directive::d_angles, F_ANGLES, bts[static_cast(BondedTypes::Angles)], plist); + print_bondeds(out, + at->nr, + Directive::d_dihedrals, + F_PDIHS, + bts[static_cast(BondedTypes::ProperDihedrals)], + plist); + print_bondeds(out, + at->nr, + Directive::d_dihedrals, + F_IDIHS, + bts[static_cast(BondedTypes::ImproperDihedrals)], + plist); + print_bondeds(out, at->nr, Directive::d_cmap, F_CMAP, bts[static_cast(BondedTypes::Cmap)], plist); print_bondeds(out, at->nr, Directive::d_polarization, F_POLARIZATION, 0, plist); print_bondeds(out, at->nr, Directive::d_thole_polarization, F_THOLE_POL, 0, plist); print_bondeds(out, at->nr, Directive::d_vsites2, F_VSITE2, 0, plist); @@ -790,7 +802,7 @@ static void at2bonds(InteractionsOfType* psb, for (int resind = 0; (resind < atoms->nres) && (i < atoms->nr); resind++) { /* add bonds from list of bonded interactions */ - for (const auto& patch : globalPatches[resind].rb[ebtsBONDS].b) + for (const auto& patch : globalPatches[resind].rb[BondedTypes::Bonds].b) { /* Unfortunately we can not issue errors or warnings * for missing atoms in bonds, as the hydrogens and terminal atoms @@ -945,9 +957,9 @@ static void check_restp_types(const PreprocessResidue& r0, const PreprocessResid static_cast(r0.bRemoveDihedralIfWithImproper), static_cast(r1.bRemoveDihedralIfWithImproper)); - for (int i = 0; i < ebtsNR; i++) + for (auto i : gmx::EnumerationWrapper{}) { - check_restp_type(btsNames[i], r0.rb[i].type, r1.rb[i].type); + check_restp_type(enumValueToString(i), r0.rb[i].type, r1.rb[i].type); } } @@ -1422,7 +1434,7 @@ static void gen_cmap(InteractionsOfType* psb, for (residx = 0; residx < nres; residx++) { /* Add CMAP terms from the list of CMAP interactions */ - for (const auto& b : usedPpResidues[residx].rb[ebtsCMAP].b) + for (const auto& b : usedPpResidues[residx].rb[BondedTypes::Cmap].b) { bool bAddCMAP = true; /* Loop over atoms in a candidate CMAP interaction and @@ -1538,12 +1550,12 @@ void pdb2top(FILE* top_file, gmx::ArrayRef cyclicBondsIndex, const gmx::MDLogger& logger) { - std::array plist; - t_excls* excls; - int* cgnr; - int* vsite_type; - int i, nmissat; - int bts[ebtsNR]; + std::array plist; + t_excls* excls; + int* cgnr; + int* vsite_type; + int i, nmissat; + gmx::EnumerationArray bts; ResidueType rt; @@ -1660,7 +1672,7 @@ void pdb2top(FILE* top_file, /* We can copy the bonded types from the first restp, * since the types have to be identical for all residues in one molecule. */ - for (i = 0; i < ebtsNR; i++) + for (auto i : gmx::EnumerationWrapper{}) { bts[i] = usedPpResidues[0].rb[i].type; } diff --git a/src/gromacs/gmxpreprocess/pdb2top.h b/src/gromacs/gmxpreprocess/pdb2top.h index 77d7f4b8cd..45677bfdb3 100644 --- a/src/gromacs/gmxpreprocess/pdb2top.h +++ b/src/gromacs/gmxpreprocess/pdb2top.h @@ -3,7 +3,7 @@ * * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. - * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by + * Copyright (c) 2013,2014,2015,2018,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. @@ -137,7 +137,7 @@ void write_top(FILE* out, const char* molname, t_atoms* at, bool bRTPresname, - int bts[], + gmx::ArrayRef bts, gmx::ArrayRef plist, t_excls excls[], PreprocessingAtomTypes* atype, diff --git a/src/gromacs/gmxpreprocess/resall.cpp b/src/gromacs/gmxpreprocess/resall.cpp index 847623e22f..84485f95d7 100644 --- a/src/gromacs/gmxpreprocess/resall.cpp +++ b/src/gromacs/gmxpreprocess/resall.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -60,6 +61,7 @@ #include "gromacs/utility/logger.h" #include "gromacs/utility/smalloc.h" #include "gromacs/utility/strdb.h" +#include "gromacs/utility/stringtoenumvalueconverter.h" #include "hackblock.h" @@ -163,7 +165,7 @@ static bool read_atoms(FILE* in, char* line, PreprocessResidue* r0, t_symtab* ta return TRUE; } -static bool read_bondeds(int bt, FILE* in, char* line, PreprocessResidue* rtpDBEntry) +static bool read_bondeds(BondedTypes bt, FILE* in, char* line, PreprocessResidue* rtpDBEntry) { char str[STRLEN]; @@ -173,7 +175,7 @@ static bool read_bondeds(int bt, FILE* in, char* line, PreprocessResidue* rtpDBE int ni; rtpDBEntry->rb[bt].b.emplace_back(); BondedInteraction* newBond = &rtpDBEntry->rb[bt].b.back(); - for (int j = 0; j < btsNiatoms[bt]; j++) + for (int j = 0; j < enumValueToNumIAtoms(bt); j++) { if (sscanf(line + n, "%s%n", str, &ni) == 1) { @@ -196,15 +198,15 @@ static bool read_bondeds(int bt, FILE* in, char* line, PreprocessResidue* rtpDBE return TRUE; } -static void print_resbondeds(FILE* out, int bt, const PreprocessResidue& rtpDBEntry) +static void print_resbondeds(FILE* out, BondedTypes bt, const PreprocessResidue& rtpDBEntry) { if (!rtpDBEntry.rb[bt].b.empty()) { - fprintf(out, " [ %s ]\n", btsNames[bt]); + fprintf(out, " [ %s ]\n", enumValueToString(bt)); for (const auto& b : rtpDBEntry.rb[bt].b) { - for (int j = 0; j < btsNiatoms[bt]; j++) + for (int j = 0; j < enumValueToNumIAtoms(bt); j++) { fprintf(out, "%6s ", b.a[j].c_str()); } @@ -234,21 +236,13 @@ static void check_rtp(gmx::ArrayRef rtpDBEntry, } } -static int get_bt(char* header) +static std::optional get_bt(char* header) { - int i; - - for (i = 0; i < ebtsNR; i++) - { - if (gmx_strcasecmp(btsNames[i], header) == 0) - { - return i; - } - } - return NOTSET; + gmx::StringToEnumValueConverter converter; + return converter.valueFrom(header); } -/* print all the ebtsNR type numbers */ +/* print all the BondedTypes type numbers */ static void print_resall_header(FILE* out, gmx::ArrayRef rtpDBEntry) { fprintf(out, "[ bondedtypes ]\n"); @@ -304,7 +298,7 @@ void print_resall(FILE* out, gmx::ArrayRef rtpDBEntry, if (r.natom() > 0) { print_resatoms(out, atype, r); - for (int bt = 0; bt < ebtsNR; bt++) + for (auto bt : gmx::EnumerationWrapper{}) { print_resbondeds(out, bt, r); } @@ -321,7 +315,7 @@ void readResidueDatabase(const std::string& rrdb, { FILE* in; char filebase[STRLEN], line[STRLEN], header[STRLEN]; - int bt, nparam; + int nparam; int dum1, dum2, dum3; bool bNextResidue, bError; @@ -333,12 +327,12 @@ void readResidueDatabase(const std::string& rrdb, /* these bonded parameters will overwritten be when * * there is a [ bondedtypes ] entry in the .rtp file */ - header_settings.rb[ebtsBONDS].type = 1; /* normal bonds */ - header_settings.rb[ebtsANGLES].type = 1; /* normal angles */ - header_settings.rb[ebtsPDIHS].type = 1; /* normal dihedrals */ - header_settings.rb[ebtsIDIHS].type = 2; /* normal impropers */ - header_settings.rb[ebtsEXCLS].type = 1; /* normal exclusions */ - header_settings.rb[ebtsCMAP].type = 1; /* normal cmap torsions */ + header_settings.rb[BondedTypes::Bonds].type = 1; /* normal bonds */ + header_settings.rb[BondedTypes::Angles].type = 1; /* normal angles */ + header_settings.rb[BondedTypes::ProperDihedrals].type = 1; /* normal dihedrals */ + header_settings.rb[BondedTypes::ImproperDihedrals].type = 2; /* normal impropers */ + header_settings.rb[BondedTypes::Exclusions].type = 1; /* normal exclusions */ + header_settings.rb[BondedTypes::Cmap].type = 1; /* normal cmap torsions */ header_settings.bKeepAllGeneratedDihedrals = FALSE; header_settings.nrexcl = 3; @@ -372,10 +366,10 @@ void readResidueDatabase(const std::string& rrdb, get_a_line(in, line, STRLEN); if ((nparam = sscanf(line, "%d %d %d %d %d %d %d %d", - &header_settings.rb[ebtsBONDS].type, - &header_settings.rb[ebtsANGLES].type, - &header_settings.rb[ebtsPDIHS].type, - &header_settings.rb[ebtsIDIHS].type, + &header_settings.rb[BondedTypes::Bonds].type, + &header_settings.rb[BondedTypes::Angles].type, + &header_settings.rb[BondedTypes::ProperDihedrals].type, + &header_settings.rb[BondedTypes::ImproperDihedrals].type, &dum1, &header_settings.nrexcl, &dum2, @@ -456,11 +450,11 @@ void readResidueDatabase(const std::string& rrdb, } else { - bt = get_bt(header); - if (bt != NOTSET) + auto bt = get_bt(header); + if (bt.has_value()) { /* header is an bonded directive */ - bError = !read_bondeds(bt, in, line, res); + bError = !read_bondeds(*bt, in, line, res); } else if (gmx::equalCaseInsensitive("atoms", header, 5)) { diff --git a/src/gromacs/gmxpreprocess/ter_db.cpp b/src/gromacs/gmxpreprocess/ter_db.cpp index c10ca620cf..f4f12e34ec 100644 --- a/src/gromacs/gmxpreprocess/ter_db.cpp +++ b/src/gromacs/gmxpreprocess/ter_db.cpp @@ -56,39 +56,37 @@ #include "gromacs/utility/cstringutil.h" #include "gromacs/utility/fatalerror.h" #include "gromacs/utility/futil.h" +#include "gromacs/utility/enumerationhelpers.h" +#include "gromacs/utility/fatalerror.h" +#include "gromacs/utility/futil.h" #include "gromacs/utility/smalloc.h" #include "gromacs/utility/strdb.h" +#include "gromacs/utility/stringtoenumvalueconverter.h" #include "hackblock.h" #include "resall.h" -/* use bonded types definitions in hackblock.h */ -#define ekwRepl (ebtsNR + 1) -#define ekwAdd (ebtsNR + 2) -#define ekwDel (ebtsNR + 3) -#define ekwNR 3 -static const char* kw_names[ekwNR] = { "replace", "add", "delete" }; - -static int find_kw(char* keyw) +enum class ReplaceType : int { - int i; + Repl, + Add, + Del, + Count +}; - for (i = 0; i < ebtsNR; i++) - { - if (gmx_strcasecmp(btsNames[i], keyw) == 0) - { - return i; - } - } - for (i = 0; i < ekwNR; i++) - { - if (gmx_strcasecmp(kw_names[i], keyw) == 0) - { - return ebtsNR + 1 + i; - } - } +static const char* enumValueToString(ReplaceType enumValue) +{ + constexpr gmx::EnumerationArray replaceTypeNames = { "replace", + "add", + "delete" }; + return replaceTypeNames[enumValue]; +} - return NOTSET; +template +static std::optional findTypeFromKeyword(char* keyw) +{ + gmx::StringToEnumValueConverter converter; + return converter.valueFrom(keyw); } #define FATAL() gmx_fatal(FARGS, "Reading Termini Database: not enough items on line\n%s", line) @@ -173,7 +171,7 @@ static void print_ter_db(const char* ff, return mod.type() == MoleculePatchType::Replace; })) { - fprintf(out, "[ %s ]\n", kw_names[ekwRepl - ebtsNR - 1]); + fprintf(out, "[ %s ]\n", enumValueToString(ReplaceType::Repl)); for (const auto& hack : modification.hack) { if (hack.type() == MoleculePatchType::Replace) @@ -187,7 +185,7 @@ static void print_ter_db(const char* ff, return mod.type() == MoleculePatchType::Add; })) { - fprintf(out, "[ %s ]\n", kw_names[ekwAdd - ebtsNR - 1]); + fprintf(out, "[ %s ]\n", enumValueToString(ReplaceType::Add)); for (const auto& hack : modification.hack) { if (hack.type() == MoleculePatchType::Add) @@ -201,7 +199,7 @@ static void print_ter_db(const char* ff, return mod.type() == MoleculePatchType::Delete; })) { - fprintf(out, "[ %s ]\n", kw_names[ekwDel - ebtsNR - 1]); + fprintf(out, "[ %s ]\n", enumValueToString(ReplaceType::Del)); for (const auto& hack : modification.hack) { if (hack.type() == MoleculePatchType::Delete) @@ -210,14 +208,14 @@ static void print_ter_db(const char* ff, } } } - for (int bt = 0; bt < ebtsNR; bt++) + for (auto bt : gmx::EnumerationWrapper{}) { if (!modification.rb[bt].b.empty()) { - fprintf(out, "[ %s ]\n", btsNames[bt]); + fprintf(out, "[ %s ]\n", enumValueToString(bt)); for (const auto& b : modification.rb[bt].b) { - for (int k = 0; k < btsNiatoms[bt]; k++) + for (int k = 0; k < enumValueToNumIAtoms(bt); k++) { fprintf(out, "%s%s", k ? "\t" : "", b.a[k].c_str()); } @@ -251,7 +249,8 @@ static void read_ter_db_file(const char* fn, FILE* in = fflib_open(fn); - int kwnr = NOTSET; + std::optional btkw; + std::optional rtkw; get_a_line(in, line, STRLEN); MoleculePatchDatabase* block = nullptr; while (!feof(in)) @@ -259,9 +258,10 @@ static void read_ter_db_file(const char* fn, if (get_header(line, header)) { /* this is a new block, or a new keyword */ - kwnr = find_kw(header); + btkw = findTypeFromKeyword(header); + rtkw = findTypeFromKeyword(header); - if (kwnr == NOTSET) + if (!btkw.has_value() && !rtkw.has_value()) { tbptr->emplace_back(MoleculePatchDatabase()); block = &tbptr->back(); @@ -281,7 +281,7 @@ static void read_ter_db_file(const char* fn, line); } /* this is not a header, so it must be data */ - if (kwnr >= ebtsNR) + if (!btkw.has_value()) { /* this is a hack: add/rename/delete atoms */ /* make space for hacks */ @@ -290,7 +290,7 @@ static void read_ter_db_file(const char* fn, /* get data */ int n = 0; - if (kwnr == ekwRepl || kwnr == ekwDel) + if (*rtkw == ReplaceType::Repl || *rtkw == ReplaceType::Del) { if (sscanf(line, "%s%n", buf, &n) != 1) { @@ -304,19 +304,23 @@ static void read_ter_db_file(const char* fn, /* we only replace or delete one atom at a time */ hack->nr = 1; } - else if (kwnr == ekwAdd) + else if (*rtkw == ReplaceType::Add) { read_ab(line, fn, hack); get_a_line(in, line, STRLEN); } else { - gmx_fatal(FARGS, "unimplemented keyword number %d (%s:%d)", kwnr, __FILE__, __LINE__); + gmx_fatal(FARGS, + "unimplemented keyword number %d (%s:%d)", + static_cast(*rtkw), + __FILE__, + __LINE__); } - if (kwnr == ekwRepl || kwnr == ekwAdd) + if (*rtkw == ReplaceType::Repl || *rtkw == ReplaceType::Add) { hack->atom.emplace_back(); - read_atom(line + n, kwnr == ekwAdd, &hack->nname, &hack->atom.back(), atype, &hack->cgnr); + read_atom(line + n, *rtkw == ReplaceType::Add, &hack->nname, &hack->atom.back(), atype, &hack->cgnr); if (hack->nname.empty()) { if (!hack->oname.empty()) @@ -334,13 +338,13 @@ static void read_ter_db_file(const char* fn, } } } - else if (kwnr >= 0 && kwnr < ebtsNR) + else if (*btkw >= BondedTypes::Bonds && *btkw < BondedTypes::Count) { /* this is bonded data: bonds, angles, dihedrals or impropers */ int n = 0; - block->rb[kwnr].b.emplace_back(); - BondedInteraction* newBond = &block->rb[kwnr].b.back(); - for (int j = 0; j < btsNiatoms[kwnr]; j++) + block->rb[*btkw].b.emplace_back(); + BondedInteraction* newBond = &block->rb[*btkw].b.back(); + for (int j = 0; j < enumValueToNumIAtoms(*btkw); j++) { int ni; if (sscanf(line + n, "%s%n", buf, &ni) == 1) @@ -353,7 +357,7 @@ static void read_ter_db_file(const char* fn, "Reading Termini Database '%s': expected %d atom names (found " "%d) on line\n%s", fn, - btsNiatoms[kwnr], + enumValueToNumIAtoms(*btkw), j - 1, line); }