MFEM  v4.1.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
complex_operator.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2020, 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 namespace mfem
22 {
23 
24 /** @brief Mimic the action of a complex operator using two real operators.
25 
26  This operator requires vectors that are twice the length of its internally
27  stored real operators, Op_Real and Op_Imag. It is assumed that these vectors
28  store the real part of the vector first followed by its imaginary part.
29 
30  ComplexOperator allows one to choose a convention upon construction, which
31  facilitates symmetry.
32 
33  If we let (y_r + i y_i) = (Op_r + i Op_i)(x_r + i x_i) then Matrix-vector
34  products are computed as:
35 
36  1. When Convention::HERMITIAN is used (default)
37  / y_r \ / Op_r -Op_i \ / x_r \
38  | | = | | | |
39  \ y_i / \ Op_i Op_r / \ x_i /
40 
41  2. When Convention::BLOCK_SYMMETRIC is used
42  / y_r \ / Op_r -Op_i \ / x_r \
43  | | = | | | |
44  \-y_i / \-Op_i -Op_r / \ x_i /
45  In other words, Matrix-vector products with Convention::BLOCK_SYMMETRIC
46  compute the complex conjugate of Op*x.
47 
48  Either convention can be used with a given complex operator, however, each
49  of them may be best suited for different classes of problems. For example:
50 
51  1. Convention::HERMITIAN, is well suited for Hermitian operators, i.e.,
52  operators where the real part is symmetric and the imaginary part of the
53  operator is anti-symmetric, hence the name. In such cases the resulting 2
54  x 2 operator will be symmetric.
55 
56  2. Convention::BLOCK_SYMMETRIC, is well suited for operators where both the
57  real and imaginary parts are symmetric. In this case the resulting 2 x 2
58  operator will also be symmetric. Such operators are common when studying
59  damped oscillations, for example.
60 
61  Note: this class cannot be used to represent a general nonlinear complex
62  operator.
63 */
64 class ComplexOperator : public Operator
65 {
66 public:
68  {
69  HERMITIAN, ///< Native convention for Hermitian operators
70  BLOCK_SYMMETRIC ///< Alternate convention for damping operators
71  };
72 
73  /** @brief Constructs complex operator object
74 
75  Note that either @p Op_Real or @p Op_Imag can be NULL, thus eliminating
76  their action (see documentation of the class for more details).
77 
78  In case ownership of the passed operator is transferred to this class
79  through @p ownReal and @p ownImag, the operators will be explicitly
80  destroyed at the end of the life of this object.
81  */
82  ComplexOperator(Operator * Op_Real, Operator * Op_Imag,
83  bool ownReal, bool ownImag,
84  Convention convention = HERMITIAN);
85 
86  virtual ~ComplexOperator();
87 
88  /** @brief Check for existence of real or imaginary part of the operator
89 
90  These methods do not check that the operators are non-zero but only that
91  the operators have been set.
92  */
93  bool hasRealPart() const { return Op_Real_ != NULL; }
94  bool hasImagPart() const { return Op_Imag_ != NULL; }
95 
96  /** @brief Real or imaginary part accessor methods
97 
98  The following accessor methods should only be called if the requested
99  part of the opertor is known to exist. This can be checked with
100  hasRealPart() or hasImagPart().
101  */
102  virtual Operator & real();
103  virtual Operator & imag();
104  virtual const Operator & real() const;
105  virtual const Operator & imag() const;
106 
107  virtual void Mult(const Vector &x, Vector &y) const;
108  virtual void MultTranspose(const Vector &x, Vector &y) const;
109 
110  virtual Type GetType() const { return Complex_Operator; }
111 
112 protected:
113  // Let this be hidden from the public interface since the implementation
114  // depends on internal members
115  void Mult(const Vector &x_r, const Vector &x_i,
116  Vector &y_r, Vector &y_i) const;
117  void MultTranspose(const Vector &x_r, const Vector &x_i,
118  Vector &y_r, Vector &y_i) const;
119 
120 protected:
123 
124  bool ownReal_;
125  bool ownImag_;
126 
128 
129  mutable Vector x_r_, x_i_, y_r_, y_i_;
130  mutable Vector *u_, *v_;
131 };
132 
133 
134 /** @brief Specialization of the ComplexOperator built from a pair of Sparse
135  Matrices.
136 
137  The purpose of this specialization is to construct a single SparseMatrix
138  object which is equivalent to the 2x2 block system that the ComplexOperator
139  mimics. The resulting SparseMatrix can then be passed along to solvers which
140  require access to the CSR matrix data such as SuperLU, STRUMPACK, or similar
141  sparse linear solvers.
142 
143  See ComplexOperator documentation above for more information.
144  */
146 {
147 public:
149  bool ownReal, bool ownImag,
150  Convention convention = HERMITIAN)
151  : ComplexOperator(A_Real, A_Imag, ownReal, ownImag, convention)
152  {}
153 
154  virtual SparseMatrix & real();
155  virtual SparseMatrix & imag();
156 
157  virtual const SparseMatrix & real() const;
158  virtual const SparseMatrix & imag() const;
159 
160  /** Combine the blocks making up this complex operator into a single
161  SparseMatrix. The resulting matrix can be passed to solvers which require
162  access to the matrix entries themselves, such as sparse direct solvers,
163  rather than simply the action of the opertor. Note that this combined
164  operator requires roughly twice the memory of the block structured
165  operator. */
166  SparseMatrix * GetSystemMatrix() const;
167 
168  virtual Type GetType() const { return MFEM_ComplexSparseMat; }
169 };
170 
171 #ifdef MFEM_USE_MPI
172 
173 /** @brief Specialization of the ComplexOperator built from a pair of
174  HypreParMatrices.
175 
176  The purpose of this specialization is to construct a single HypreParMatrix
177  object which is equivalent to the 2x2 block system that the ComplexOperator
178  mimics. The resulting HypreParMatrix can then be passed along to solvers
179  which require access to the CSR matrix data such as SuperLU, STRUMPACK, or
180  similar sparse linear solvers.
181 
182  See ComplexOperator documentation above for more information.
183  */
185 {
186 public:
188  bool ownReal, bool ownImag,
189  Convention convention = HERMITIAN);
190 
191  virtual HypreParMatrix & real();
192  virtual HypreParMatrix & imag();
193 
194  virtual const HypreParMatrix & real() const;
195  virtual const HypreParMatrix & imag() const;
196 
197  /** Combine the blocks making up this complex operator into a single
198  HypreParMatrix. The resulting matrix can be passed to solvers which
199  require access to the matrix entries themselves, such as sparse direct
200  solvers or Hypre preconditioners, rather than simply the action of the
201  opertor. Note that this combined operator requires roughly twice the
202  memory of the block structured operator. */
204 
205  virtual Type GetType() const { return Complex_Hypre_ParCSR; }
206 
207 private:
208  void getColStartStop(const HypreParMatrix * A_r,
209  const HypreParMatrix * A_i,
210  int & num_recv_procs,
211  HYPRE_Int *& offd_col_start_stop) const;
212 
213  MPI_Comm comm_;
214  int myid_;
215  int nranks_;
216 };
217 
218 #endif // MFEM_USE_MPI
219 
220 }
221 
222 #endif // MFEM_COMPLEX_OPERATOR
virtual Operator & real()
Real or imaginary part accessor methods.
virtual Type GetType() const
ComplexHypreParMatrix(HypreParMatrix *A_Real, HypreParMatrix *A_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
Mimic the action of a complex operator using two real operators.
ID for class ComplexHypreParMatrix.
Definition: operator.hpp:242
ComplexSparseMatrix(SparseMatrix *A_Real, SparseMatrix *A_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
Alternate convention for damping operators.
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.
Data type sparse matrix.
Definition: sparsemat.hpp:40
virtual Type GetType() const
virtual SparseMatrix & real()
Real or imaginary part accessor methods.
SparseMatrix * GetSystemMatrix() const
Type
Enumeration defining IDs for some classes derived from Operator.
Definition: operator.hpp:229
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Specialization of the ComplexOperator built from a pair of Sparse Matrices.
virtual Operator & imag()
Specialization of the ComplexOperator built from a pair of HypreParMatrices.
virtual SparseMatrix & imag()
Native convention for Hermitian operators.
virtual Type GetType() const
ID for class ComplexSparseMatrix.
Definition: operator.hpp:241
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 ...
Vector data type.
Definition: vector.hpp:48
HypreParMatrix * GetSystemMatrix() const
virtual HypreParMatrix & imag()
ID for class ComplexOperator.
Definition: operator.hpp:240
Abstract operator.
Definition: operator.hpp:24
Wrapper for hypre&#39;s ParCSR matrix class.
Definition: hypre.hpp:187
virtual HypreParMatrix & real()
Real or imaginary part accessor methods.