Merge remote-tracking branch 'gerrit/release-4-6'
[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 "gromacs/analysisdata/dataframe.h"
41 #include "gromacs/analysisdata/datastorage.h"
42 #include "gromacs/analysisdata/paralleloptions.h"
43 #include "gromacs/fatalerror/exceptions.h"
44 #include "gromacs/fatalerror/gmxassert.h"
45
46 #include "analysisdata-impl.h"
47
48 namespace gmx
49 {
50
51 /********************************************************************
52  * AnalysisData::Impl
53  */
54
55 AnalysisData::Impl::Impl()
56 {
57 }
58
59
60 AnalysisData::Impl::~Impl()
61 {
62 }
63
64
65 /********************************************************************
66  * AnalysisData
67  */
68
69 AnalysisData::AnalysisData()
70     : impl_(new Impl)
71 {
72 }
73
74
75 AnalysisData::~AnalysisData()
76 {
77 }
78
79
80 void
81 AnalysisData::setColumns(int ncol, bool multipoint)
82 {
83     GMX_RELEASE_ASSERT(ncol > 0, "Number of columns must be positive");
84     GMX_RELEASE_ASSERT(impl_->handles_.empty(),
85                        "Cannot change data dimensionality after creating handles");
86     setColumnCount(ncol);
87     setMultipoint(multipoint);
88     impl_->storage_.setMultipoint(multipoint);
89 }
90
91
92 AnalysisDataHandle
93 AnalysisData::startData(const AnalysisDataParallelOptions &opt)
94 {
95     GMX_RELEASE_ASSERT(impl_->handles_.size() < static_cast<unsigned>(opt.parallelizationFactor()),
96                        "Too many calls to startData() compared to provided options");
97     if (impl_->handles_.empty())
98     {
99         notifyDataStart();
100         impl_->storage_.setParallelOptions(opt);
101         impl_->storage_.startDataStorage(this);
102     }
103     else if (isMultipoint())
104     {
105         GMX_THROW(NotImplementedError("Parallelism not supported for multipoint data"));
106     }
107
108     Impl::HandlePointer handle(new internal::AnalysisDataHandleImpl(this));
109     impl_->handles_.push_back(move(handle));
110     return AnalysisDataHandle(impl_->handles_.back().get());
111 }
112
113
114 void
115 AnalysisData::finishData(AnalysisDataHandle handle)
116 {
117     Impl::HandleList::iterator i;
118
119     for (i = impl_->handles_.begin(); i != impl_->handles_.end(); ++i)
120     {
121         if (i->get() == handle.impl_)
122         {
123             break;
124         }
125     }
126     GMX_RELEASE_ASSERT(i != impl_->handles_.end(),
127                        "finishData() called for an unknown handle");
128
129     impl_->handles_.erase(i);
130
131     if (impl_->handles_.empty())
132     {
133         notifyDataFinish();
134     }
135 }
136
137
138 AnalysisDataFrameRef
139 AnalysisData::tryGetDataFrameInternal(int index) const
140 {
141     return impl_->storage_.tryGetDataFrame(index);
142 }
143
144
145 bool
146 AnalysisData::requestStorageInternal(int nframes)
147 {
148     return impl_->storage_.requestStorage(nframes);
149 }
150
151
152 /********************************************************************
153  * AnalysisDataHandleImpl
154  */
155
156 internal::AnalysisDataHandleImpl::AnalysisDataHandleImpl(AnalysisData *data)
157     : data_(*data), currentFrame_(NULL)
158 {
159 }
160
161
162 /********************************************************************
163  * AnalysisDataHandle
164  */
165
166 AnalysisDataHandle::AnalysisDataHandle()
167     : impl_(NULL)
168 {
169 }
170
171
172 AnalysisDataHandle::AnalysisDataHandle(internal::AnalysisDataHandleImpl *impl)
173     : impl_(impl)
174 {
175 }
176
177
178 void
179 AnalysisDataHandle::startFrame(int index, real x, real dx)
180 {
181     GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
182     GMX_RELEASE_ASSERT(impl_->currentFrame_ == NULL,
183                        "startFrame() called twice without calling finishFrame()");
184     impl_->currentFrame_ =
185         &impl_->data_.impl_->storage_.startFrame(index, x, dx);
186 }
187
188
189 void
190 AnalysisDataHandle::setPoint(int col, real y, real dy, bool present)
191 {
192     GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
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_ != NULL, "Invalid data handle used");
203     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
204                        "setPoints() called without calling startFrame()");
205     for (int i = 0; i < n; ++i)
206     {
207         impl_->currentFrame_->setValue(firstcol + i, y[i]);
208     }
209 }
210
211
212 void
213 AnalysisDataHandle::finishPointSet()
214 {
215     GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
216     GMX_RELEASE_ASSERT(impl_->data_.isMultipoint(),
217                        "finishPointSet() called for non-multipoint data");
218     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
219                        "finishPointSet() called without calling startFrame()");
220     impl_->currentFrame_->finishPointSet();
221 }
222
223
224 void
225 AnalysisDataHandle::finishFrame()
226 {
227     GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
228     GMX_RELEASE_ASSERT(impl_->currentFrame_ != NULL,
229                        "finishFrame() called without calling startFrame()");
230     int index = impl_->currentFrame_->frameIndex();
231     impl_->currentFrame_ = NULL;
232     impl_->data_.impl_->storage_.finishFrame(index);
233 }
234
235
236 void
237 AnalysisDataHandle::finishData()
238 {
239     GMX_RELEASE_ASSERT(impl_ != NULL, "Invalid data handle used");
240     // Deletes the implementation pointer.
241     impl_->data_.finishData(*this);
242     impl_ = NULL;
243 }
244
245 } // namespace gmx