libMesh
system_norm.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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 // libMesh includes
20 #include "libmesh/system_norm.h"
21 #include "libmesh/enum_norm_type.h"
22 #include "libmesh/int_range.h"
23 
24 namespace libMesh
25 {
26 
28  _norms(1, DISCRETE_L2), _weights(1, 1.0), _weights_sq(1, 1.0)
29 {
30 }
31 
32 
34  _norms(1, t), _weights(1, 1.0), _weights_sq(1, 1.0)
35 {
36 }
37 
38 
39 SystemNorm::SystemNorm(const std::vector<FEMNormType> & norms) :
40  _norms(norms), _weights(1, 1.0), _weights_sq(1, 1.0)
41 {
42  if (_norms.empty())
43  _norms.push_back(DISCRETE_L2);
44 }
45 
46 
47 SystemNorm::SystemNorm(const std::vector<FEMNormType> & norms,
48  std::vector<Real> & weights) :
49  _norms(norms), _weights(weights), _weights_sq(_weights.size(), 0.0)
50 {
51  if (_norms.empty())
52  _norms.push_back(DISCRETE_L2);
53 
54  if (_weights.empty())
55  {
56  _weights.push_back(1.0);
57  _weights_sq.push_back(1.0);
58  }
59  else
60  for (auto i : index_range(_weights))
61  _weights_sq[i] = _weights[i] * _weights[i];
62 }
63 
64 SystemNorm::SystemNorm(const std::vector<FEMNormType> & norms,
65  std::vector<std::vector<Real>> & weights):
66  _norms(norms),
67  _weights(weights.size()),
68  _weights_sq(weights.size()),
69  _off_diagonal_weights(weights)
70 {
71  if (_norms.empty())
72  _norms.push_back(DISCRETE_L2);
73 
74  if (_weights.empty())
75  {
76  _weights.push_back(1.0);
77  _weights_sq.push_back(1.0);
78  }
79  else
80  {
81  // Loop over the entries of the user provided matrix and store its entries in
82  // the _off_diagonal_weights or _diagonal_weights
83  for (auto i : index_range(_off_diagonal_weights))
84  {
85  if (_off_diagonal_weights[i].size() > i)
86  {
88  _off_diagonal_weights[i][i] = 0;
89  }
90  else
91  _weights[i] = 1.0;
92  }
93  for (auto i : index_range(_weights))
94  _weights_sq[i] = _weights[i] * _weights[i];
95  }
96 }
97 
99 {
100  libmesh_assert (!_norms.empty());
101 
102  if (_norms[0] == DISCRETE_L1 ||
103  _norms[0] == DISCRETE_L2 ||
104  _norms[0] == DISCRETE_L_INF)
105  return true;
106 
107  return false;
108 }
109 
110 
111 FEMNormType SystemNorm::type(unsigned int var) const
112 {
113  libmesh_assert (!_norms.empty());
114 
115  std::size_t i = (var < _norms.size()) ? var : _norms.size() - 1;
116 
117  return _norms[i];
118 }
119 
120 
121 
122 void SystemNorm::set_type(unsigned int var, const FEMNormType & t)
123 {
124  libmesh_assert (!_norms.empty());
125 
126  if (var >= _norms.size())
127  _norms.resize(var+1, t);
128 
129  _norms[var] = t;
130 }
131 
132 
133 Real SystemNorm::weight(unsigned int var) const
134 {
135  libmesh_assert (!_weights.empty());
136 
137  return (var < _weights.size()) ? _weights[var] : 1.0;
138 }
139 
140 
141 void SystemNorm::set_weight(unsigned int var, Real w)
142 {
143  libmesh_assert (!_weights.empty());
144 
145  if (var >= _weights.size())
146  {
147  _weights.resize(var+1, 1.0);
148  _weights_sq.resize(var+1, 1.0);
149  }
150 
151  _weights[var] = w;
152  _weights_sq[var] = w*w;
153 }
154 
156  unsigned int j,
157  Real w)
158 {
159  libmesh_assert (!_weights.empty());
160 
161  if (i >= _off_diagonal_weights.size())
162  {
163  _off_diagonal_weights.resize(i+1);
164  }
165 
166  if (j >= _off_diagonal_weights[i].size())
167  {
168  _off_diagonal_weights[i].resize(j+1, 0.);
169  }
170 
171  _off_diagonal_weights[i][j] = w;
172 
173 }
174 
175 
176 Real SystemNorm::weight_sq(unsigned int var) const
177 {
178  libmesh_assert (!_weights_sq.empty());
179 
180  return (var < _weights_sq.size()) ? _weights_sq[var] : 1.0;
181 }
182 
183 
184 Real SystemNorm::calculate_norm(const std::vector<Real> & v1,
185  const std::vector<Real> & v2)
186 {
187  // The vectors are assumed to both be vectors of the (same number
188  // of) components
189  std::size_t vsize = v1.size();
190  libmesh_assert_equal_to (vsize, v2.size());
191 
192  // We'll support implicitly defining weights, but if the user sets
193  // more weights than he uses then something's probably wrong
194  std::size_t diagsize = this->_weights.size();
195  libmesh_assert_greater_equal (vsize, diagsize);
196 
197  // Initialize the variable val
198  Real val = 0.;
199 
200  // Loop over all the components of the system with explicit
201  // weights
202  for (std::size_t i = 0; i != diagsize; i++)
203  {
204  val += this->_weights[i] * v1[i] * v2[i];
205  }
206  // Loop over all the components of the system with implicit
207  // weights
208  for (std::size_t i = diagsize; i < vsize; i++)
209  {
210  val += v1[i] * v2[i];
211  }
212 
213  // Loop over the components of the system
214  std::size_t nrows = this->_off_diagonal_weights.size();
215  libmesh_assert_less_equal (vsize, nrows);
216 
217  for (std::size_t i = 0; i != nrows; i++)
218  {
219  std::size_t ncols = this->_off_diagonal_weights[i].size();
220  for (std::size_t j=0; j != ncols; j++)
221  {
222  // The diagonal weights here were set to zero in the
223  // constructor.
224  val += this->_off_diagonal_weights[i][j] * v1[i] * v2[j];
225  }
226  }
227 
228  return(val);
229 }
230 
231 Real SystemNorm::calculate_norm(const std::vector<Real> & v1)
232 {
233  return this->calculate_norm(v1,v1);
234 }
235 
237 {
238  std::size_t nrows = this->_off_diagonal_weights.size();
239 
240  // If any of the off-diagonal elements is not 0, then we are in the non-identity case
241  for (std::size_t i = 0; i != nrows; i++)
242  {
243  std::size_t ncols = this->_off_diagonal_weights[i].size();
244  for (std::size_t j = 0; j != ncols; j++)
245  {
246  if (_off_diagonal_weights[i][j] != 0)
247  {
248  return(false);
249  }
250  }
251  }
252 
253  // If any of the diagonal elements is not 1, then we are in the non-identity case
254  nrows = this->_weights.size();
255  for (std::size_t i = 0; i != nrows; i++)
256  if (_weights[i] != 1)
257  return(false);
258 
259  // If all the off-diagonals elements are 0, and diagonal elements 1, then we are in an identity case
260  return(true);
261 }
262 
263 }
libMesh::DISCRETE_L_INF
Definition: enum_norm_type.h:54
libMesh::SystemNorm::set_off_diagonal_weight
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.C:155
libMesh::DISCRETE_L2
Definition: enum_norm_type.h:53
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::SystemNorm::is_identity
bool is_identity()
Definition: system_norm.C:236
libMesh::SystemNorm::weight_sq
Real weight_sq(unsigned int var) const
Definition: system_norm.C:176
libMesh::SystemNorm::_weights_sq
std::vector< Real > _weights_sq
Definition: system_norm.h:169
libMesh::SystemNorm::_weights
std::vector< Real > _weights
Definition: system_norm.h:168
libMesh::SystemNorm::weight
Real weight(unsigned int var) const
Definition: system_norm.C:133
libMesh::SystemNorm::type
FEMNormType type(unsigned int var) const
Definition: system_norm.C:111
libMesh::SystemNorm::is_discrete
bool is_discrete() const
Definition: system_norm.C:98
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::FEMNormType
FEMNormType
Definition: enum_norm_type.h:34
libMesh::SystemNorm::SystemNorm
SystemNorm()
Constructor, defaults to DISCRETE_L2.
Definition: system_norm.C:27
libMesh::SystemNorm::set_type
void set_type(unsigned int var, const FEMNormType &t)
Sets the type of the norm in variable var.
Definition: system_norm.C:122
libMesh::SystemNorm::_off_diagonal_weights
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:175
libMesh::DISCRETE_L1
Definition: enum_norm_type.h:52
libMesh::SystemNorm::calculate_norm
Real calculate_norm(const std::vector< Real > &v)
Definition: system_norm.C:231
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::SystemNorm::set_weight
void set_weight(unsigned int var, Real w)
Sets the weight corresponding to the norm in variable var.
Definition: system_norm.C:141
libMesh::SystemNorm::_norms
std::vector< FEMNormType > _norms
Definition: system_norm.h:166