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