GEOSX
Arnoldi.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
7  * Copyright (c) 2018-2020 TotalEnergies
8  * Copyright (c) 2019- GEOSX Contributors
9  * All rights reserved
10  *
11  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
12  * ------------------------------------------------------------------------------------------------------------
13  */
14 
19 #ifndef GEOS_LINEARALGEBRA_UTILITIES_ARNOLDI_HPP_
20 #define GEOS_LINEARALGEBRA_UTILITIES_ARNOLDI_HPP_
21 
22 #include "denseLinearAlgebra/interfaces/blaslapack/BlasLapackLA.hpp"
24 
25 namespace geos
26 {
27 
35 template< typename VECTOR >
37 {
38  localIndex const numGlobalRows = LvArray::integerConversion< localIndex >( op.numGlobalRows() );
39  localIndex const numLocalRows = op.numLocalRows();
40  localIndex const mInternal = std::min( numGlobalRows, m );
41 
42  // Initialize data structure (Hessenberg matrix and Krylov subspace)
43  array2d< real64, MatrixLayout::ROW_MAJOR_PERM > H( mInternal+1, mInternal );
44  array1d< VECTOR > V( mInternal + 1 );
45 
46  // Initial unitary vector
47  V[0].create( numLocalRows, op.comm() );
48  V[0].set( 1.0 / sqrt( static_cast< real64 >( numGlobalRows ) ) );
49 
50  for( localIndex j = 0; j < mInternal; ++j )
51  {
52  // Apply operator
53  V[j+1].create( numLocalRows, op.comm() );
54  op.apply( V[j], V[j+1] );
55  // Arnoldi process
56  for( localIndex i = 0; i <= j; ++i )
57  {
58  H( i, j ) = V[i].dot( V[j+1] );
59  V[j+1].axpy( -H( i, j ), V[i] );
60  }
61  H( j+1, j ) = V[j+1].norm2();
62  V[j+1].scale( 1.0 / H( j+1, j ) );
63  }
64 
65  // Disregard the last entry and make the matrix square
66  // Note: this is ok since we are using ROW_MAJOR_PERM
67  H.resize( mInternal, mInternal );
68 
69  // Compute the eigenvalues
70  array1d< std::complex< real64 > > lambda( mInternal );
71  BlasLapackLA::matrixEigenvalues( H, lambda );
72 
73  // Find the largest eigenvalues
74  real64 lambdaMax = 0.0;
75  for( localIndex i = 0; i < mInternal; ++i )
76  {
77  lambdaMax = std::max( std::abs( lambda[i] ), lambdaMax );
78  }
79 
80  return lambdaMax;
81 }
82 
83 } // namespace geos
84 
85 #endif //GEOS_LINEARALGEBRA_UTILITIES_ARNOLDI_HPP_
Abstract base class for linear operators.
virtual globalIndex numGlobalRows() const =0
Get the number of global rows.
virtual localIndex numLocalRows() const =0
Get the number of local rows.
virtual void apply(Vector const &src, Vector &dst) const =0
Apply operator to a vector, dst = this(src).
virtual MPI_Comm comm() const =0
Get the MPI communicator the matrix was created with.
Array< T, 2, PERMUTATION > array2d
Alias for 2D array.
Definition: DataTypes.hpp:232
double real64
64-bit floating point type.
Definition: DataTypes.hpp:139
real64 ArnoldiLargestEigenvalue(LinearOperator< VECTOR > const &op, localIndex const m=4)
Function implementing the Arnoldi scheme to compute the largest eigenvalue.
Definition: Arnoldi.hpp:36
GEOSX_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
Definition: DataTypes.hpp:125
Array< T, 1 > array1d
Alias for 1D array.
Definition: DataTypes.hpp:216