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