Add a few C++ helper classes/macros.
[alexxy/gromacs.git] / src / gromacs / analysisdata / analysisdata.cpp
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief
33  * Implements classes in analysisdata.h.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \ingroup module_analysisdata
37  */
38 #include "gromacs/analysisdata/analysisdata.h"
39
40 #include <algorithm>
41 #include <memory>
42
43 #include "gromacs/analysisdata/dataframe.h"
44 #include "gromacs/analysisdata/datastorage.h"
45 #include "gromacs/analysisdata/paralleloptions.h"
46 #include "gromacs/fatalerror/exceptions.h"
47 #include "gromacs/fatalerror/gmxassert.h"
48
49 #include "analysisdata-impl.h"
50
51 namespace gmx
52 {
53
54 /********************************************************************
55  * AnalysisData::Impl
56  */
57
58 AnalysisData::Impl::Impl()
59 {
60 }
61
62
63 AnalysisData::Impl::~Impl()
64 {
65     HandleList::const_iterator i;
66     for (i = handles_.begin(); i != handles_.end(); ++i)
67     {
68         delete *i;
69     }
70 }
71
72
73 /********************************************************************
74  * AnalysisData
75  */
76
77 AnalysisData::AnalysisData()
78     : impl_(new Impl)
79 {
80 }
81
82
83 AnalysisData::~AnalysisData()
84 {
85 }
86
87
88 void
89 AnalysisData::setColumns(int ncol, bool multipoint)
90 {
91     GMX_RELEASE_ASSERT(ncol > 0, "Number of columns must be positive");
92     GMX_RELEASE_ASSERT(impl_->handles_.empty(),
93                        "Cannot change data dimensionality after creating handles");
94     setColumnCount(ncol);
95     setMultipoint(multipoint);
96     impl_->storage_.setMultipoint(multipoint);
97 }
98
99
100 AnalysisDataHandle *
101 AnalysisData::startData(const AnalysisDataParallelOptions &opt)
102 {
103     GMX_RELEASE_ASSERT(impl_->handles_.size() < static_cast<unsigned>(opt.parallelizationFactor()),
104                        "Too many calls to startData() compared to provided options");
105     if (impl_->handles_.empty())
106     {
107         notifyDataStart();
108         impl_->storage_.setParallelOptions(opt);
109         impl_->storage_.startDataStorage(this);
110     }
111     else if (isMultipoint())
112     {
113         GMX_THROW(NotImplementedError("Parallelism not supported for multipoint data"));
114     }
115
116     std::auto_ptr<AnalysisDataHandle> handle(new AnalysisDataHandle(this));
117     impl_->handles_.push_back(handle.get());
118     return handle.release();
119 }
120
121
122 void
123 AnalysisData::finishData(AnalysisDataHandle *handle)
124 {
125     Impl::HandleList::iterator i;
126
127     i = std::find(impl_->handles_.begin(), impl_->handles_.end(), handle);
128     GMX_RELEASE_ASSERT(i != impl_->handles_.end(),
129                        "finishData() called for an unknown handle");
130
131     impl_->handles_.erase(i);
132     delete handle;
133
134     if (impl_->handles_.empty())
135     {
136         notifyDataFinish();
137     }
138 }
139
140
141 AnalysisDataFrameRef
142 AnalysisData::tryGetDataFrameInternal(int index) const
143 {
144     return impl_->storage_.tryGetDataFrame(index);
145 }
146
147
148 bool
149 AnalysisData::requestStorageInternal(int nframes)
150 {
151     return impl_->storage_.requestStorage(nframes);
152 }
153
154
155 /********************************************************************
156  * AnalysisDataHandle::Impl
157  */
158
159 AnalysisDataHandle::Impl::Impl(AnalysisData *data)
160     : data_(*data), currentFrame_(NULL)
161 {
162 }
163
164
165 /********************************************************************
166  * AnalysisDataHandle
167  */
168
169 AnalysisDataHandle::AnalysisDataHandle(AnalysisData *data)
170     : impl_(new Impl(data))
171 {
172 }
173
174
175 AnalysisDataHandle::~AnalysisDataHandle()
176 {
177 }
178
179
180 void
181 AnalysisDataHandle::startFrame(int index, real x, real dx)
182 {
183     GMX_RELEASE_ASSERT(impl_->currentFrame_ == NULL,
184                        "startFrame() called twice without calling finishFrame()");
185     impl_->currentFrame_ =
186         &impl_->data_.impl_->storage_.startFrame(index, x, dx);
187 }
188
189
190 void
191 AnalysisDataHandle::setPoint(int col, real y, real dy, bool present)
192 {
193     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
194                        "setPoint() called without calling startFrame()");
195     impl_->currentFrame_->setValue(col, y, dy, present);
196 }
197
198
199 void
200 AnalysisDataHandle::setPoints(int firstcol, int n, const real *y)
201 {
202     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
203                        "setPoints() called without calling startFrame()");
204     for (int i = 0; i < n; ++i)
205     {
206         impl_->currentFrame_->setValue(firstcol + i, y[i]);
207     }
208 }
209
210
211 void
212 AnalysisDataHandle::finishPointSet()
213 {
214     GMX_RELEASE_ASSERT(impl_->data_.isMultipoint(),
215                        "finishPointSet() called for non-multipoint data");
216     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
217                        "finishPointSet() called without calling startFrame()");
218     impl_->currentFrame_->finishPointSet();
219 }
220
221
222 void
223 AnalysisDataHandle::finishFrame()
224 {
225     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
226                        "finishFrame() called without calling startFrame()");
227     int index = impl_->currentFrame_->frameIndex();
228     impl_->currentFrame_ = NULL;
229     impl_->data_.impl_->storage_.finishFrame(index);
230 }
231
232
233 void
234 AnalysisDataHandle::finishData()
235 {
236     // Calls delete this
237     impl_->data_.finishData(this);
238 }
239
240 } // namespace gmx