OGS
LinAlg.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "LinAlg.h"
5
6// TODO reorder LinAlg function signatures?
7
8// Global PETScMatrix/PETScVector //////////////////////////////////////////
9#ifdef USE_PETSC
10
13
14namespace MathLib
15{
16namespace LinAlg
17{
18// Vector
19
24
25void set(PETScVector& x, PetscScalar const a)
26{
27 VecSet(x.getRawVector(), a);
28}
29
30void copy(PETScVector const& x, PETScVector& y)
31{
32 if (!y.getRawVector())
33 y.shallowCopy(x);
34 VecCopy(x.getRawVector(), y.getRawVector());
35}
36
37void scale(PETScVector& x, PetscScalar const a)
38{
39 VecScale(x.getRawVector(), a);
40}
41
42// y = a*y + X
43void aypx(PETScVector& y, PetscScalar const a, PETScVector const& x)
44{
45 // TODO check sizes
46 VecAYPX(y.getRawVector(), a, x.getRawVector());
47}
48
49// y = a*x + y
50void axpy(PETScVector& y, PetscScalar const a, PETScVector const& x)
51{
52 // TODO check sizes
53 VecAXPY(y.getRawVector(), a, x.getRawVector());
54}
55
56// y = a*x + b*y
57void axpby(PETScVector& y, PetscScalar const a, PetscScalar const b,
58 PETScVector const& x)
59{
60 // TODO check sizes
61 VecAXPBY(y.getRawVector(), a, b, x.getRawVector());
62}
63
64double dot(PETScVector const& a, PETScVector const& b)
65{
66 PetscScalar result;
67 VecDot(a.getRawVector(), b.getRawVector(), &result);
68 // PetscRealPart is a no-op for real builds and keeps this compiling for a
69 // complex-scalar PETSc build (where PetscScalar is std::complex).
70 return static_cast<double>(PetscRealPart(result));
71}
72
73// Explicit specialization
74// Computes w = x/y componentwise.
75// \note that VecPointwiseDivide avoids to divide by values that are
76// identically zero such as
77// for (int i=0; i<n; i++)
78// {
79// w[i] = y[i] == 0.0 ? 0.0 : x[i] / y[i];
80// }
81//
82template <>
84 PETScVector const& y)
85{
86 VecPointwiseDivide(w.getRawVector(), x.getRawVector(), y.getRawVector());
87}
88
89// Explicit specialization
90// Computes the Manhattan norm of x
91template <>
92double norm1(PETScVector const& x)
93{
94 PetscScalar norm = 0.;
95 VecNorm(x.getRawVector(), NORM_1, &norm);
96 return norm;
97}
98
99// Explicit specialization
100// Computes the Euclidean norm of x
101template <>
102double norm2(PETScVector const& x)
103{
104 PetscScalar norm = 0.;
105 VecNorm(x.getRawVector(), NORM_2, &norm);
106 return norm;
107}
108
109// Explicit specialization
110// Computes the Maximum norm of x
111template <>
112double normMax(PETScVector const& x)
113{
114 PetscScalar norm = 0.;
115 VecNorm(x.getRawVector(), NORM_INFINITY, &norm);
116 return norm;
117}
118
119// Matrix
120
121void copy(PETScMatrix const& A, PETScMatrix& B)
122{
123 B = A;
124}
125
126// A = a*A
127void scale(PETScMatrix& A, PetscScalar const a)
128{
129 MatScale(A.getRawMatrix(), a);
130}
131
132// Y = a*Y + X
133void aypx(PETScMatrix& Y, PetscScalar const a, PETScMatrix const& X)
134{
135 auto const pattern = nonzeroPatternStructure(X.getSparsityColumnIndices(),
137 MatAYPX(Y.getRawMatrix(), a, X.getRawMatrix(), pattern);
138}
139
140// Y = a*X + Y
141void axpy(PETScMatrix& Y, PetscScalar const a, PETScMatrix const& X)
142{
143 auto const pattern = nonzeroPatternStructure(X.getSparsityColumnIndices(),
145 MatAXPY(Y.getRawMatrix(), a, X.getRawMatrix(), pattern);
146}
147
148// Matrix and Vector
149
150// v3 = A*v1 + v2
151void matMult(PETScMatrix const& A, PETScVector const& x, PETScVector& y)
152{
153 // TODO check sizes
154 assert(&x != &y);
155 if (!y.getRawVector())
156 y.shallowCopy(x);
157 MatMult(A.getRawMatrix(), x.getRawVector(), y.getRawVector());
158}
159
160// v3 = A*v1 + v2
161void matMultAdd(PETScMatrix const& A, PETScVector const& v1,
162 PETScVector const& v2, PETScVector& v3)
163{
164 // TODO check sizes
165 assert(&v1 != &v3);
166 if (!v3.getRawVector())
167 v3.shallowCopy(v1);
168 MatMultAdd(A.getRawMatrix(), v1.getRawVector(), v2.getRawVector(),
169 v3.getRawVector());
170}
171
172void linearSysNormalize(PETScMatrix const& /*A*/, PETScMatrix& /*new_A*/,
173 PETScVector const& /*b*/, PETScVector& /*new_b*/)
174{
175 // The following block is deactivated, because there is no tests yet for the
176 // normalization operation in PETSc. This will be a task for later.
177 /*
178 assert(&A != &new_A);
179 assert(&b != &new_b);
180
181 PetscInt n_rows(0);
182 PetscInt n_cols(0);
183 MatGetSize(A.getRawMatrix(), &n_rows, &n_cols);
184 // only when A matrix is not square
185 if (n_rows != n_cols)
186 {
187 // new_b = A^T * b
188 MatMultTranspose(A.getRawMatrix(), b.getRawVector(),
189 new_b.getRawVector());
190 // new_A = A^T * A
191 MatTranspose(A.getRawMatrix(), MAT_INITIAL_MATRIX,
192 &(new_A.getRawMatrix()));
193 }
194 */
195 OGS_FATAL(
196 "Normalization operation is not implemented yet for PETSc library! "
197 "Program terminated.");
198}
199
201{
202 A.finalizeAssembly(MAT_FINAL_ASSEMBLY);
203}
204
209
210} // namespace LinAlg
211} // namespace MathLib
212
213// Sparse global EigenMatrix/EigenVector
214// //////////////////////////////////////////
215#else
216
219
220namespace MathLib
221{
222namespace LinAlg
223{
224// Vector
225
226void setLocalAccessibleVector(EigenVector const& /*x*/) {}
227
228void set(EigenVector& x, double const a)
229{
230 x.getRawVector().setConstant(a);
231}
232
233void copy(EigenVector const& x, EigenVector& y)
234{
235 y = x;
236}
237
238void scale(EigenVector& x, double const a)
239{
240 x.getRawVector() *= a;
241}
242
243// y = a*y + X
244void aypx(EigenVector& y, double const a, EigenVector const& x)
245{
246 // TODO: does that break anything?
247 y.getRawVector() = a * y.getRawVector() + x.getRawVector();
248}
249
250// y = a*x + y
251void axpy(EigenVector& y, double const a, EigenVector const& x)
252{
253 // TODO: does that break anything?
254 y.getRawVector() += a * x.getRawVector();
255}
256
257// y = a*x + b*y
258void axpby(EigenVector& y, double const a, double const b, EigenVector const& x)
259{
260 // TODO: does that break anything?
261 y.getRawVector() = a * x.getRawVector() + b * y.getRawVector();
262}
263
264double dot(EigenVector const& a, EigenVector const& b)
265{
266 // Make the operands locally accessible before reading their entries, so
267 // dot() is self-sufficient regardless of the caller. In this serial Eigen
268 // build there are no ghost entries, so these calls are no-ops; the PETSc
269 // overload obtains the equivalent guarantee from PETSc itself.
272 return a.getRawVector().dot(b.getRawVector());
273}
274
275// Explicit specialization
276// Computes w = x/y componentwise.
277template <>
278void componentwiseDivide(EigenVector& w, EigenVector const& x,
279 EigenVector const& y)
280{
281 w.getRawVector().noalias() = x.getRawVector().binaryExpr(
282 y.getRawVector(),
283 [](auto const x, auto const y) { return y == 0 ? 0.0 : x / y; });
284}
285
286// Explicit specialization
287// Computes the Manhattan norm of x
288template <>
289double norm1(EigenVector const& x)
290{
291 return x.getRawVector().lpNorm<1>();
292}
293
294// Explicit specialization
295// Euclidean norm
296template <>
297double norm2(EigenVector const& x)
298{
299 return x.getRawVector().norm();
300}
301
302// Explicit specialization
303// Computes the Maximum norm of x
304template <>
305double normMax(EigenVector const& x)
306{
307 return x.getRawVector().lpNorm<Eigen::Infinity>();
308}
309
310// Matrix
311
312void copy(EigenMatrix const& A, EigenMatrix& B)
313{
314 B = A;
315}
316
317// A = a*A
318void scale(EigenMatrix& A, double const a)
319{
320 // TODO: does that break anything?
321 A.getRawMatrix() *= a;
322}
323
324// Y = a*Y + X
325void aypx(EigenMatrix& Y, double const a, EigenMatrix const& X)
326{
327 // TODO: does that break anything?
328 Y.getRawMatrix() = a * Y.getRawMatrix() + X.getRawMatrix();
329}
330
331// Y = a*X + Y
332void axpy(EigenMatrix& Y, double const a, EigenMatrix const& X)
333{
334 // TODO: does that break anything?
335 Y.getRawMatrix() = a * X.getRawMatrix() + Y.getRawMatrix();
336}
337
338// Matrix and Vector
339
340// v3 = A*v1 + v2
341void matMult(EigenMatrix const& A, EigenVector const& x, EigenVector& y)
342{
343 assert(&x != &y);
344 y.getRawVector() = A.getRawMatrix() * x.getRawVector();
345}
346
347// v3 = A*v1 + v2
348void matMultAdd(EigenMatrix const& A, EigenVector const& v1,
349 EigenVector const& v2, EigenVector& v3)
350{
351 assert(&v1 != &v3);
352 // TODO: does that break anything?
353 v3.getRawVector() =
354 v2.getRawVector() + A.getRawMatrix() * v1.getRawVector();
355}
356
357void linearSysNormalize(EigenMatrix const& A, EigenMatrix& new_A,
358 EigenVector const& b, EigenVector& new_b)
359{
360 // make sure that new_A and new_b are not the same memory
361 assert(&A != &new_A);
362 assert(&b != &new_b);
363
364 if (A.getRawMatrix().rows() == A.getRawMatrix().cols())
365 {
366 WARN(
367 "The number of rows and columns are the same for the LHS matrix."
368 "Are you sure you still need to normalize the LHS matrix and RHS "
369 "vector? ");
370 }
371
372 new_b.getRawVector() = A.getRawMatrix().transpose() * b.getRawVector();
373 new_A.getRawMatrix() = A.getRawMatrix().transpose() * A.getRawMatrix();
374}
375
376void finalizeAssembly(EigenMatrix& x)
377{
378 x.getRawMatrix().makeCompressed();
379}
380
381void finalizeAssembly(EigenVector& /*x*/) {}
382
383} // namespace LinAlg
384
385} // namespace MathLib
386
387#endif
#define OGS_FATAL(...)
Definition Error.h:10
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
Wrapper class for PETSc matrix routines for matrix.
Definition PETScMatrix.h:23
Mat & getRawMatrix()
Get matrix reference.
Definition PETScMatrix.h:85
void finalizeAssembly(const MatAssemblyType asm_type=MAT_FINAL_ASSEMBLY)
Perform MPI collection of assembled entries in buffer.
Definition PETScMatrix.h:60
std::vector< PetscInt > const & getSparsityColumnIndices() const
Column indices cached at preallocation (empty on the fallback path).
Definition PETScMatrix.h:79
Wrapper class for PETSc vector.
Definition PETScVector.h:28
void finalizeAssembly()
Perform MPI collection of assembled entries in buffer.
void setLocalAccessibleVector() const
void shallowCopy(const PETScVector &v)
PETSc_Vec & getRawVector()
Exposes the underlying PETSc vector.
double norm(MatrixOrVector const &x, MathLib::VecNormType type)
Definition LinAlg.h:89
double dot(PETScVector const &a, PETScVector const &b)
Definition LinAlg.cpp:64
void linearSysNormalize(PETScMatrix const &, PETScMatrix &, PETScVector const &, PETScVector &)
Definition LinAlg.cpp:172
void finalizeAssembly(PETScMatrix &A)
Definition LinAlg.cpp:200
double norm1(PETScVector const &x)
Definition LinAlg.cpp:92
double normMax(PETScVector const &x)
Definition LinAlg.cpp:112
void copy(PETScVector const &x, PETScVector &y)
Definition LinAlg.cpp:30
void componentwiseDivide(PETScVector &w, PETScVector const &x, PETScVector const &y)
Definition LinAlg.cpp:83
void setLocalAccessibleVector(PETScVector const &x)
Definition LinAlg.cpp:20
void set(PETScVector &x, PetscScalar const a)
Definition LinAlg.cpp:25
void matMult(PETScMatrix const &A, PETScVector const &x, PETScVector &y)
Definition LinAlg.cpp:151
void matMultAdd(PETScMatrix const &A, PETScVector const &v1, PETScVector const &v2, PETScVector &v3)
Definition LinAlg.cpp:161
double norm2(PETScVector const &x)
Definition LinAlg.cpp:102
void scale(PETScVector &x, PetscScalar const a)
Definition LinAlg.cpp:37
void aypx(PETScVector &y, PetscScalar const a, PETScVector const &x)
Definition LinAlg.cpp:43
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
Definition LinAlg.cpp:50
void axpby(PETScVector &y, PetscScalar const a, PetscScalar const b, PETScVector const &x)
Definition LinAlg.cpp:57
MatStructure nonzeroPatternStructure(std::vector< PetscInt > const &col_a, std::vector< PetscInt > const &col_b)
double const GaussLegendre< 1 >::X[1]