OpenLB 1.7
Loading...
Searching...
No Matches
benchmarkUtil.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2019 Mathias J. Krause, Maximilian Gaedtke, Marc Haußmann, Davide Dapelo, Jonathan Jeppener-Haltenhoff
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef BENCHMARK_UTIL_HH
25#define BENCHMARK_UTIL_HH
26
27#include "benchmarkUtil.h"
28#include <iostream>
29#include <string>
30#include <sstream>
31#include <numeric>
32#include <algorithm>
33#include "utilities/omath.h"
34#include <cassert>
35
36
37namespace olb {
38
39namespace util {
40
41
43
44template<typename T>
45ValueTracer<T>::ValueTracer(T u, T L, T epsilon)
46 : _deltaT((int)(L/u/2.)),
47 _epsilon(epsilon),
48 _t(0),
49 _converged(false),
50 clout(std::cout,"ValueTracer")
51{ }
52
53template<typename T>
54ValueTracer<T>::ValueTracer(int deltaT, T epsilon)
55 : _deltaT(deltaT),
56 _epsilon(epsilon),
57 _t(0),
58 _converged(false),
59 clout(std::cout,"ValueTracer")
60{ }
61
62template<typename T>
63ValueTracer<T>::ValueTracer(int deltaT, T epsilon, std::string name)
64 : _deltaT(deltaT),
65 _epsilon(epsilon),
66 _t(0),
67 _converged(false),
68 clout(std::cout,"ValueTracer "+name)
69{ }
70
71template<typename T>
73{
74 return _deltaT;
75}
76
77template<typename T>
78void ValueTracer<T>::takeValue(T val, bool doPrint)
79{
80 _values.push_back(val);
81 if ((int)_values.size() > util::abs(_deltaT)) {
82 _values.erase(_values.begin());
83 if (doPrint && _t%_deltaT==0) {
84 T average = computeAverage();
85 T stdDev = computeStdDev(average);
86 clout << "average=" << average << "; stdDev/average=" << stdDev/average << std::endl;
87 }
88 }
89 ++_t;
90}
91
92template<typename T>
94{
95 _t = _t%_deltaT;
96 _deltaT = (int) (L/u/2.);
97 if ( (int)_values.size() > util::abs(_deltaT) ) {
98 _values.erase(_values.begin(), _values.begin() + (_values.size()-_deltaT) );
99 }
100}
101
102template<typename T>
104{
105 _t = 0;
106 if ((int)_values.size() > 0) {
107 _values.erase(_values.begin(), _values.begin() + _values.size() );
108 }
109}
110
111template<typename T>
113{
114 if ((int)_values.size() < util::abs(_deltaT)) {
115 return false;
116 }
117 else {
118 T average = computeAverage();
119 T stdDev = computeStdDev(average);
120 if (!std::isnan(stdDev/average)) {
121 return util::fabs(stdDev/average) < _epsilon;
122 }
123 else {
124 clout << "simulation diverged." << std::endl;
125 return true;
126 }
127 }
128}
129template<typename T>
131{
132 if ((int)_values.size() < util::abs(_deltaT)) {
133 return false;
134 }
135 else {
136 T average = computeAverage();
137 T stdDev = computeStdDev(average);
138 if (!std::isnan(stdDev/average)) {
139 return util::fabs(stdDev/average) < _epsilon;
140 }
141 else {
142 clout << "simulation diverged." << std::endl;
143 return false;
144 }
145 }
146}
147template<typename T>
149{
150 if ((int)_values.size() < util::abs(_deltaT)) {
151 return false;
152 }
153 else {
154 T minEl = *min_element(_values.begin(), _values.end());
155 T maxEl = *max_element(_values.begin(), _values.end());
156 T average = computeAverage();
157 return (maxEl - minEl)/average < _epsilon;
158 }
159}
160
161template<typename T>
163{
164 return std::accumulate(_values.begin(), _values.end(), 0.) / _values.size();
165}
166
167template<typename T>
169{
170 int n = _values.size();
171 T sqrDev = 0.;
172 for (int i=0; i<n; ++i) {
173 sqrDev += (_values[i]-average)*(_values[i]-average);
174 }
175 return util::sqrt(sqrDev/(n-1));
176}
177
178template<typename T>
180{
181 return _epsilon;
182}
183
184template<typename T>
186{
187 _epsilon = epsilon;
188}
189
190
191
193
194template<typename T>
196 : iniVal(_iniVal), step(_step), state(first), clout(std::cout,"BisectStepper")
197{
198 if (util::nearZero(step)) {
199 step = iniVal/5.;
200 }
201 assert(step>0.);
202}
203
204template<typename T>
205T BisectStepper<T>::getVal(bool stable, bool doPrint)
206{
207 std::stringstream message;
208 switch (state) {
209 case first:
210 if (stable) {
211 currentVal = iniVal+step;
212 state = up;
213 message << "[" << iniVal << ",infty]";
214 }
215 else {
216 currentVal = iniVal-step;
217 state = down;
218 message << "[-infty," << iniVal << "]";
219 }
220 break;
221 case up:
222 if (stable) {
223 message << "[" << currentVal << ",infty]";
224 currentVal += step;
225 }
226 else {
227 lowerVal = currentVal-step;
228 upperVal = currentVal;
229 currentVal = 0.5*(lowerVal+upperVal);
230 state = bisect;
231 message << "[" << lowerVal << "," << upperVal << "]";
232 }
233 break;
234 case down:
235 if (!stable) {
236 message << "[-infty," << currentVal << "]";
237 currentVal -= step;
238 }
239 else {
240 lowerVal = currentVal;
241 upperVal = currentVal+step;
242 currentVal = 0.5*(lowerVal+upperVal);
243 state = bisect;
244 message << "[" << lowerVal << "," << upperVal << "]";
245 }
246 break;
247 case bisect:
248 if (stable) {
249 lowerVal = currentVal;
250 }
251 else {
252 upperVal = currentVal;
253 }
254 currentVal = 0.5*(lowerVal+upperVal);
255 message << "[" << lowerVal << "," << upperVal << "]";
256 break;
257 }
258 if (doPrint) {
259 clout << "Value in range " << message.str() << std::endl;
260 }
261 return currentVal;
262}
263
264template<typename T>
266{
267 return (state==bisect) && ((upperVal-lowerVal)/lowerVal < epsilon);
268}
269
271
272template<typename T>
273Newton1D<T>::Newton1D(AnalyticalF1D<T,T>& f, T yValue, T eps, int maxIterations) : _f(f), _df(f,eps), _yValue(yValue), _eps(eps), _maxIterations(maxIterations)
274{
275}
276
277template<typename T>
278T Newton1D<T>::solve(T startValue, bool print)
279{
280 T fValue[1], dfValue[1], x[1];
281 x[0] = startValue;
282 _f(fValue,x);
283 T eps = util::fabs(fValue[0] - _yValue);
284 for (int i=0; i<_maxIterations && eps>_eps; i++) {
285 _f(fValue,x);
286 _df(dfValue,x);
287 eps = util::fabs(fValue[0] - _yValue);
288 if (print) {
289 std::cout << "newtonStep=" << i << "; eps=" << eps << "; x=" << x[0] << "; f(x)="<< fValue[0] << "; df(x)="<< dfValue[0] << std::endl;
290 }
291 x[0] -= (fValue[0] - _yValue)/dfValue[0];
292 }
293 return x[0];
294}
295
296template<typename T>
300
301template<typename T>
303{
304 T integral[1], tmp[1], min_[1], max_[1], x[1], deltax[0];
305 min_[0] = min;
306 max_[0] = max;
307 deltax[0] = (max - min) / nSteps;
308 _f(tmp, min);
309 integral[0] = 0.5 * tmp[0];
310 x[0] = min;
311 for (int i = 1; i < nSteps; i++) {
312 x[0] += deltax[0];
313 _f(tmp, x);
314 integral[0] += tmp[0];
315 }
316
317 _f(tmp, max);
318 integral[0] += 0.5*tmp[0];
319 integral[0] *= deltax[0];
320
321 std::cout << "Itnegral=" << integral[0] << std::endl;
322
323 return integral[0];
324}
325
327template<typename T>
329 : _size(size)
330{}
331
332template<typename T>
334{
335 _data.push_back(entry);
336 if (_data.size() > static_cast<unsigned int>(_size) ) {
337 _data.erase( _data.begin() );
338 }
339}
340
341template<typename T>
343{
344 T avg = T();
345 for (auto i=_data.begin(); i!=_data.end(); i++) {
346 avg += *i;
347 }
348 avg *= 1. / _data.size();
349 return avg;
350}
351
352template<typename T>
354{
355 if (pos < 0) {
356 return _data.back();
357 }
358
359 if (pos >= _size) {
360 return _data.front();
361 }
362
363 return _data[_size - 1 - pos];;
364}
365
366template<typename T>
368{
369 return _size;
370}
371
373template<typename T, typename S>
375 const std::function<T(int)> smoothingFactorFunction)
376 : AnalyticalF1D<T,S>(1),
377 _smoothingFactorFunction(smoothingFactorFunction),
378 _EMA(0),
379 _noOfEntries(0) {}
380
381template<typename T, typename S>
383{
384 if (_noOfEntries == 0) {
385 _noOfEntries++;
386 _EMA = val;
387
388 }
389 else {
390 _noOfEntries++;
391 S smoothingFactor = _smoothingFactorFunction(_noOfEntries);
392 _EMA = val* smoothingFactor + _EMA * (1 - smoothingFactor);
393 }
394}
395
396template<typename T, typename S>
398{
399 _noOfEntries = 0;
400}
401
402
403template<typename T, typename S>
404bool ExponentialMovingAverage<T,S>::operator()(T output[], const S x[])
405{
406 output[0] = _EMA;
407 return true;
408}
409
410} // namespace util
411
412} // namespace olb
413
414#endif
BisectStepper(T _iniVal, T _step=0.)
The only constructor.
T getVal(bool stable, bool doPrint=false)
Get new value, and indicate if the previous value yielded a stable system or not.
bool hasConverged(T epsilon) const
Test for convergence.
void insert(T entry)
insert a new entry ed eventually erases the oldest one
T & get(int pos)
get reference to the last entry for pos=0, the second-to-last for pos=1, and so on
T average()
average over all the entries
int getSize()
return size of the buffer
void resetNoOfEntries()
reset number of entries
void takeValue(const T val)
compute next EMA with given value
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
ExponentialMovingAverage(const std::function< T(int)> smoothingFactorFunction=[](int i) -> T { return 2./(1+i);})
(constructor)
T solve(T startValue, bool print=false)
Newton1D(AnalyticalF1D< T, T > &f, T yValue=T(), T eps=1.e-8, int maxIterations=100)
TrapezRuleInt1D(AnalyticalF1D< T, T > &f)
T integrate(T min, T max, int nSteps)
bool hasConverged() const
Test for convergence, with respect to stdDev.
int getDeltaT() const
Get characteristic time scale.
bool convergenceCheck() const
Test for convergence, with respect to difference between min and max value;.
void resetScale(T u, T L)
Change values of u and L to update characteristic scales of the system.
void setEpsilon(T epsilon)
bool hasConvergedMinMax() const
Test for convergence, with respect to difference between min and max value;.
ValueTracer(T u, T L, T epsilon)
Ctor.
void takeValue(T val, bool doPrint=false)
Feed the object with a new measured scalar.
T computeStdDev(T average) const
void resetValues()
reinitializes the values
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
ADf< T, DIM > abs(const ADf< T, DIM > &a)
Definition aDiff.h:1019
cpu::simd::Pack< T > min(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:124
T average(const Vector< T, Size > &a)
computes the average of all elements
T max_element(const Vector< T, Size > &a)
finds maximum element of all elements
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
T min_element(const Vector< T, Size > &a)
finds minimum element of all elements
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
Definition pack.h:106
bool nearZero(const ADf< T, DIM > &a)
Definition aDiff.h:1087
void print(U data, const std::string &name="", OstreamManager clout=OstreamManager(std::cout,"print"), const char delimiter=',')
Top level namespace for all of OpenLB.