static int multi_body_bondeds_count(const gmx_mtop_t& mtop)
{
- int n = 0;
- gmx_mtop_ilistloop_t iloop = gmx_mtop_ilistloop_init(mtop);
- int nmol = 0;
- while (const InteractionLists* ilists = gmx_mtop_ilistloop_next(iloop, &nmol))
+ int n = 0;
+ for (const auto ilists : IListRange(mtop))
{
- for (auto& ilist : extractILists(*ilists, IF_BOND))
+ for (auto& ilist : extractILists(ilists.list(), IF_BOND))
{
if (NRAL(ilist.functionType) > 2)
{
- n += nmol * (ilist.iatoms.size() / ilistStride(ilist));
+ n += ilists.nmol() * (ilist.iatoms.size() / ilistStride(ilist));
}
}
}
/* Returns whether mtop contains constraints and/or vsites */
static bool systemHasConstraintsOrVsites(const gmx_mtop_t& mtop)
{
- auto* ilistLoop = gmx_mtop_ilistloop_init(mtop);
- int nmol = 0;
- while (const InteractionLists* ilists = gmx_mtop_ilistloop_next(ilistLoop, &nmol))
+ for (const auto ilists : IListRange(mtop))
{
- if (!extractILists(*ilists, IF_CONSTRAINT | IF_VSITE).empty())
+ if (!extractILists(ilists.list(), IF_CONSTRAINT | IF_VSITE).empty())
{
return true;
}
}
-
return false;
}
static void set_disres_npair(gmx_mtop_t* mtop)
{
- gmx_mtop_ilistloop_t iloop;
- int nmol;
-
gmx::ArrayRef<t_iparams> ip = mtop->ffparams.iparams;
- iloop = gmx_mtop_ilistloop_init(*mtop);
- while (const InteractionLists* ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
+ for (const auto ilist : IListRange(*mtop))
{
- const InteractionList& il = (*ilist)[F_DISRES];
+ const InteractionList& il = ilist.list()[F_DISRES];
if (!il.empty())
{
static bool absolute_reference(const t_inputrec* ir, const gmx_mtop_t& sys, const bool posres_only, ivec AbsRef)
{
- int d, g, i;
- gmx_mtop_ilistloop_t iloop;
- int nmol;
- const t_iparams* pr;
+ int d, g, i;
+ const t_iparams* pr;
clear_ivec(AbsRef);
}
/* Check for position restraints */
- iloop = gmx_mtop_ilistloop_init(sys);
- while (const InteractionLists* ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
+ for (const auto ilist : IListRange(sys))
{
- if (nmol > 0 && (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
+ if (ilist.nmol() > 0 && (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
{
- for (i = 0; i < (*ilist)[F_POSRES].size(); i += 2)
+ for (int i = 0; i < ilist.list()[F_POSRES].size(); i += 2)
{
- pr = &sys.ffparams.iparams[(*ilist)[F_POSRES].iatoms[i]];
+ pr = &sys.ffparams.iparams[ilist.list()[F_POSRES].iatoms[i]];
for (d = 0; d < DIM; d++)
{
if (pr->posres.fcA[d] != 0)
}
}
}
- for (i = 0; i < (*ilist)[F_FBPOSRES].size(); i += 2)
+ for (i = 0; i < ilist.list()[F_FBPOSRES].size(); i += 2)
{
/* Check for flat-bottom posres */
- pr = &sys.ffparams.iparams[(*ilist)[F_FBPOSRES].iatoms[i]];
+ pr = &sys.ffparams.iparams[ilist.list()[F_FBPOSRES].iatoms[i]];
if (pr->fbposres.k != 0)
{
switch (pr->fbposres.geom)
t_state* state,
gmx_bool bIsREMD)
{
- int fa, nmol, npair, np;
- history_t* hist;
- gmx_mtop_ilistloop_t iloop;
- char* ptr;
- int type_min, type_max;
+ history_t* hist;
+ char* ptr;
+ int type_min, type_max;
if (gmx_mtop_ftype_count(mtop, F_DISRES) == 0)
{
dd->npair = 0;
type_min = INT_MAX;
type_max = 0;
- iloop = gmx_mtop_ilistloop_init(mtop);
- while (const InteractionLists* il = gmx_mtop_ilistloop_next(iloop, &nmol))
+ for (const auto il : IListRange(mtop))
{
- if (nmol > 1 && !(*il)[F_DISRES].empty() && ir->eDisre != DistanceRestraintRefinement::Ensemble)
+ if (il.nmol() > 1 && !il.list()[F_DISRES].empty()
+ && ir->eDisre != DistanceRestraintRefinement::Ensemble)
{
gmx_fatal(FARGS,
"NMR distance restraints with multiple copies of the same molecule are "
"a restraint potential (bonds type 10) instead.");
}
- np = 0;
- for (fa = 0; fa < (*il)[F_DISRES].size(); fa += 3)
+ int np = 0;
+ for (int fa = 0; fa < il.list()[F_DISRES].size(); fa += 3)
{
- int type;
-
- type = (*il)[F_DISRES].iatoms[fa];
+ int type = il.list()[F_DISRES].iatoms[fa];
np++;
- npair = mtop.ffparams.iparams[type].disres.npair;
+ int npair = mtop.ffparams.iparams[type].disres.npair;
if (np == npair)
{
- dd->nres += (ir->eDisre == DistanceRestraintRefinement::Ensemble ? 1 : nmol);
- dd->npair += nmol * npair;
+ dd->nres += (ir->eDisre == DistanceRestraintRefinement::Ensemble ? 1 : il.nmol());
+ dd->npair += il.nmol() * npair;
np = 0;
type_min = std::min(type_min, type);
od->eig = nullptr;
od->v = nullptr;
- int* nr_ex = nullptr;
- int typeMin = INT_MAX;
- int typeMax = 0;
- gmx_mtop_ilistloop_t iloop = gmx_mtop_ilistloop_init(mtop);
- int nmol;
- while (const InteractionLists* il = gmx_mtop_ilistloop_next(iloop, &nmol))
- {
- const int numOrires = (*il)[F_ORIRES].size();
- if (nmol > 1 && numOrires > 0)
+ int* nr_ex = nullptr;
+ int typeMin = INT_MAX;
+ int typeMax = 0;
+ for (const auto il : IListRange(mtop))
+ {
+ const int numOrires = il.list()[F_ORIRES].size();
+ if (il.nmol() > 1 && numOrires > 0)
{
gmx_fatal(FARGS,
"Found %d copies of a molecule with orientation restrains while the current "
"code only supports a single copy. If you want to ensemble average, run "
"multiple copies of the system using the multi-sim feature of mdrun.",
- nmol);
+ il.nmol());
}
for (int i = 0; i < numOrires; i += 3)
{
- int type = (*il)[F_ORIRES].iatoms[i];
+ int type = il.list()[F_ORIRES].iatoms[i];
int ex = mtop.ffparams.iparams[type].orires.ex;
if (ex >= od->nex)
{
useSimd_(getenv("GMX_DISABLE_SIMD_KERNELS") == nullptr)
{
/* Check that we have only one settle type */
- int settle_type = -1;
- gmx_mtop_ilistloop_t iloop = gmx_mtop_ilistloop_init(mtop);
- int nmol;
- const int nral1 = 1 + NRAL(F_SETTLE);
- while (const InteractionLists* ilists = gmx_mtop_ilistloop_next(iloop, &nmol))
+ int settle_type = -1;
+ const int nral1 = 1 + NRAL(F_SETTLE);
+ for (const auto ilists : IListRange(mtop))
{
- const InteractionList& ilist = (*ilists)[F_SETTLE];
+ const InteractionList& ilist = ilists.list()[F_SETTLE];
for (int i = 0; i < ilist.size(); i += nral1)
{
if (settle_type == -1)
return TRUE;
}
-typedef struct gmx_mtop_ilistloop
+IListIterator::IListIterator(const gmx_mtop_t& mtop, size_t molblock) :
+ mtop_(&mtop),
+ mblock_(molblock)
{
- const gmx_mtop_t* mtop;
- int mblock;
-} t_gmx_mtop_ilist;
+}
-gmx_mtop_ilistloop_t gmx_mtop_ilistloop_init(const gmx_mtop_t& mtop)
+IListIterator& IListIterator::operator++()
{
- struct gmx_mtop_ilistloop* iloop = nullptr;
-
- snew(iloop, 1);
-
- iloop->mtop = &mtop;
- iloop->mblock = -1;
-
- return iloop;
+ mblock_++;
+ return *this;
}
-static void gmx_mtop_ilistloop_destroy(gmx_mtop_ilistloop_t iloop)
+bool IListIterator::operator==(const IListIterator& o) const
{
- sfree(iloop);
+ return mtop_ == o.mtop_ && mblock_ == o.mblock_;
}
-const InteractionLists* gmx_mtop_ilistloop_next(gmx_mtop_ilistloop_t iloop, int* nmol)
+const InteractionLists& IListProxy::list() const
{
- if (iloop == nullptr)
+ // one past the end means we want to take the
+ // intermolecular list instead.
+ if (it_->mblock_ == it_->mtop_->molblock.size())
{
- gmx_incons("gmx_mtop_ilistloop_next called without calling gmx_mtop_ilistloop_init");
+ return *it_->mtop_->intermolecular_ilist;
}
-
- iloop->mblock++;
- if (iloop->mblock >= gmx::ssize(iloop->mtop->molblock))
+ else
{
- if (iloop->mblock == gmx::ssize(iloop->mtop->molblock) && iloop->mtop->bIntermolecularInteractions)
- {
- *nmol = 1;
- return iloop->mtop->intermolecular_ilist.get();
- }
-
- gmx_mtop_ilistloop_destroy(iloop);
- return nullptr;
+ return it_->mtop_->moltype[it_->mtop_->molblock[it_->mblock_].type].ilist;
}
+}
- *nmol = iloop->mtop->molblock[iloop->mblock].nmol;
-
- return &iloop->mtop->moltype[iloop->mtop->molblock[iloop->mblock].type].ilist;
+int IListProxy::nmol() const
+{
+ // one past the end means we want to take the
+ // intermolecular list instead.
+ if (it_->mblock_ == it_->mtop_->molblock.size())
+ {
+ return 1;
+ }
+ else
+ {
+ return it_->mtop_->molblock[it_->mblock_].nmol;
+ }
}
-typedef struct gmx_mtop_ilistloop_all
+
+IListRange::IListRange(const gmx_mtop_t& mtop) : begin_(mtop), end_(mtop, mtop.molblock.size())
{
- const gmx_mtop_t* mtop;
- size_t mblock;
- int mol;
- int a_offset;
-} t_gmx_mtop_ilist_all;
+ if (mtop.bIntermolecularInteractions)
+ {
+ end_ = IListIterator(mtop, mtop.molblock.size() + 1);
+ }
+}
int gmx_mtop_ftype_count(const gmx_mtop_t& mtop, int ftype)
{
- int nmol = 0;
- int n = 0;
+ int n = 0;
- gmx_mtop_ilistloop_t iloop = gmx_mtop_ilistloop_init(mtop);
- while (const InteractionLists* il = gmx_mtop_ilistloop_next(iloop, &nmol))
+ for (const IListProxy il : IListRange(mtop))
{
- n += nmol * (*il)[ftype].size() / (1 + NRAL(ftype));
+ n += il.nmol() * il.list()[ftype].size() / (1 + NRAL(ftype));
}
if (mtop.bIntermolecularInteractions)
{
int n = 0;
- gmx_mtop_ilistloop_t iloop = gmx_mtop_ilistloop_init(mtop);
- int nmol = 0;
- while (const InteractionLists* il = gmx_mtop_ilistloop_next(iloop, &nmol))
+ for (const IListProxy il : IListRange(mtop))
{
for (int ftype = 0; ftype < F_NRE; ftype++)
{
if ((interaction_function[ftype].flags & if_flags) == if_flags)
{
- n += nmol * (*il)[ftype].size() / (1 + NRAL(ftype));
+ n += il.nmol() * il.list()[ftype].size() / (1 + NRAL(ftype));
}
}
}
AtomIterator begin_, end_;
};
+class IListIterator;
+
+//! Proxy object returned from IListIterator
+class IListProxy
+{
+public:
+ //! Default constructor.
+ IListProxy(const IListIterator* it) : it_(it) {}
+ //! Access current global atom number.
+ const InteractionLists& list() const;
+ //! Access current molecule.
+ int nmol() const;
+
+private:
+ const IListIterator* it_;
+};
+
+/*! \brief
+ * Object that allows looping over all atoms in an mtop.
+ */
+class IListIterator :
+ public boost::stl_interfaces::proxy_iterator_interface<IListIterator, std::forward_iterator_tag, InteractionLists, IListProxy>
+{
+ using Base =
+ boost::stl_interfaces::proxy_iterator_interface<IListIterator, std::forward_iterator_tag, InteractionLists, IListProxy>;
+
+public:
+ //! Construct from topology.
+ explicit IListIterator(const gmx_mtop_t& mtop, size_t mblock = 0);
+
+ //! Prefix increment.
+ IListIterator& operator++();
+ using Base:: operator++;
+
+ //! Equality comparison.
+ bool operator==(const IListIterator& o) const;
+
+ //! Dereference operator. Returns proxy.
+ IListProxy operator*() const { return { this }; }
+
+private:
+ //! Global topology.
+ const gmx_mtop_t* mtop_;
+ //! Index of molecule block corresponding to the current location.
+ size_t mblock_;
+
+ friend class IListProxy;
+};
+
+
+/*! \brief
+ * Range over all interaction lists of topology.
+ *
+ * Includes the intermolecular interactions as the final element in the
+ * range if present.
+ */
+class IListRange
+{
+public:
+ //! Default constructor.
+ explicit IListRange(const gmx_mtop_t& mtop);
+ //! Iterator to begin of range.
+ IListIterator& begin() { return begin_; }
+ //! Iterator to end of range.
+ IListIterator& end() { return end_; }
+
+private:
+ IListIterator begin_, end_;
+};
+
/* Abstract type for atom loop over atoms in all molecule blocks */
typedef struct gmx_mtop_atomloop_block* gmx_mtop_atomloop_block_t;
gmx_bool gmx_mtop_atomloop_block_next(gmx_mtop_atomloop_block_t aloop, const t_atom** atom, int* nmol);
-/* Abstract type for ilist loop over all ilists */
-typedef struct gmx_mtop_ilistloop* gmx_mtop_ilistloop_t;
-
-/* Initialize an ilist loop over all molecule types in the system. */
-gmx_mtop_ilistloop_t gmx_mtop_ilistloop_init(const gmx_mtop_t& mtop);
-
-/* Loop to the next molecule,
- * When not at the end:
- * returns a valid pointer to the next array ilist_mol[F_NRE],
- * writes the number of molecules for this ilist in *nmol.
- * When at the end, destroys iloop and returns nullptr.
- */
-const InteractionLists* gmx_mtop_ilistloop_next(gmx_mtop_ilistloop_t iloop, int* nmol);
-
/* Returns the total number of interactions in the system of type ftype */
int gmx_mtop_ftype_count(const gmx_mtop_t& mtop, int ftype);