MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
complex_operator.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_COMPLEX_OPERATOR
13#define MFEM_COMPLEX_OPERATOR
14
15#include "operator.hpp"
16#include "sparsemat.hpp"
17#ifdef MFEM_USE_MPI
18#include "hypre.hpp"
19#endif
20
21#ifdef MFEM_USE_SUITESPARSE
22#include <umfpack.h>
23#endif
24
25namespace mfem
26{
27#ifdef MFEM_USE_MPI
28class ComplexHypreParMatrix; // forward declaration
29#endif
30
31/** @brief Mimic the action of a complex operator using two real operators.
32
33 This operator requires vectors that are twice the length of its internally
34 stored real operators, Op_Real and Op_Imag. It is assumed that these vectors
35 store the real part of the vector first followed by its imaginary part.
36
37 ComplexOperator allows one to choose a convention upon construction, which
38 facilitates symmetry.
39
40 If we let (y_r + i y_i) = (Op_r + i Op_i)(x_r + i x_i) then Matrix-vector
41 products are computed as:
42
43 1. When Convention::HERMITIAN is used (default)
44 / y_r \ / Op_r -Op_i \ / x_r \
45 | | = | | | |
46 \ y_i / \ Op_i Op_r / \ x_i /
47
48 2. When Convention::BLOCK_SYMMETRIC is used
49 / y_r \ / Op_r -Op_i \ / x_r \
50 | | = | | | |
51 \-y_i / \-Op_i -Op_r / \ x_i /
52 In other words, Matrix-vector products with Convention::BLOCK_SYMMETRIC
53 compute the complex conjugate of Op*x.
54
55 Either convention can be used with a given complex operator, however, each
56 of them may be best suited for different classes of problems. For example:
57
58 1. Convention::HERMITIAN, is well suited for Hermitian operators, i.e.,
59 operators where the real part is symmetric and the imaginary part of the
60 operator is anti-symmetric, hence the name. In such cases the resulting 2
61 x 2 operator will be symmetric.
62
63 2. Convention::BLOCK_SYMMETRIC, is well suited for operators where both the
64 real and imaginary parts are symmetric. In this case the resulting 2 x 2
65 operator will also be symmetric. Such operators are common when studying
66 damped oscillations, for example.
67
68 Note: this class cannot be used to represent a general nonlinear complex
69 operator.
70*/
72{
73public:
75 {
76 HERMITIAN, ///< Native convention for Hermitian operators
77 BLOCK_SYMMETRIC ///< Alternate convention for damping operators
78 };
79
80 /** @brief Constructs complex operator object
81
82 Note that either @p Op_Real or @p Op_Imag can be NULL, thus eliminating
83 their action (see documentation of the class for more details).
84
85 In case ownership of the passed operator is transferred to this class
86 through @p ownReal and @p ownImag, the operators will be explicitly
87 destroyed at the end of the life of this object.
88 */
89 ComplexOperator(Operator * Op_Real, Operator * Op_Imag,
90 bool ownReal, bool ownImag,
91 Convention convention = HERMITIAN);
92
93 virtual ~ComplexOperator();
94
95 /** @brief Check for existence of real or imaginary part of the operator
96
97 These methods do not check that the operators are non-zero but only that
98 the operators have been set.
99 */
100 bool hasRealPart() const { return Op_Real_ != NULL; }
101 bool hasImagPart() const { return Op_Imag_ != NULL; }
102
103 /** @brief Real or imaginary part accessor methods
104
105 The following accessor methods should only be called if the requested
106 part of the operator is known to exist. This can be checked with
107 hasRealPart() or hasImagPart().
108 */
109 virtual Operator & real();
110 virtual Operator & imag();
111 virtual const Operator & real() const;
112 virtual const Operator & imag() const;
113
114 void Mult(const Vector &x, Vector &y) const override;
115 void MultTranspose(const Vector &x, Vector &y) const override;
116
117 using Operator::Mult;
119
120 virtual Type GetType() const { return Complex_Operator; }
121
123
124#ifdef MFEM_USE_MPI
125 /** @brief Return a newly allocated ComplexHypreParMatrix representation.
126
127 If the real and imaginary parts are HypreParMatrix objects, the returned
128 object borrows them and they must outlive the returned
129 ComplexHypreParMatrix. If they are BlockOperator objects with
130 HypreParMatrix blocks, they are first merged into monolithic matrices
131 owned by the returned ComplexHypreParMatrix.
132
133 The returned ComplexHypreParMatrix is owned by the caller, who is
134 responsible for deleting it. */
136#endif
137
138protected:
139 // Let this be hidden from the public interface since the implementation
140 // depends on internal members
141 void Mult(const Vector &x_r, const Vector &x_i,
142 Vector &y_r, Vector &y_i) const;
143 void MultTranspose(const Vector &x_r, const Vector &x_i,
144 Vector &y_r, Vector &y_i) const;
145
146protected:
149
152
154
156 mutable Vector *u_, *v_;
157};
158
159
160/** @brief Specialization of the ComplexOperator built from a pair of Sparse
161 Matrices.
162
163 The purpose of this specialization is to construct a single SparseMatrix
164 object which is equivalent to the 2x2 block system that the ComplexOperator
165 mimics. The resulting SparseMatrix can then be passed along to solvers which
166 require access to the CSR matrix data such as SuperLU, STRUMPACK, or similar
167 sparse linear solvers.
168
169 See ComplexOperator documentation above for more information.
170 */
172{
173public:
175 bool ownReal, bool ownImag,
176 Convention convention = HERMITIAN)
177 : ComplexOperator(A_Real, A_Imag, ownReal, ownImag, convention)
178 {}
179
180 SparseMatrix & real() override;
181 SparseMatrix & imag() override;
182
183 const SparseMatrix & real() const override;
184 const SparseMatrix & imag() const override;
185
186 /** Combine the blocks making up this complex operator into a single
187 SparseMatrix. The resulting matrix can be passed to solvers which require
188 access to the matrix entries themselves, such as sparse direct solvers,
189 rather than simply the action of the operator. Note that this combined
190 operator requires roughly twice the memory of the block structured
191 operator. */
193
194 Type GetType() const override { return MFEM_ComplexSparseMat; }
195};
196
197#ifdef MFEM_USE_SUITESPARSE
198/** @brief Interface with UMFPack solver specialized for ComplexSparseMatrix
199 This approach avoids forming a monolithic SparseMatrix which leads
200 to increased memory and flops
201 */
203{
204protected:
206 bool transa;
208
209 void *Numeric;
210 SuiteSparse_long *AI, *AJ;
211
212 void Init();
213
214public:
215 real_t Control[UMFPACK_CONTROL];
216 mutable real_t Info[UMFPACK_INFO];
217
218 /** @brief For larger matrices, if the solver fails, set the parameter @a
219 use_long_ints_ = true. */
220 ComplexUMFPackSolver(bool use_long_ints_ = false, bool transa_ = false)
221 : use_long_ints(use_long_ints_), transa(transa_) { Init(); }
222 /** @brief Factorize the given ComplexSparseMatrix using the defaults.
223 For larger matrices, if the solver fails, set the parameter
224 @a use_long_ints_ = true. */
225 ComplexUMFPackSolver(ComplexSparseMatrix &A, bool use_long_ints_ = false,
226 bool transa_ = false)
227 : use_long_ints(use_long_ints_), transa(transa_) { Init(); SetOperator(A); }
228
229 /** @brief Factorize the given Operator @a op which must be
230 a ComplexSparseMatrix.
231
232 The factorization uses the parameters set in the #Control data member.
233 @note This method calls SparseMatrix::SortColumnIndices()
234 for real and imag parts of the ComplexSparseMatrix,
235 modifying the matrices if the column indices are not already sorted. */
236 void SetOperator(const Operator &op) override;
237
238 // Set the print level field in the #Control data member.
239 void SetPrintLevel(int print_lvl) { Control[UMFPACK_PRL] = print_lvl; }
240
241 // This determines the action of MultTranspose (see below for details)
242 void SetTransposeSolve(bool transa_) { transa = transa_; }
243
244 /** @brief This is solving the system A x = b */
245 void Mult(const Vector &b, Vector &x) const override;
246
247 /** @brief
248 This is solving the system:
249 A^H x = b (when transa = false)
250 This is equivalent to solving the transpose block system for the
251 case of Convention = HERMITIAN
252 A^T x = b (when transa = true)
253 This is equivalent to solving the transpose block system for the
254 case of Convention = BLOCK_SYMMETRIC */
255 void MultTranspose(const Vector &b, Vector &x) const override;
256
257 virtual ~ComplexUMFPackSolver();
258};
259
260#endif
261
262#ifdef MFEM_USE_MPI
263
264/** @brief Specialization of the ComplexOperator built from a pair of
265 HypreParMatrices.
266
267 The purpose of this specialization is to construct a single HypreParMatrix
268 object which is equivalent to the 2x2 block system that the ComplexOperator
269 mimics. The resulting HypreParMatrix can then be passed along to solvers
270 which require access to the CSR matrix data such as SuperLU, STRUMPACK, or
271 similar sparse linear solvers.
272
273 See ComplexOperator documentation above for more information.
274 */
276{
277public:
279 bool ownReal, bool ownImag,
280 Convention convention = HERMITIAN);
281
282 HypreParMatrix & real() override;
283 HypreParMatrix & imag() override;
284
285 const HypreParMatrix & real() const override;
286 const HypreParMatrix & imag() const override;
287
288 /** Combine the blocks making up this complex operator into a single
289 HypreParMatrix. The resulting matrix can be passed to solvers which
290 require access to the matrix entries themselves, such as sparse direct
291 solvers or Hypre preconditioners, rather than simply the action of the
292 operator. Note that this combined operator requires roughly twice the
293 memory of the block structured operator. */
295
296 Type GetType() const override { return Complex_Hypre_ParCSR; }
297
298private:
299 void getColStartStop(const HypreParMatrix * A_r,
300 const HypreParMatrix * A_i,
301 int & num_recv_procs,
302 HYPRE_BigInt *& offd_col_start_stop) const;
303
304 MPI_Comm comm_;
305 int myid_;
306 int nranks_;
307};
308
309#endif // MFEM_USE_MPI
310
311}
312
313#endif // MFEM_COMPLEX_OPERATOR
Specialization of the ComplexOperator built from a pair of HypreParMatrices.
HypreParMatrix & imag() override
ComplexHypreParMatrix(HypreParMatrix *A_Real, HypreParMatrix *A_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
HypreParMatrix & real() override
Real or imaginary part accessor methods.
HypreParMatrix * GetSystemMatrix() const
Type GetType() const override
Mimic the action of a complex operator using two real operators.
virtual Operator & imag()
ComplexOperator(Operator *Op_Real, Operator *Op_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
Constructs complex operator object.
bool hasRealPart() const
Check for existence of real or imaginary part of the operator.
void MultTranspose(const Vector &x, Vector &y) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
ComplexHypreParMatrix * AsComplexHypreParMatrix() const
Return a newly allocated ComplexHypreParMatrix representation.
virtual Type GetType() const
virtual Operator & real()
Real or imaginary part accessor methods.
Convention GetConvention() const
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
@ HERMITIAN
Native convention for Hermitian operators.
@ BLOCK_SYMMETRIC
Alternate convention for damping operators.
Specialization of the ComplexOperator built from a pair of Sparse Matrices.
ComplexSparseMatrix(SparseMatrix *A_Real, SparseMatrix *A_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
SparseMatrix & imag() override
SparseMatrix * GetSystemMatrix() const
Type GetType() const override
SparseMatrix & real() override
Real or imaginary part accessor methods.
Interface with UMFPack solver specialized for ComplexSparseMatrix This approach avoids forming a mono...
void SetTransposeSolve(bool transa_)
ComplexUMFPackSolver(ComplexSparseMatrix &A, bool use_long_ints_=false, bool transa_=false)
Factorize the given ComplexSparseMatrix using the defaults. For larger matrices, if the solver fails,...
void MultTranspose(const Vector &b, Vector &x) const override
This is solving the system: A^H x = b (when transa = false) This is equivalent to solving the transpo...
void Mult(const Vector &b, Vector &x) const override
This is solving the system A x = b.
real_t Control[UMFPACK_CONTROL]
ComplexUMFPackSolver(bool use_long_ints_=false, bool transa_=false)
For larger matrices, if the solver fails, set the parameter use_long_ints_ = true.
void SetOperator(const Operator &op) override
Factorize the given Operator op which must be a ComplexSparseMatrix.
void SetPrintLevel(int print_lvl)
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
Abstract operator.
Definition operator.hpp:27
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Type
Enumeration defining IDs for some classes derived from Operator.
Definition operator.hpp:319
@ MFEM_ComplexSparseMat
ID for class ComplexSparseMatrix.
Definition operator.hpp:330
@ Complex_Operator
ID for class ComplexOperator.
Definition operator.hpp:329
@ Complex_Hypre_ParCSR
ID for class ComplexHypreParMatrix.
Definition operator.hpp:331
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition operator.hpp:102
Base class for solvers.
Definition operator.hpp:855
Data type sparse matrix.
Definition sparsemat.hpp:51
Vector data type.
Definition vector.hpp:82
HYPRE_Int HYPRE_BigInt
real_t b
Definition lissajous.cpp:42
float real_t
Definition config.hpp:46