preCICE v3.1.1
Loading...
Searching...
No Matches
Storage.cpp
Go to the documentation of this file.
1#include <boost/range.hpp>
2
4#include "math/Bspline.hpp"
6#include "time/Storage.hpp"
7#include "time/Time.hpp"
8#include "utils/assertion.hpp"
9
10namespace precice::time {
11
13 : _stampleStorage{}, _degree(0)
14{
15}
16
18{
19 this->clear();
20 this->_degree = other.getInterpolationDegree();
21 for (const auto &stample : other.stamples()) {
22 this->setSampleAtTime(stample.timestamp, stample.sample);
23 }
24 return *this;
25}
26
27void Storage::setSampleAtTime(double time, const Sample &sample)
28{
29 // The spline has to be recomputed, since the underlying data has changed
30 _bspline.reset();
31
32 if (_stampleStorage.empty()) {
33 _stampleStorage.emplace_back(Stample{time, sample});
34 return;
35 }
36
37 const double currentWindowStart = _stampleStorage.front().timestamp;
38
39 PRECICE_ASSERT(not sample.values.hasNaN());
40 PRECICE_ASSERT(math::smallerEquals(currentWindowStart, time), "Setting sample outside of valid range!", currentWindowStart, time);
41 // check if key "time" exists.
42 auto existingSample = std::find_if(_stampleStorage.begin(), _stampleStorage.end(), [&time](const auto &s) { return math::equals(s.timestamp, time); });
43 if (existingSample == _stampleStorage.end()) { // key does not exist yet
44 PRECICE_ASSERT(math::smaller(maxStoredTime(), time), maxStoredTime(), time, "Trying to write sample with a time that is too small. Please use clear(), if you want to write new samples to the storage.");
45 _stampleStorage.emplace_back(Stample{time, sample});
46 } else {
47 // Overriding sample
48 existingSample->sample = sample;
49 }
50}
51
52void Storage::setInterpolationDegree(int interpolationDegree)
53{
55 _degree = interpolationDegree;
56
57 // The spline has to be recomputed, since the underlying data has changed
58 _bspline.reset();
59}
60
62{
63 return _degree;
64}
65
67{
68 if (_stampleStorage.size() == 0) {
69 return -1; // invalid return
70 } else {
71 return _stampleStorage.back().timestamp;
72 }
73}
74
75int Storage::nTimes() const
76{
77 return _stampleStorage.size();
78}
79
80int Storage::nDofs() const
81{
83 return _stampleStorage[0].sample.values.size();
84}
85
87{
88 PRECICE_ASSERT(nTimes() >= 2, "Calling Storage::move() is only allowed, if there is a sample at the beginning and at the end. This ensures that this function is only called at the end of the window.", getTimes());
89 PRECICE_ASSERT(!_stampleStorage.empty(), "Storage does not contain any data!");
90 const double nextWindowStart = _stampleStorage.back().timestamp;
91 _stampleStorage.erase(_stampleStorage.begin(), --_stampleStorage.end());
92 PRECICE_ASSERT(nextWindowStart == _stampleStorage.front().timestamp);
93
94 // The spline has to be recomputed, since the underlying data has changed
95 _bspline.reset();
96}
97
99{
100 PRECICE_ASSERT(!_stampleStorage.empty(), "Storage does not contain any data!");
101 const double thisWindowStart = _stampleStorage.front().timestamp;
102 _stampleStorage.erase(++_stampleStorage.begin(), _stampleStorage.end());
103 PRECICE_ASSERT(_stampleStorage.size() == 1);
104 PRECICE_ASSERT(thisWindowStart == _stampleStorage.front().timestamp);
105
106 // The spline has to be recomputed, since the underlying data has changed
107 _bspline.reset();
108}
109
111{
112 _stampleStorage.clear();
113 PRECICE_ASSERT(_stampleStorage.size() == 0);
114
115 // The spline has to be recomputed, since the underlying data has changed
116 _bspline.reset();
117}
118
120{
121 if (_stampleStorage.empty()) {
122 return;
123 }
124 _stampleStorage.erase(_stampleStorage.begin(), --_stampleStorage.end());
125
126 // The spline has to be recomputed, since the underlying data has changed
127 _bspline.reset();
128}
129
130void Storage::trimBefore(double time)
131{
132 auto beforeTime = [time](const auto &s) { return math::smaller(s.timestamp, time); };
133 _stampleStorage.erase(std::remove_if(_stampleStorage.begin(), _stampleStorage.end(), beforeTime), _stampleStorage.end());
134
135 // The spline has to be recomputed, since the underlying data has changed
136 _bspline.reset();
137}
138
139void Storage::trimAfter(double time)
140{
141 auto afterTime = [time](const auto &s) { return math::greater(s.timestamp, time); };
142 _stampleStorage.erase(std::remove_if(_stampleStorage.begin(), _stampleStorage.end(), afterTime), _stampleStorage.end());
143
144 // The spline has to be recomputed, since the underlying data has changed
145 _bspline.reset();
146}
147
149{
150 PRECICE_TRACE(before);
151 if (nTimes() == 1) {
152 return _stampleStorage.front().sample; // @todo in this case the name getSampleAtOrAfter does not fit, because _stampleStorage.front().sample is returned for any time before.
153 } else {
154 auto stample = std::find_if(_stampleStorage.begin(), _stampleStorage.end(), [&before](const auto &s) { return math::greaterEquals(s.timestamp, before); });
155 PRECICE_ASSERT(stample != _stampleStorage.end(), "no values found!");
156 return stample->sample;
157 }
158}
159
160Eigen::VectorXd Storage::getTimes() const
161{
162 auto times = Eigen::VectorXd(nTimes());
163 for (int i = 0; i < times.size(); i++) {
164 times[i] = _stampleStorage[i].timestamp;
165 }
166 return times;
167}
168
169bool Storage::empty() const
170{
171 return _stampleStorage.empty();
172}
173
175{
177 return _stampleStorage[_stampleStorage.size() - 1];
178}
179
181{
182 auto times = Eigen::VectorXd(nTimes());
183 auto values = Eigen::MatrixXd(nDofs(), nTimes());
184 for (int i = 0; i < times.size(); i++) {
185 times[i] = _stampleStorage[i].timestamp;
186 values.col(i) = _stampleStorage[i].sample.values;
187 }
188 return std::make_pair(times, values);
189}
190
191Eigen::VectorXd Storage::sample(double time) const
192{
193 const int usedDegree = computeUsedDegree(_degree, nTimes());
194
195 if (usedDegree == 0) {
196 return this->getSampleAtOrAfter(time).values;
197 }
198
199 PRECICE_ASSERT(usedDegree >= 1);
200
201 //Return the sample corresponding to time if it exists
202 const int i = findTimeId(time);
203 if (i > -1) { // _stampleStorage contains sample at given time
204 return _stampleStorage[i].sample.values; // don't use getTimesAndValues, because this would iterate over the complete _stampleStorage.
205 }
206
207 //Create a new bspline if _bspline does not already contain a spline
208 if (!_bspline.has_value()) {
209 auto [times, values] = getTimesAndValues();
210 _bspline.emplace(times, values, usedDegree);
211 }
212
213 return _bspline.value().interpolateAt(time);
214}
215
216Eigen::MatrixXd Storage::sampleGradients(double time) const
217{
218 const int usedDegree = computeUsedDegree(_degree, nTimes());
219
220 if (usedDegree == 0) {
221 return this->getSampleAtOrAfter(time).gradients;
222 }
223
224 PRECICE_WARN("You specified interpolation degree of {}, but only degree 0 is supported for gradient interpolation", usedDegree); // @todo implement this like for sampleAt
225 return this->getSampleAtOrAfter(time).gradients;
226}
227
228int Storage::computeUsedDegree(int requestedDegree, int numberOfAvailableSamples) const
229{
230 PRECICE_ASSERT(requestedDegree <= Time::MAX_WAVEFORM_DEGREE);
231 return std::min(requestedDegree, numberOfAvailableSamples - 1);
232}
233
235{
236 return _stampleStorage.front().sample;
237}
238
240{
241 return _stampleStorage.back().sample;
242}
243
244int Storage::findTimeId(double time) const
245{
246 int i = 0;
247 while (math::smallerEquals(_stampleStorage[i].timestamp, time)) {
248 if (math::equals(_stampleStorage[i].timestamp, time)) {
249 return i;
250 }
251 i++;
252 }
253 return -1; // time not found in times
254}
255
256} // namespace precice::time
#define PRECICE_WARN(...)
Definition LogMacros.hpp:11
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:95
#define PRECICE_ASSERT(...)
Definition assertion.hpp:87
void trimAfter(double time)
Definition Storage.cpp:139
Eigen::VectorXd sample(double time) const
Need to use interpolation for the case with changing time grids.
Definition Storage.cpp:191
Sample getSampleAtOrAfter(double before) const
Returns the Sample at time following "before" contained in this Storage.
Definition Storage.cpp:148
auto stamples() const
Get the stamples.
Definition Storage.hpp:75
void trimBefore(double time)
Definition Storage.cpp:130
int findTimeId(double time) const
Definition Storage.cpp:244
void setSampleAtTime(double time, const Sample &sample)
Store Sample at a specific time.
Definition Storage.cpp:27
Storage()
Stores data samples in time and provides corresponding convenience functions.
Definition Storage.cpp:12
void clear()
Clears this Storage by deleting all values.
Definition Storage.cpp:110
int nDofs() const
Number of Dofs for each values.
Definition Storage.cpp:80
Eigen::MatrixXd sampleGradients(double time) const
Definition Storage.cpp:216
void trim()
Trims this Storage by deleting all values except values associated with the window start.
Definition Storage.cpp:98
std::pair< Eigen::VectorXd, Eigen::MatrixXd > getTimesAndValues() const
Get all normalized dts and values in ascending order (with respect to normalized dts)
Definition Storage.cpp:180
double maxStoredTime() const
Get maximum time that is stored in this Storage.
Definition Storage.cpp:66
std::optional< math::Bspline > _bspline
Definition Storage.hpp:149
int computeUsedDegree(int requestedDegree, int numberOfAvailableSamples) const
Computes which degree may be used for interpolation.
Definition Storage.cpp:228
Storage & operator=(const Storage &other)
Copy assignment operator to assign Storage to this Storage.
Definition Storage.cpp:17
void setInterpolationDegree(int interpolationDegree)
Definition Storage.cpp:52
std::vector< Stample > _stampleStorage
Stores Stamples on the current window.
Definition Storage.hpp:143
void move()
Move this Storage by deleting all stamples except the one at the end of the window.
Definition Storage.cpp:86
int nTimes() const
Number of stored times.
Definition Storage.cpp:75
Eigen::VectorXd getTimes() const
Get all normalized dts stored in this Storage sorted ascending.
Definition Storage.cpp:160
time::Sample getSampleAtBeginning()
Definition Storage.cpp:234
const time::Stample & last() const
Definition Storage.cpp:174
time::Sample getSampleAtEnd()
Definition Storage.cpp:239
int getInterpolationDegree() const
Definition Storage.cpp:61
static const int MAX_WAVEFORM_DEGREE
The maximum allowed interpolation degree.
Definition Time.hpp:15
static const int MIN_WAVEFORM_DEGREE
The minimum required interpolation degree.
Definition Time.hpp:12
T find_if(T... args)
T make_pair(T... args)
T min(T... args)
constexpr bool equals(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares two Eigen::MatrixBase for equality up to tolerance.
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type smallerEquals(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type smaller(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type greater(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
contains the time interpolation logic.
Definition Sample.hpp:6
T remove_if(T... args)
Eigen::MatrixXd gradients
The gradients of the data. Use gradients.col(i) to get the gradient at vertex i.
Definition Sample.hpp:52
Eigen::VectorXd values
Definition Sample.hpp:49
Stample containing timestampled Sample.
Definition Stample.hpp:7