|
Palabos
Version 1.0
|
00001 /* This file is part of the Palabos library. 00002 * 00003 * Copyright (C) 2011 FlowKit Sarl 00004 * Avenue de Chailly 23 00005 * 1012 Lausanne, Switzerland 00006 * E-mail contact: contact@flowkit.com 00007 * 00008 * The most recent release of Palabos can be downloaded at 00009 * <http://www.palabos.org/> 00010 * 00011 * The library Palabos is free software: you can redistribute it and/or 00012 * modify it under the terms of the GNU Affero General Public License as 00013 * published by the Free Software Foundation, either version 3 of the 00014 * License, or (at your option) any later version. 00015 * 00016 * The library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Affero General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Affero General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 */ 00024 00025 #ifndef BENCHMARK_UTIL_HH 00026 #define BENCHMARK_UTIL_HH 00027 00028 #include "core/globalDefs.h" 00029 #include "io/parallelIO.h" 00030 #include "algorithm/benchmarkUtil.h" 00031 #include <iostream> 00032 #include <string> 00033 #include <sstream> 00034 #include <numeric> 00035 #include <algorithm> 00036 #include <cmath> 00037 #include <cassert> 00038 00039 00040 namespace plb { 00041 00042 namespace util { 00043 00044 00046 00047 template<typename T> 00048 ValueTracer<T>::ValueTracer(T u, T L, T _epsilon) 00049 : deltaT((plint)(L/u/2.)), 00050 epsilon(_epsilon), 00051 t(0), 00052 converged(false) 00053 { } 00054 00055 template<typename T> 00056 plint ValueTracer<T>::getDeltaT() const { 00057 return deltaT; 00058 } 00059 00060 template<typename T> 00061 void ValueTracer<T>::takeValue(T val, bool doPrint) { 00062 values.push_back(val); 00063 if ((plint)values.size() > abs(deltaT)) { 00064 values.erase(values.begin()); 00065 if (doPrint && t%deltaT==0) { 00066 T average = computeAverage(); 00067 T stdDev = computeStdDev(average); 00068 pcout << "average=" << average << "; stdDev/average=" << stdDev/average << std::endl; 00069 } 00070 } 00071 ++t; 00072 } 00073 00074 template<typename T> 00075 void ValueTracer<T>::resetScale(T u, T L) { 00076 t = t%deltaT; 00077 deltaT = (plint) (L/u/2.); 00078 if ( (plint)values.size() > abs(deltaT) ) { 00079 values.erase(values.begin(), values.begin() + (values.size()-deltaT) ); 00080 } 00081 } 00082 00083 template<typename T> 00084 void ValueTracer<T>::resetValues() { 00085 t = 0; 00086 if ((plint)values.size() > 0) { 00087 values.erase(values.begin(), values.begin() + values.size() ); 00088 } 00089 } 00090 00091 template<typename T> 00092 bool ValueTracer<T>::hasConverged() const { 00093 if ((plint)values.size() < abs(deltaT)) { 00094 return false; 00095 } 00096 else { 00097 T average = computeAverage(); 00098 T stdDev = computeStdDev(average); 00099 if (!isnan(stdDev/average)) 00100 return fabs(stdDev/average) < epsilon; 00101 else { 00102 pcout << "simulation diverged.\n"; 00103 return true; 00104 } 00105 } 00106 } 00107 00108 template<typename T> 00109 bool ValueTracer<T>::hasConvergedMinMax() const { 00110 if ((plint)values.size() < abs(deltaT)) { 00111 return false; 00112 } 00113 else { 00114 T minEl = *min_element(values.begin(), values.end()); 00115 T maxEl = *max_element(values.begin(), values.end()); 00116 T average = computeAverage(); 00117 return (maxEl - minEl)/average < epsilon; 00118 } 00119 } 00120 00121 template<typename T> 00122 T ValueTracer<T>::computeAverage() const { 00123 return accumulate(values.begin(), values.end(), 0.) / values.size(); 00124 } 00125 00126 template<typename T> 00127 T ValueTracer<T>::computeStdDev(T average) const { 00128 plint n = values.size(); 00129 T sqrDev = 0.; 00130 for (plint i=0; i<n; ++i) { 00131 sqrDev += (values[i]-average)*(values[i]-average); 00132 } 00133 return sqrt(sqrDev/(n-1)); 00134 } 00135 00136 template<typename T> 00137 void ValueTracer<T>::setEpsilon(T epsilon_) { 00138 epsilon = epsilon_; 00139 } 00140 00141 00142 00144 00145 template<typename T> 00146 BisectStepper<T>::BisectStepper(T _iniVal, T _step) 00147 : iniVal(_iniVal), step(_step), state(first) 00148 { 00149 if (step==0.) { 00150 step = iniVal/5.; 00151 } 00152 assert(step>0.); 00153 } 00154 00155 template<typename T> 00156 T BisectStepper<T>::getVal(bool stable, bool doPrint) { 00157 std::stringstream message; 00158 switch(state) { 00159 case first: 00160 if(stable) { 00161 currentVal = iniVal+step; 00162 state = up; 00163 message << "[" << iniVal << ",infty]"; 00164 } 00165 else { 00166 currentVal = iniVal-step; 00167 state = down; 00168 message << "[-infty," << iniVal << "]"; 00169 } 00170 break; 00171 case up: 00172 if (stable) { 00173 message << "[" << currentVal << ",infty]"; 00174 currentVal += step; 00175 } 00176 else { 00177 lowerVal = currentVal-step; 00178 upperVal = currentVal; 00179 currentVal = 0.5*(lowerVal+upperVal); 00180 state = bisect; 00181 message << "[" << lowerVal << "," << upperVal << "]"; 00182 } 00183 break; 00184 case down: 00185 if (!stable) { 00186 message << "[-infty," << currentVal << "]"; 00187 currentVal -= step; 00188 } 00189 else { 00190 lowerVal = currentVal; 00191 upperVal = currentVal+step; 00192 currentVal = 0.5*(lowerVal+upperVal); 00193 state = bisect; 00194 message << "[" << lowerVal << "," << upperVal << "]"; 00195 } 00196 break; 00197 case bisect: 00198 if (stable) { 00199 lowerVal = currentVal; 00200 } 00201 else { 00202 upperVal = currentVal; 00203 } 00204 currentVal = 0.5*(lowerVal+upperVal); 00205 message << "[" << lowerVal << "," << upperVal << "]"; 00206 break; 00207 } 00208 if (doPrint) { 00209 pcout << "Value in range " << message.str() << std::endl; 00210 } 00211 return currentVal; 00212 } 00213 00214 template<typename T> 00215 bool BisectStepper<T>::hasConverged(T epsilon) const { 00216 return (state==bisect) && ((upperVal-lowerVal)/lowerVal < epsilon); 00217 } 00218 00219 } // namespace util 00220 00221 } // namespace plb 00222 00223 #endif