libMesh
system_norm.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #ifndef LIBMESH_SYSTEM_NORM_H
21 #define LIBMESH_SYSTEM_NORM_H
22 
23 // Local includes
24 #include "libmesh/libmesh_common.h" // for Real
25 #include "libmesh/enum_norm_type.h"
26 
27 // C++ includes
28 #include <vector>
29 
30 namespace libMesh
31 {
32 
44 {
45 public:
46 
50  SystemNorm();
51 
60  SystemNorm(const FEMNormType & t);
61 
69  explicit
70  SystemNorm(const std::vector<FEMNormType> & norms);
71 
79  SystemNorm(const std::vector<FEMNormType> & norms,
80  std::vector<Real> & weights);
81 
89  SystemNorm(const std::vector<FEMNormType> & norms,
90  std::vector<std::vector<Real>> & weights);
91 
95  SystemNorm(const SystemNorm & s);
96 
100  bool is_discrete() const;
101 
106  Real calculate_norm(const std::vector<Real> & v);
107 
111  Real calculate_norm(const std::vector<Real> & v1,
112  const std::vector<Real> & v2);
113 
117  bool is_identity();
118 
122  FEMNormType type(unsigned int var) const;
123 
127  void set_type(unsigned int var, const FEMNormType & t);
128 
132  Real weight(unsigned int var) const;
133 
137  void set_weight(unsigned int var, Real w);
138 
142  void set_off_diagonal_weight(unsigned int i, unsigned int j, Real w);
143 
148  Real weight_sq(unsigned int var) const;
149 
150 
151 
152 private:
153  std::vector<FEMNormType> _norms;
154 
155  std::vector<Real> _weights;
156  std::vector<Real> _weights_sq;
157 
162  std::vector<std::vector<Real>> _off_diagonal_weights;
163 };
164 
165 
166 
167 // ------------------------------------------------------------
168 // SystemNorm inline methods
169 
170 inline
172  _norms(1, DISCRETE_L2), _weights(1, 1.0), _weights_sq(1, 1.0)
173 {
174 }
175 
176 
177 inline
179  _norms(1, t), _weights(1, 1.0), _weights_sq(1, 1.0)
180 {
181 }
182 
183 
184 inline
185 SystemNorm::SystemNorm(const std::vector<FEMNormType> & norms) :
186  _norms(norms), _weights(1, 1.0), _weights_sq(1, 1.0)
187 {
188  if (_norms.empty())
189  _norms.push_back(DISCRETE_L2);
190 }
191 
192 
193 inline
194 SystemNorm::SystemNorm(const std::vector<FEMNormType> & norms,
195  std::vector<Real> & weights) :
196  _norms(norms), _weights(weights), _weights_sq(_weights.size(), 0.0)
197 {
198  if (_norms.empty())
199  _norms.push_back(DISCRETE_L2);
200 
201  if (_weights.empty())
202  {
203  _weights.push_back(1.0);
204  _weights_sq.push_back(1.0);
205  }
206  else
207  for (std::size_t i=0; i != _weights.size(); ++i)
208  _weights_sq[i] = _weights[i] * _weights[i];
209 }
210 
211 inline
212 SystemNorm::SystemNorm(const std::vector<FEMNormType> & norms,
213  std::vector<std::vector<Real>> & weights):
214  _norms(norms),
215  _weights(weights.size()),
216  _weights_sq(weights.size()),
217  _off_diagonal_weights(weights)
218 {
219  if (_norms.empty())
220  _norms.push_back(DISCRETE_L2);
221 
222  if (_weights.empty())
223  {
224  _weights.push_back(1.0);
225  _weights_sq.push_back(1.0);
226  }
227  else
228  {
229  // Loop over the entries of the user provided matrix and store its entries in
230  // the _off_diagonal_weights or _diagonal_weights
231  for (std::size_t i=0; i!=_off_diagonal_weights.size(); ++i)
232  {
233  if (_off_diagonal_weights[i].size() > i)
234  {
235  _weights[i] = _off_diagonal_weights[i][i];
236  _off_diagonal_weights[i][i] = 0;
237  }
238  else
239  _weights[i] = 1.0;
240  }
241  for (std::size_t i=0; i != _weights.size(); ++i)
242  _weights_sq[i] = _weights[i] * _weights[i];
243  }
244 }
245 
246 inline
249 {
250 }
251 
252 
253 inline
255 {
256  libmesh_assert (!_norms.empty());
257 
258  if (_norms[0] == DISCRETE_L1 ||
259  _norms[0] == DISCRETE_L2 ||
260  _norms[0] == DISCRETE_L_INF)
261  return true;
262 
263  return false;
264 }
265 
266 
267 inline
268 FEMNormType SystemNorm::type(unsigned int var) const
269 {
270  libmesh_assert (!_norms.empty());
271 
272  std::size_t i = (var < _norms.size()) ? var : _norms.size() - 1;
273 
274  return _norms[i];
275 }
276 
277 
278 
279 inline
280 void SystemNorm::set_type(unsigned int var, const FEMNormType & t)
281 {
282  libmesh_assert (!_norms.empty());
283 
284  if (var >= _norms.size())
285  _norms.resize(var+1, t);
286 
287  _norms[var] = t;
288 }
289 
290 
291 inline
292 Real SystemNorm::weight(unsigned int var) const
293 {
294  libmesh_assert (!_weights.empty());
295 
296  return (var < _weights.size()) ? _weights[var] : 1.0;
297 }
298 
299 
300 inline
301 void SystemNorm::set_weight(unsigned int var, Real w)
302 {
303  libmesh_assert (!_weights.empty());
304 
305  if (var >= _weights.size())
306  {
307  _weights.resize(var+1, 1.0);
308  _weights_sq.resize(var+1, 1.0);
309  }
310 
311  _weights[var] = w;
312  _weights_sq[var] = w*w;
313 }
314 
315 inline
317  unsigned int j,
318  Real w)
319 {
320  libmesh_assert (!_weights.empty());
321 
322  if (i >= _off_diagonal_weights.size())
323  {
324  _off_diagonal_weights.resize(i+1);
325  }
326 
327  if (j >= _off_diagonal_weights[i].size())
328  {
329  _off_diagonal_weights[i].resize(j+1, 0.);
330  }
331 
332  _off_diagonal_weights[i][j] = w;
333 
334 }
335 
336 
337 inline
338 Real SystemNorm::weight_sq(unsigned int var) const
339 {
340  libmesh_assert (!_weights_sq.empty());
341 
342  return (var < _weights_sq.size()) ? _weights_sq[var] : 1.0;
343 }
344 
345 
346 inline
347 Real SystemNorm::calculate_norm(const std::vector<Real> & v1,
348  const std::vector<Real> & v2)
349 {
350  // The vectors are assumed to both be vectors of the (same number
351  // of) components
352  std::size_t vsize = v1.size();
353  libmesh_assert_equal_to (vsize, v2.size());
354 
355  // We'll support implicitly defining weights, but if the user sets
356  // more weights than he uses then something's probably wrong
357  std::size_t diagsize = this->_weights.size();
358  libmesh_assert_greater_equal (vsize, diagsize);
359 
360  // Initialize the variable val
361  Real val = 0.;
362 
363  // Loop over all the components of the system with explicit
364  // weights
365  for (std::size_t i = 0; i != diagsize; i++)
366  {
367  val += this->_weights[i] * v1[i] * v2[i];
368  }
369  // Loop over all the components of the system with implicit
370  // weights
371  for (std::size_t i = diagsize; i < vsize; i++)
372  {
373  val += v1[i] * v2[i];
374  }
375 
376  // Loop over the components of the system
377  std::size_t nrows = this->_off_diagonal_weights.size();
378  libmesh_assert_less_equal (vsize, nrows);
379 
380  for (std::size_t i = 0; i != nrows; i++)
381  {
382  std::size_t ncols = this->_off_diagonal_weights[i].size();
383  for (std::size_t j=0; j != ncols; j++)
384  {
385  // The diagonal weights here were set to zero in the
386  // constructor.
387  val += this->_off_diagonal_weights[i][j] * v1[i] * v2[j];
388  }
389  }
390 
391  return(val);
392 }
393 
394 inline
395 Real SystemNorm::calculate_norm(const std::vector<Real> & v1)
396 {
397  return this->calculate_norm(v1,v1);
398 }
399 
400 inline
402 {
403  std::size_t nrows = this->_off_diagonal_weights.size();
404 
405  // If any of the off-diagonal elements is not 0, then we are in the non-identity case
406  for (std::size_t i = 0; i != nrows; i++)
407  {
408  std::size_t ncols = this->_off_diagonal_weights[i].size();
409  for (std::size_t j = 0; j != ncols; j++)
410  {
411  if (_off_diagonal_weights[i][j] != 0)
412  {
413  return(false);
414  }
415  }
416  }
417 
418  // If any of the diagonal elements is not 1, then we are in the non-identity case
419  nrows = this->_weights.size();
420  for (std::size_t i = 0; i != nrows; i++)
421  if (_weights[i] != 1)
422  return(false);
423 
424  // If all the off-diagonals elements are 0, and diagonal elements 1, then we are in an identity case
425  return(true);
426 }
427 
428 } // namespace libMesh
429 
430 #endif // LIBMESH_SYSTEM_NORM_H
std::vector< FEMNormType > _norms
Definition: system_norm.h:153
Real weight(unsigned int var) const
Definition: system_norm.h:292
std::vector< Real > _weights_sq
Definition: system_norm.h:156
This class defines a norm/seminorm to be applied to a NumericVector which contains coefficients in a ...
Definition: system_norm.h:43
The libMesh namespace provides an interface to certain functionality in the library.
void set_off_diagonal_weight(unsigned int i, unsigned int j, Real w)
Sets the weight corresponding to the norm from the variable pair v1(var1) coming from v2(var2)...
Definition: system_norm.h:316
libmesh_assert(j)
void set_weight(unsigned int var, Real w)
Sets the weight corresponding to the norm in variable var.
Definition: system_norm.h:301
bool is_discrete() const
Definition: system_norm.h:254
Real weight_sq(unsigned int var) const
Definition: system_norm.h:338
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Real calculate_norm(const std::vector< Real > &v)
Definition: system_norm.h:395
std::vector< std::vector< Real > > _off_diagonal_weights
One more data structure needed to store the off diagonal components for the generalize SystemNorm cas...
Definition: system_norm.h:162
FEMNormType type(unsigned int var) const
Definition: system_norm.h:268
std::vector< Real > _weights
Definition: system_norm.h:155
void set_type(unsigned int var, const FEMNormType &t)
Sets the type of the norm in variable var.
Definition: system_norm.h:280
SystemNorm()
Constructor, defaults to DISCRETE_L2.
Definition: system_norm.h:171
FEMNormType
defines an enum for norms defined on vectors of finite element coefficients