$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 // C++ includes 00020 #include <algorithm> // for std::min_element, std::max_element 00021 #include <fstream> // std::ofstream 00022 #include <numeric> // std::accumulate 00023 00024 // Local includes 00025 #include "libmesh/statistics.h" 00026 #include "libmesh/libmesh_logging.h" 00027 00028 namespace libMesh 00029 { 00030 00031 00032 00033 // ------------------------------------------------------------ 00034 // StatisticsVector class member functions 00035 template <typename T> 00036 Real StatisticsVector<T>::l2_norm() const 00037 { 00038 Real normsq = 0.; 00039 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00040 for (dof_id_type i = 0; i != n; ++i) 00041 normsq += ((*this)[i] * (*this)[i]); 00042 00043 return std::sqrt(normsq); 00044 } 00045 00046 00047 template <typename T> 00048 T StatisticsVector<T>::minimum() const 00049 { 00050 START_LOG ("minimum()", "StatisticsVector"); 00051 00052 const T min = *(std::min_element(this->begin(), this->end())); 00053 00054 STOP_LOG ("minimum()", "StatisticsVector"); 00055 00056 return min; 00057 } 00058 00059 00060 00061 00062 template <typename T> 00063 T StatisticsVector<T>::maximum() const 00064 { 00065 START_LOG ("maximum()", "StatisticsVector"); 00066 00067 const T max = *(std::max_element(this->begin(), this->end())); 00068 00069 STOP_LOG ("maximum()", "StatisticsVector"); 00070 00071 return max; 00072 } 00073 00074 00075 00076 00077 template <typename T> 00078 Real StatisticsVector<T>::mean() const 00079 { 00080 START_LOG ("mean()", "StatisticsVector"); 00081 00082 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00083 00084 Real the_mean = 0; 00085 00086 for (dof_id_type i=0; i<n; i++) 00087 { 00088 the_mean += ( static_cast<Real>((*this)[i]) - the_mean ) / 00089 static_cast<Real>(i + 1); 00090 } 00091 00092 STOP_LOG ("mean()", "StatisticsVector"); 00093 00094 return the_mean; 00095 } 00096 00097 00098 00099 00100 template <typename T> 00101 Real StatisticsVector<T>::median() 00102 { 00103 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00104 00105 if (n == 0) 00106 return 0.; 00107 00108 START_LOG ("median()", "StatisticsVector"); 00109 00110 std::sort(this->begin(), this->end()); 00111 00112 const dof_id_type lhs = (n-1) / 2; 00113 const dof_id_type rhs = n / 2; 00114 00115 Real the_median = 0; 00116 00117 00118 if (lhs == rhs) 00119 { 00120 the_median = static_cast<Real>((*this)[lhs]); 00121 } 00122 00123 else 00124 { 00125 the_median = ( static_cast<Real>((*this)[lhs]) + 00126 static_cast<Real>((*this)[rhs]) ) / 2.0; 00127 } 00128 00129 STOP_LOG ("median()", "StatisticsVector"); 00130 00131 return the_median; 00132 } 00133 00134 00135 00136 00137 template <typename T> 00138 Real StatisticsVector<T>::median() const 00139 { 00140 StatisticsVector<T> sv = (*this); 00141 00142 return sv.median(); 00143 } 00144 00145 00146 00147 00148 template <typename T> 00149 Real StatisticsVector<T>::variance(const Real mean_in) const 00150 { 00151 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00152 00153 START_LOG ("variance()", "StatisticsVector"); 00154 00155 Real the_variance = 0; 00156 00157 for (dof_id_type i=0; i<n; i++) 00158 { 00159 const Real delta = ( static_cast<Real>((*this)[i]) - mean_in ); 00160 the_variance += (delta * delta - the_variance) / 00161 static_cast<Real>(i + 1); 00162 } 00163 00164 if (n > 1) 00165 the_variance *= static_cast<Real>(n) / static_cast<Real>(n - 1); 00166 00167 STOP_LOG ("variance()", "StatisticsVector"); 00168 00169 return the_variance; 00170 } 00171 00172 00173 template <typename T> 00174 void StatisticsVector<T>::normalize() 00175 { 00176 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00177 const Real max = this->maximum(); 00178 00179 for (dof_id_type i=0; i<n; i++) 00180 { 00181 (*this)[i] = static_cast<T>((*this)[i] / max); 00182 } 00183 } 00184 00185 00186 00187 00188 00189 template <typename T> 00190 void StatisticsVector<T>::histogram(std::vector<dof_id_type>& bin_members, 00191 unsigned int n_bins) 00192 { 00193 // Must have at least 1 bin 00194 libmesh_assert (n_bins>0); 00195 00196 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00197 00198 std::sort(this->begin(), this->end()); 00199 00200 // The StatisticsVector can hold both integer and float types. 00201 // We will define all the bins, etc. using Reals. 00202 Real min = static_cast<Real>(this->minimum()); 00203 Real max = static_cast<Real>(this->maximum()); 00204 Real bin_size = (max - min) / static_cast<Real>(n_bins); 00205 00206 START_LOG ("histogram()", "StatisticsVector"); 00207 00208 std::vector<Real> bin_bounds(n_bins+1); 00209 for (unsigned int i=0; i<bin_bounds.size(); i++) 00210 bin_bounds[i] = min + i * bin_size; 00211 00212 // Give the last bin boundary a little wiggle room: we don't want 00213 // it to be just barely less than the max, otherwise our bin test below 00214 // may fail. 00215 bin_bounds.back() += 1.e-6 * bin_size; 00216 00217 // This vector will store the number of members each bin has. 00218 bin_members.resize(n_bins); 00219 00220 dof_id_type data_index = 0; 00221 for (unsigned int j=0; j<bin_members.size(); j++) // bin vector indexing 00222 { 00223 // libMesh::out << "(debug) Filling bin " << j << std::endl; 00224 00225 for (dof_id_type i=data_index; i<n; i++) // data vector indexing 00226 { 00227 //libMesh::out << "(debug) Processing index=" << i << std::endl; 00228 Real current_val = static_cast<Real>( (*this)[i] ); 00229 00230 // There may be entries in the vector smaller than the value 00231 // reported by this->minimum(). (e.g. inactive elements in an 00232 // ErrorVector.) We just skip entries like that. 00233 if ( current_val < min ) 00234 { 00235 // libMesh::out << "(debug) Skipping entry v[" << i << "]=" 00236 // << (*this)[i] 00237 // << " which is less than the min value: min=" 00238 // << min << std::endl; 00239 continue; 00240 } 00241 00242 if ( current_val > bin_bounds[j+1] ) // if outside the current bin (bin[j] is bounded 00243 // by bin_bounds[j] and bin_bounds[j+1]) 00244 { 00245 // libMesh::out.precision(16); 00246 // libMesh::out.setf(std::ios_base::fixed); 00247 // libMesh::out << "(debug) (*this)[i]= " << (*this)[i] 00248 // << " is greater than bin_bounds[j+1]=" 00249 // << bin_bounds[j+1] << std::endl; 00250 data_index = i; // start searching here for next bin 00251 break; // go to next bin 00252 } 00253 00254 // Otherwise, increment current bin's count 00255 bin_members[j]++; 00256 // libMesh::out << "(debug) Binned index=" << i << std::endl; 00257 } 00258 } 00259 00260 #ifdef DEBUG 00261 // Check the number of binned entries 00262 const dof_id_type n_binned = std::accumulate(bin_members.begin(), 00263 bin_members.end(), 00264 static_cast<dof_id_type>(0), 00265 std::plus<dof_id_type>()); 00266 00267 if (n != n_binned) 00268 { 00269 libMesh::out << "Warning: The number of binned entries, n_binned=" 00270 << n_binned 00271 << ", did not match the total number of entries, n=" 00272 << n << "." << std::endl; 00273 } 00274 #endif 00275 00276 00277 STOP_LOG ("histogram()", "StatisticsVector"); 00278 } 00279 00280 00281 00282 00283 00284 template <typename T> 00285 void StatisticsVector<T>::plot_histogram(const processor_id_type my_procid, 00286 const std::string& filename, 00287 unsigned int n_bins) 00288 { 00289 // First generate the histogram with the desired number of bins 00290 std::vector<dof_id_type> bin_members; 00291 this->histogram(bin_members, n_bins); 00292 00293 // The max, min and bin size are used to generate x-axis values. 00294 T min = this->minimum(); 00295 T max = this->maximum(); 00296 T bin_size = (max - min) / static_cast<T>(n_bins); 00297 00298 // On processor 0: Write histogram to file 00299 if (my_procid==0) 00300 { 00301 std::ofstream out_stream (filename.c_str()); 00302 00303 out_stream << "clear all\n"; 00304 out_stream << "clf\n"; 00305 //out_stream << "x=linspace(" << min << "," << max << "," << n_bins+1 << ");\n"; 00306 00307 // abscissa values are located at the center of each bin. 00308 out_stream << "x=["; 00309 for (unsigned int i=0; i<bin_members.size(); ++i) 00310 { 00311 out_stream << min + (i+0.5)*bin_size << " "; 00312 } 00313 out_stream << "];\n"; 00314 00315 out_stream << "y=["; 00316 for (unsigned int i=0; i<bin_members.size(); ++i) 00317 { 00318 out_stream << bin_members[i] << " "; 00319 } 00320 out_stream << "];\n"; 00321 out_stream << "bar(x,y);\n"; 00322 } 00323 } 00324 00325 00326 00327 template <typename T> 00328 void StatisticsVector<T>::histogram(std::vector<dof_id_type>& bin_members, 00329 unsigned int n_bins) const 00330 { 00331 StatisticsVector<T> sv = (*this); 00332 00333 return sv.histogram(bin_members, n_bins); 00334 } 00335 00336 00337 00338 00339 template <typename T> 00340 std::vector<dof_id_type> StatisticsVector<T>::cut_below(Real cut) const 00341 { 00342 START_LOG ("cut_below()", "StatisticsVector"); 00343 00344 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00345 00346 std::vector<dof_id_type> cut_indices; 00347 cut_indices.reserve(n/2); // Arbitrary 00348 00349 for (dof_id_type i=0; i<n; i++) 00350 { 00351 if ((*this)[i] < cut) 00352 { 00353 cut_indices.push_back(i); 00354 } 00355 } 00356 00357 STOP_LOG ("cut_below()", "StatisticsVector"); 00358 00359 return cut_indices; 00360 } 00361 00362 00363 00364 00365 template <typename T> 00366 std::vector<dof_id_type> StatisticsVector<T>::cut_above(Real cut) const 00367 { 00368 START_LOG ("cut_above()", "StatisticsVector"); 00369 00370 const dof_id_type n = cast_int<dof_id_type>(this->size()); 00371 00372 std::vector<dof_id_type> cut_indices; 00373 cut_indices.reserve(n/2); // Arbitrary 00374 00375 for (dof_id_type i=0; i<n; i++) 00376 { 00377 if ((*this)[i] > cut) 00378 { 00379 cut_indices.push_back(i); 00380 } 00381 } 00382 00383 STOP_LOG ("cut_above()", "StatisticsVector"); 00384 00385 return cut_indices; 00386 } 00387 00388 00389 00390 00391 //------------------------------------------------------------ 00392 // Explicit Instantions 00393 template class StatisticsVector<float>; 00394 template class StatisticsVector<double>; 00395 #ifdef LIBMESH_DEFAULT_TRIPLE_PRECISION 00396 template class StatisticsVector<long double>; 00397 #endif 00398 template class StatisticsVector<int>; 00399 template class StatisticsVector<unsigned int>; 00400 00401 } // namespace libMesh