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"
43 #include "gromacs/analysisdata/dataframe.h"
44 #include "gromacs/fatalerror/exceptions.h"
45 #include "gromacs/fatalerror/gmxassert.h"
47 #include "abstractdata-impl.h"
48 #include "analysisdata-impl.h"
53 /********************************************************************
55 ********************************************************************/
58 frame_index_gtr(AnalysisDataFrame *a, AnalysisDataFrame *b)
60 return a->_index > b->_index;
64 AnalysisData::Impl::Impl(AnalysisData *data)
65 : _data(*data), _pstart(0)
70 AnalysisData::Impl::~Impl()
72 HandleList::const_iterator i;
73 for (i = _handles.begin(); i != _handles.end(); ++i)
78 FrameList::const_iterator j;
79 for (j = _pending.begin(); j != _pending.end(); ++j)
87 AnalysisData::Impl::addPendingFrame(AnalysisDataFrame *fr)
89 GMX_ASSERT(fr->_index >= _data.frameCount(),
90 "addPendingFrame() called for too old frame");
91 size_t pindex = fr->_index - _data.frameCount();
94 // Just store our frame if it is the next one.
95 _data.storeNextFrame(fr->_x, fr->_dx, fr->_y, fr->_dy, fr->_present);
100 if (pindex >= _pending.size())
102 // TODO: We need to wait until earlier frames are ready...
104 // TODO: This is not thread-safe.
106 if (pindex > _pending.size())
108 pindex -= _pending.size();
111 int ncol = _data.columnCount();
112 _pending[pindex]->_x = fr->_x;
113 _pending[pindex]->_dx = fr->_dx;
114 for (int i = 0; i < ncol; ++i)
116 _pending[pindex]->_y[i] = fr->_y[i];
117 _pending[pindex]->_dy[i] = fr->_dy[i];
118 _pending[pindex]->_present[i] = fr->_present[i];
120 _pending[pindex]->_index = fr->_index;
122 processPendingFrames();
127 AnalysisData::Impl::processPendingFrames()
129 while (_pending[_pstart]->_index != -1)
131 AnalysisDataFrame *fr = _pending[_pstart];
133 _data.storeNextFrame(fr->_x, fr->_dx, fr->_y, fr->_dy, fr->_present);
141 AnalysisData::Impl::incrementPStart()
143 size_t val = _pstart;
146 if (val >= _pending.size())
148 val -= _pending.size();
154 /********************************************************************
158 AnalysisData::AnalysisData()
159 : _impl(new Impl(this))
164 AnalysisData::~AnalysisData()
171 AnalysisData::setColumns(int ncol, bool multipoint)
173 GMX_RELEASE_ASSERT(ncol > 0, "Number of columns must be positive");
174 GMX_RELEASE_ASSERT(_impl->_handles.empty(),
175 "Cannot change data dimensionality after creating handles");
176 setColumnCount(ncol);
177 setMultipoint(multipoint);
182 AnalysisData::startData(AnalysisDataParallelOptions opt)
184 if (_impl->_handles.empty())
188 else if (isMultipoint())
190 GMX_THROW(NotImplementedError("Parallelism not supported for multipoint data"));
193 std::auto_ptr<AnalysisDataHandle> handle(new AnalysisDataHandle(this));
194 _impl->_handles.push_back(handle.get());
196 size_t oldSize = _impl->_pending.size();
197 _impl->_pending.resize(2 * _impl->_handles.size() - 1);
198 Impl::FrameList::iterator i;
199 for (i = _impl->_pending.begin() + oldSize; i != _impl->_pending.end(); ++i)
201 *i = new AnalysisDataFrame(columnCount());
205 return handle.release();
210 AnalysisData::finishData(AnalysisDataHandle *handle)
212 Impl::HandleList::iterator i;
214 i = std::find(_impl->_handles.begin(), _impl->_handles.end(), handle);
215 GMX_RELEASE_ASSERT(i != _impl->_handles.end(),
216 "finishData() called for an unknown handle");
218 _impl->_handles.erase(i);
221 if (_impl->_handles.empty())
228 /********************************************************************
229 * AnalysisDataHandle::Impl
232 AnalysisDataHandle::Impl::Impl(AnalysisData *data)
235 if (!_data.isMultipoint())
237 _frame.reset(new AnalysisDataFrame(_data.columnCount()));
242 AnalysisDataHandle::Impl::~Impl()
247 /********************************************************************
251 AnalysisDataHandle::AnalysisDataHandle(AnalysisData *data)
252 : _impl(new Impl(data))
257 AnalysisDataHandle::~AnalysisDataHandle()
264 AnalysisDataHandle::startFrame(int index, real x, real dx)
266 if (_impl->_data.isMultipoint())
268 _impl->_data.notifyFrameStart(AnalysisDataFrameHeader(index, x, dx));
272 _impl->_frame->_index = index;
273 _impl->_frame->_x = x;
274 _impl->_frame->_dx = dx;
275 for (int i = 0; i < _impl->_data.columnCount(); ++i)
277 _impl->_frame->_y[i] = 0.0;
278 _impl->_frame->_dy[i] = 0.0;
279 _impl->_frame->_present[i] = false;
286 AnalysisDataHandle::addPoint(int col, real y, real dy, bool present)
288 if (_impl->_data.isMultipoint())
290 _impl->_data.notifyPointsAdd(col, 1, &y, &dy, &present);
294 GMX_ASSERT(!_impl->_frame->_present[col],
295 "Data for a column set multiple times");
296 _impl->_frame->_y[col] = y;
297 _impl->_frame->_dy[col] = dy;
298 _impl->_frame->_present[col] = present;
304 AnalysisDataHandle::addPoints(int firstcol, int n,
305 const real *y, const real *dy,
308 if (_impl->_data.isMultipoint())
310 _impl->_data.notifyPointsAdd(firstcol, n, y, dy, present);
314 for (int i = 0; i < n; ++i)
316 addPoint(firstcol + i, y[i], dy ? dy[i] : 0.0,
317 present ? present[i] : true);
324 AnalysisDataHandle::finishFrame()
326 if (_impl->_data.isMultipoint())
328 _impl->_data.notifyFrameFinish();
332 _impl->_data._impl->addPendingFrame(_impl->_frame.get());
338 AnalysisDataHandle::addFrame(int index, real x, const real *y, const real *dy,
341 addFrame(index, x, 0.0, y, dy, present);
346 AnalysisDataHandle::addFrame(int index, real x, real dx,
347 const real *y, const real *dy,
350 startFrame(index, x, dx);
351 addPoints(0, _impl->_data.columnCount(), y, dy, present);
357 AnalysisDataHandle::finishData()
360 _impl->_data.finishData(this);