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