3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Implements classes in analysisdata.h.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_analysisdata
38 #include "gromacs/analysisdata/analysisdata.h"
40 #include "gromacs/analysisdata/dataframe.h"
41 #include "gromacs/analysisdata/datastorage.h"
42 #include "gromacs/analysisdata/paralleloptions.h"
43 #include "gromacs/utility/exceptions.h"
44 #include "gromacs/utility/gmxassert.h"
45 #include "gromacs/utility/uniqueptr.h"
50 /********************************************************************
51 * AnalysisDataHandleImpl
58 * Private implementation class for AnalysisDataHandle.
60 * \ingroup module_analysisdata
62 class AnalysisDataHandleImpl
65 //! Creates a handle associated with the given data object.
66 explicit AnalysisDataHandleImpl(AnalysisData *data)
67 : data_(*data), currentFrame_(NULL)
71 //! The data object that this handle belongs to.
73 //! Current storage frame object, or NULL if no current frame.
74 AnalysisDataStorageFrame *currentFrame_;
77 } // namespace internal
79 /********************************************************************
84 * Private implementation class for AnalysisData.
86 * \ingroup module_analysisdata
88 class AnalysisData::Impl
91 //! Smart pointer type to manage a data handle implementation.
92 typedef gmx_unique_ptr<internal::AnalysisDataHandleImpl>::type
94 //! Shorthand for a list of data handles.
95 typedef std::vector<HandlePointer> HandleList;
97 //! Storage implementation.
98 AnalysisDataStorage storage_;
100 * List of handles for this data object.
102 * Note that AnalysisDataHandle objects also contain (raw) pointers
108 /********************************************************************
112 AnalysisData::AnalysisData()
118 AnalysisData::~AnalysisData()
124 AnalysisData::setColumnCount(int ncol)
126 GMX_RELEASE_ASSERT(ncol > 0, "Number of columns must be positive");
127 GMX_RELEASE_ASSERT(impl_->handles_.empty(),
128 "Cannot change data dimensionality after creating handles");
129 AbstractAnalysisData::setColumnCount(ncol);
134 AnalysisData::setMultipoint(bool bMultipoint)
136 GMX_RELEASE_ASSERT(impl_->handles_.empty(),
137 "Cannot change data type after creating handles");
138 AbstractAnalysisData::setMultipoint(bMultipoint);
139 impl_->storage_.setMultipoint(bMultipoint);
144 AnalysisData::startData(const AnalysisDataParallelOptions &opt)
146 GMX_RELEASE_ASSERT(impl_->handles_.size() < static_cast<unsigned>(opt.parallelizationFactor()),
147 "Too many calls to startData() compared to provided options");
148 if (impl_->handles_.empty())
151 impl_->storage_.setParallelOptions(opt);
152 impl_->storage_.startDataStorage(this);
154 else if (isMultipoint())
156 GMX_THROW(NotImplementedError("Parallelism not supported for multipoint data"));
159 Impl::HandlePointer handle(new internal::AnalysisDataHandleImpl(this));
160 impl_->handles_.push_back(move(handle));
161 return AnalysisDataHandle(impl_->handles_.back().get());
166 AnalysisData::finishData(AnalysisDataHandle handle)
168 Impl::HandleList::iterator i;
170 for (i = impl_->handles_.begin(); i != impl_->handles_.end(); ++i)
172 if (i->get() == handle.impl_)
177 GMX_RELEASE_ASSERT(i != impl_->handles_.end(),
178 "finishData() called for an unknown handle");
180 impl_->handles_.erase(i);
182 if (impl_->handles_.empty())
190 AnalysisData::tryGetDataFrameInternal(int index) const
192 return impl_->storage_.tryGetDataFrame(index);
197 AnalysisData::requestStorageInternal(int nframes)
199 return impl_->storage_.requestStorage(nframes);
203 /********************************************************************
207 AnalysisDataHandle::AnalysisDataHandle()
213 AnalysisDataHandle::AnalysisDataHandle(internal::AnalysisDataHandleImpl *impl)
220 AnalysisDataHandle::startFrame(int index, real x, real dx)
222 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
223 GMX_RELEASE_ASSERT(impl_->currentFrame_ == NULL,
224 "startFrame() called twice without calling finishFrame()");
225 impl_->currentFrame_ =
226 &impl_->data_.impl_->storage_.startFrame(index, x, dx);
231 AnalysisDataHandle::setPoint(int column, real value, bool bPresent)
233 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
234 GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
235 "setPoint() called without calling startFrame()");
236 impl_->currentFrame_->setValue(column, value, bPresent);
241 AnalysisDataHandle::setPoint(int column, real value, real error, bool bPresent)
243 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
244 GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
245 "setPoint() called without calling startFrame()");
246 impl_->currentFrame_->setValue(column, value, error, bPresent);
251 AnalysisDataHandle::setPoints(int firstColumn, int count, const real *values)
253 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
254 GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
255 "setPoints() called without calling startFrame()");
256 for (int i = 0; i < count; ++i)
258 impl_->currentFrame_->setValue(firstColumn + i, values[i]);
264 AnalysisDataHandle::finishPointSet()
266 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
267 GMX_RELEASE_ASSERT(impl_->data_.isMultipoint(),
268 "finishPointSet() called for non-multipoint data");
269 GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
270 "finishPointSet() called without calling startFrame()");
271 impl_->currentFrame_->finishPointSet();
276 AnalysisDataHandle::finishFrame()
278 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
279 GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
280 "finishFrame() called without calling startFrame()");
281 int index = impl_->currentFrame_->frameIndex();
282 impl_->currentFrame_ = NULL;
283 impl_->data_.impl_->storage_.finishFrame(index);
288 AnalysisDataHandle::finishData()
290 GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
291 // Deletes the implementation pointer.
292 impl_->data_.finishData(*this);