2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements test helper routines from toputils.h.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_selection
50 #include "gromacs/compat/make_unique.h"
51 #include "gromacs/fileio/confio.h"
52 #include "gromacs/fileio/trxio.h"
53 #include "gromacs/math/vec.h"
54 #include "gromacs/topology/atoms.h"
55 #include "gromacs/topology/mtop_util.h"
56 #include "gromacs/topology/topology.h"
57 #include "gromacs/trajectory/trajectoryframe.h"
58 #include "gromacs/utility/arrayref.h"
59 #include "gromacs/utility/cstringutil.h"
60 #include "gromacs/utility/gmxassert.h"
61 #include "gromacs/utility/smalloc.h"
63 #include "testutils/testfilemanager.h"
70 TopologyManager::TopologyManager()
71 : mtop_(), frame_(nullptr)
75 TopologyManager::~TopologyManager()
77 if (frame_ != nullptr)
86 for (char *atomtype : atomtypes_)
92 void TopologyManager::requestFrame()
94 GMX_RELEASE_ASSERT(mtop_ == nullptr,
95 "Frame must be requested before initializing topology");
96 if (frame_ == nullptr)
102 void TopologyManager::requestVelocities()
104 GMX_RELEASE_ASSERT(frame_ != nullptr,
105 "Velocities requested before requesting a frame");
107 if (frame_->natoms > 0)
109 snew(frame_->v, frame_->natoms);
113 void TopologyManager::requestForces()
115 GMX_RELEASE_ASSERT(frame_ != nullptr,
116 "Forces requested before requesting a frame");
118 if (frame_->natoms > 0)
120 snew(frame_->f, frame_->natoms);
124 void TopologyManager::loadTopology(const char *filename)
128 rvec *xtop = nullptr;
131 GMX_RELEASE_ASSERT(mtop_ == nullptr, "Topology initialized more than once");
132 mtop_ = gmx::compat::make_unique<gmx_mtop_t>();
134 gmx::test::TestFileManager::getInputFilePath(filename).c_str(),
135 &fullTopology, mtop_.get(), &ePBC, frame_ != nullptr ? &xtop : nullptr,
138 if (frame_ != nullptr)
140 GMX_ASSERT(xtop != nullptr, "Keep the static analyzer happy");
141 frame_->natoms = mtop_->natoms;
143 snew(frame_->x, frame_->natoms);
144 std::memcpy(frame_->x, xtop, sizeof(*frame_->x) * frame_->natoms);
146 copy_mat(box, frame_->box);
152 void TopologyManager::initAtoms(int count)
154 GMX_RELEASE_ASSERT(mtop_ == nullptr, "Topology initialized more than once");
155 mtop_ = gmx::compat::make_unique<gmx_mtop_t>();
156 mtop_->moltype.resize(1);
157 init_t_atoms(&mtop_->moltype[0].atoms, count, FALSE);
158 mtop_->molblock.resize(1);
159 mtop_->molblock[0].type = 0;
160 mtop_->molblock[0].nmol = 1;
161 mtop_->molblock[0].natoms_mol = count;
162 mtop_->natoms = count;
163 mtop_->maxres_renum = 0;
164 gmx_mtop_finalize(mtop_.get());
165 GMX_RELEASE_ASSERT(mtop_->maxres_renum == 0, "maxres_renum in mtop can be modified by an env.var., that is not supported in this test");
166 t_atoms &atoms = this->atoms();
167 for (int i = 0; i < count; ++i)
169 atoms.atom[i].m = (i % 3 == 0 ? 2.0 : 1.0);
171 atoms.haveMass = TRUE;
172 if (frame_ != nullptr)
174 frame_->natoms = count;
176 snew(frame_->x, count);
179 snew(frame_->v, count);
183 snew(frame_->f, count);
188 void TopologyManager::initAtomTypes(const ArrayRef<const char *const> &types)
190 GMX_RELEASE_ASSERT(mtop_ != nullptr, "Topology not initialized");
191 atomtypes_.reserve(types.size());
192 for (const char *type : types)
194 atomtypes_.push_back(gmx_strdup(type));
196 t_atoms &atoms = this->atoms();
197 snew(atoms.atomtype, atoms.nr);
199 for (int i = 0; i < atoms.nr; ++i, ++j)
201 if (j == types.size())
205 atoms.atomtype[i] = &atomtypes_[j];
207 atoms.haveType = TRUE;
210 void TopologyManager::initUniformResidues(int residueSize)
212 GMX_RELEASE_ASSERT(mtop_ != nullptr, "Topology not initialized");
213 t_atoms &atoms = this->atoms();
214 int residueIndex = -1;
215 for (int i = 0; i < atoms.nr; ++i)
217 if (i % residueSize == 0)
221 atoms.atom[i].resind = residueIndex;
223 atoms.nres = residueIndex;
226 void TopologyManager::initUniformMolecules(int moleculeSize)
228 GMX_RELEASE_ASSERT(mtop_ != nullptr, "Topology not initialized");
229 GMX_RELEASE_ASSERT(mtop_->molblock.size() == 1, "initUniformMolecules only implemented for a single molblock");
230 gmx_molblock_t &molblock = mtop_->molblock[0];
231 t_atoms &atoms = mtop_->moltype[molblock.type].atoms;
232 GMX_RELEASE_ASSERT(atoms.nr % moleculeSize == 0,
233 "The number of atoms should be a multiple of moleculeSize");
234 molblock.nmol = atoms.nr/moleculeSize;
235 atoms.nr = moleculeSize;
236 const int nres = atoms.atom[atoms.nr].resind;
237 GMX_RELEASE_ASSERT(atoms.atom[atoms.nr-1].resind != nres,
238 "The residues should break at molecule boundaries");
240 molblock.natoms_mol = moleculeSize;
241 mtop_->haveMoleculeIndices = true;
244 void TopologyManager::initFrameIndices(const ArrayRef<const int> &index)
246 GMX_RELEASE_ASSERT(frame_ != nullptr, "Frame not initialized");
247 GMX_RELEASE_ASSERT(!frame_->bIndex, "Frame atom indices can only be set once");
249 frame_->bIndex = TRUE;
250 snew(frame_->index, index.size());
251 std::copy(index.begin(), index.end(), frame_->index);
253 frame_->natoms = index.size();
256 t_atoms &TopologyManager::atoms()
258 GMX_RELEASE_ASSERT(mtop_ != nullptr, "Topology not initialized");
259 GMX_RELEASE_ASSERT(mtop_->natoms == mtop_->moltype[0].atoms.nr,
260 "Test setup assumes all atoms in a single molecule type");
261 return mtop_->moltype[0].atoms;