libMesh
Loading...
Searching...
No Matches
system_norm.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
24namespace 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
39SystemNorm::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
47SystemNorm::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
65SystemNorm::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
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 ||
106 return true;
107
108 return false;
109}
110
111
112FEMNormType 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
123void 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
134Real 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
142void 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
177Real 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
185Real 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
232Real 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}
bool is_discrete() const
Definition system_norm.C:99
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...
std::vector< FEMNormType > _norms
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...
std::vector< Real > _weights
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).
FEMNormType type(unsigned int var) const
SystemNorm()
Constructor, defaults to DISCRETE_L2 with weight of 1.0.
Definition system_norm.C:27
std::vector< std::vector< Real > > _off_diagonal_weights
One more data structure needed to store the off diagonal components for the generalize SystemNorm cas...
Real calculate_norm(const std::vector< Real > &v)
std::vector< Real > _weights_sq
Real weight(unsigned int var) const
Real weight_sq(unsigned int var) const
The libMesh namespace provides an interface to certain functionality in the library.
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:153
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real