$extrastylesheet
system_norm.h
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 
00020 #ifndef LIBMESH_SYSTEM_NORM_H
00021 #define LIBMESH_SYSTEM_NORM_H
00022 
00023 // Local includes
00024 #include "libmesh/libmesh_common.h" // for Real
00025 #include "libmesh/enum_norm_type.h"
00026 
00027 // C++ includes
00028 #include <vector>
00029 
00030 namespace libMesh
00031 {
00032 
00033 // Forward Declarations
00034 
00045 // ------------------------------------------------------------
00046 // SystemNorm class definition
00047 class SystemNorm
00048 {
00049 public:
00050 
00054   SystemNorm();
00055 
00064   SystemNorm(const FEMNormType &t);
00065 
00073   explicit
00074   SystemNorm(const std::vector<FEMNormType> &norms);
00075 
00083   SystemNorm(const std::vector<FEMNormType> &norms, std::vector<Real> &weights);
00084 
00092   SystemNorm(const std::vector<FEMNormType> &norms, std::vector<std::vector<Real> > &weights);
00093 
00097   SystemNorm(const SystemNorm &s);
00098 
00102   bool is_discrete() const;
00103 
00108   Real calculate_norm(const std::vector<Real>& v);
00109 
00113   Real calculate_norm(const std::vector<Real>& v1, const std::vector<Real>& v2);
00114 
00118   bool is_identity();
00119 
00123   FEMNormType type(unsigned int var) const;
00124 
00128   void set_type(unsigned int var, const FEMNormType& t);
00129 
00133   Real weight(unsigned int var) const;
00134 
00138   void set_weight(unsigned int var, Real w);
00139 
00143   void set_off_diagonal_weight(unsigned int i, unsigned int j, Real w);
00144 
00149   Real weight_sq(unsigned int var) const;
00150 
00151 
00152 
00153 private:
00154   std::vector<FEMNormType> _norms;
00155 
00156   std::vector<Real> _weights;
00157   std::vector<Real> _weights_sq;
00158 
00163   std::vector<std::vector<Real> > _off_diagonal_weights;
00164 };
00165 
00166 
00167 
00168 // ------------------------------------------------------------
00169 // SystemNorm inline methods
00170 
00171 inline
00172 SystemNorm::SystemNorm() :
00173   _norms(1, DISCRETE_L2), _weights(1, 1.0), _weights_sq(1, 1.0)
00174 {
00175 }
00176 
00177 
00178 inline
00179 SystemNorm::SystemNorm(const FEMNormType &t) :
00180   _norms(1, t), _weights(1, 1.0), _weights_sq(1, 1.0)
00181 {
00182 }
00183 
00184 
00185 inline
00186 SystemNorm::SystemNorm(const std::vector<FEMNormType> &norms) :
00187   _norms(norms), _weights(1, 1.0), _weights_sq(1, 1.0)
00188 {
00189   if (_norms.empty())
00190     _norms.push_back(DISCRETE_L2);
00191 }
00192 
00193 
00194 inline
00195 SystemNorm::SystemNorm(const std::vector<FEMNormType> &norms,
00196                        std::vector<Real> &weights) :
00197   _norms(norms), _weights(weights), _weights_sq(_weights.size(), 0.0)
00198 {
00199   if (_norms.empty())
00200     _norms.push_back(DISCRETE_L2);
00201 
00202   if (_weights.empty())
00203     {
00204       _weights.push_back(1.0);
00205       _weights_sq.push_back(1.0);
00206     }
00207   else
00208     for (std::size_t i=0; i != _weights.size(); ++i)
00209       _weights_sq[i] = _weights[i] * _weights[i];
00210 }
00211 
00212 inline
00213 SystemNorm::SystemNorm(const std::vector<FEMNormType> &norms,
00214                        std::vector<std::vector<Real> > &weights):
00215   _norms(norms),
00216   _weights(weights.size()),
00217   _weights_sq(weights.size()),
00218   _off_diagonal_weights(weights)
00219 {
00220   if(_norms.empty())
00221     _norms.push_back(DISCRETE_L2);
00222 
00223   if (_weights.empty())
00224     {
00225       _weights.push_back(1.0);
00226       _weights_sq.push_back(1.0);
00227     }
00228   else
00229     {
00230       // Loop over the entries of the user provided matrix and store its entries in
00231       // the _off_diagonal_weights or _diagonal_weights
00232       for(std::size_t i=0; i!=_off_diagonal_weights.size(); ++i)
00233         {
00234           if(_off_diagonal_weights[i].size() > i)
00235             {
00236               _weights[i] = _off_diagonal_weights[i][i];
00237               _off_diagonal_weights[i][i] = 0;
00238             }
00239           else
00240             _weights[i] = 1.0;
00241         }
00242       for (std::size_t i=0; i != _weights.size(); ++i)
00243         _weights_sq[i] = _weights[i] * _weights[i];
00244     }
00245 }
00246 
00247 inline
00248 SystemNorm::SystemNorm(const SystemNorm &s) :
00249   _norms(s._norms), _weights(s._weights), _weights_sq(s._weights_sq)
00250 {
00251 }
00252 
00253 
00254 inline
00255 bool SystemNorm::is_discrete() const
00256 {
00257   libmesh_assert (!_norms.empty());
00258 
00259   if (_norms[0] == DISCRETE_L1 ||
00260       _norms[0] == DISCRETE_L2 ||
00261       _norms[0] == DISCRETE_L_INF)
00262     return true;
00263 
00264   return false;
00265 }
00266 
00267 
00268 inline
00269 FEMNormType SystemNorm::type(unsigned int var) const
00270 {
00271   libmesh_assert (!_norms.empty());
00272 
00273   std::size_t i = (var < _norms.size()) ? var : _norms.size() - 1;
00274 
00275   return _norms[i];
00276 }
00277 
00278 
00279 
00280 inline
00281 void SystemNorm::set_type(unsigned int var, const FEMNormType &t)
00282 {
00283   libmesh_assert (!_norms.empty());
00284 
00285   if (var >= _norms.size())
00286     _norms.resize(var+1, t);
00287 
00288   _norms[var] = t;
00289 }
00290 
00291 
00292 inline
00293 Real SystemNorm::weight(unsigned int var) const
00294 {
00295   libmesh_assert (!_weights.empty());
00296 
00297   return (var < _weights.size()) ? _weights[var] : 1.0;
00298 }
00299 
00300 
00301 inline
00302 void SystemNorm::set_weight(unsigned int var, Real w)
00303 {
00304   libmesh_assert (!_weights.empty());
00305 
00306   if (var >= _weights.size())
00307     {
00308       _weights.resize(var+1, 1.0);
00309       _weights_sq.resize(var+1, 1.0);
00310     }
00311 
00312   _weights[var] = w;
00313   _weights_sq[var] = w*w;
00314 }
00315 
00316 inline
00317 void SystemNorm::set_off_diagonal_weight(unsigned int i, unsigned int j, Real w)
00318 {
00319   libmesh_assert (!_weights.empty());
00320 
00321   if (i >= _off_diagonal_weights.size())
00322     {
00323       _off_diagonal_weights.resize(i+1);
00324     }
00325 
00326   if (j >= _off_diagonal_weights[i].size())
00327     {
00328       _off_diagonal_weights[i].resize(j+1, 0.);
00329     }
00330 
00331   _off_diagonal_weights[i][j] = w;
00332 
00333 }
00334 
00335 
00336 inline
00337 Real SystemNorm::weight_sq(unsigned int var) const
00338 {
00339   libmesh_assert (!_weights_sq.empty());
00340 
00341   return (var < _weights_sq.size()) ? _weights_sq[var] : 1.0;
00342 }
00343 
00344 
00345 inline
00346 Real SystemNorm::calculate_norm(const std::vector<Real>& v1, const std::vector<Real>& v2)
00347 {
00348   // The vectors are assumed to both be vectors of the (same number
00349   // of) components
00350   std::size_t vsize = v1.size();
00351   libmesh_assert_equal_to (vsize, v2.size());
00352 
00353   // We'll support implicitly defining weights, but if the user sets
00354   // more weights than he uses then something's probably wrong
00355   std::size_t diagsize = this->_weights.size();
00356   libmesh_assert_greater_equal (vsize, diagsize);
00357 
00358   // Initialize the variable val
00359   Real val = 0.;
00360 
00361   // Loop over all the components of the system with explicit
00362   // weights
00363   for(std::size_t i = 0; i != diagsize; i++)
00364     {
00365       val += this->_weights[i] * v1[i] * v2[i];
00366     }
00367   // Loop over all the components of the system with implicit
00368   // weights
00369   for(std::size_t i = diagsize; i < vsize; i++)
00370     {
00371       val += v1[i] * v2[i];
00372     }
00373 
00374   // Loop over the components of the system
00375   std::size_t nrows = this->_off_diagonal_weights.size();
00376   libmesh_assert_less_equal (vsize, nrows);
00377 
00378   for(std::size_t i = 0; i != nrows; i++)
00379     {
00380       std::size_t ncols = this->_off_diagonal_weights[i].size();
00381       for(std::size_t j=0; j != ncols; j++)
00382         {
00383           // Note that the diagonal weights here were set to zero
00384           // in the constructor
00385           val += this->_off_diagonal_weights[i][j] * v1[i] * v2[j];
00386         }
00387     }
00388 
00389   return(val);
00390 }
00391 
00392 inline
00393 Real SystemNorm::calculate_norm(const std::vector<Real>& v1)
00394 {
00395   return this->calculate_norm(v1,v1);
00396 }
00397 
00398 inline
00399 bool SystemNorm::is_identity()
00400 {
00401   std::size_t nrows = this->_off_diagonal_weights.size();
00402 
00403   // If any of the off-diagonal elements is not 0, then we are in the non-identity case
00404   for(std::size_t i = 0; i != nrows; i++)
00405     {
00406       std::size_t ncols = this->_off_diagonal_weights[i].size();
00407       for(std::size_t j = 0; j != ncols; j++)
00408         {
00409           if(_off_diagonal_weights[i][j] != 0)
00410             {
00411               return(false);
00412             }
00413         }
00414     }
00415 
00416   // If any of the diagonal elements is not 1, then we are in the non-identity case
00417   nrows = this->_weights.size();
00418   for(std::size_t i = 0; i != nrows; i++)
00419     if(_weights[i] != 1)
00420       return(false);
00421 
00422   // If all the off-diagonals elements are 0, and diagonal elements 1, then we are in an identity case
00423   return(true);
00424 }
00425 
00426 } // namespace libMesh
00427 
00428 #endif // LIBMESH_SYSTEM_NORM_H