$extrastylesheet
statistics.C
Go to the documentation of this file.
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