imate
C++/CUDA Reference
c_lanczos_tridiagonalization.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright 2021, Siavash Ameli <sameli@berkeley.edu>
3  * SPDX-License-Identifier: BSD-3-Clause
4  * SPDX-FileType: SOURCE
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the license found in the LICENSE.txt file in the root
8  * directory of this source tree.
9  */
10 
11 
12 // =======
13 // Headers
14 // =======
15 
17 #include <cmath> // sqrt
18 #include "./c_orthogonalization.h" // cOrthogonalization
19 #include "../_c_basic_algebra/c_vector_operations.h" // cVectorOperations
20 
21 
22 // ============================
23 // c lanczos tridiagonalization
24 // ============================
25 
115 
116 template <typename DataType>
119  const DataType* v,
120  const LongIndexType n,
121  const IndexType m,
122  const DataType lanczos_tol,
123  const FlagType orthogonalize,
124  DataType* alpha,
125  DataType* beta)
126 {
127  // buffer_size is number of last orthogonal vectors to keep in the buffer V
128  IndexType buffer_size;
129  if (orthogonalize == 0 || orthogonalize == 1)
130  {
131  // At least two vectors must be stored in buffer for Lanczos recursion
132  buffer_size = 2;
133  }
134  else if ((orthogonalize < 0) ||
135  (orthogonalize > static_cast<FlagType>(m)))
136  {
137  // Using full reorthogonalization, keep all of the m vectors in buffer
138  buffer_size = m;
139  }
140  else
141  {
142  // Orthogonalize with less than m vectors (0 < orthogonalize < m)
143  buffer_size = orthogonalize;
144  }
145 
146  // Allocate 2D array (as 1D array, and coalesced row-wise) to store
147  // the last buffer_size of orthogonalized vectors of length n. New vectors
148  // are stored by cycling through the buffer to replace with old ones.
149  DataType* V = new DataType[n * buffer_size];
150 
151  // Allocate vector r
152  DataType* r = new DataType[n];
153 
154  // Copy v into r
156 
157  // Initial beta
158  DataType initial_beta = cVectorOperations<DataType>::euclidean_norm(r, n);
159 
160  // Declare iterators
161  IndexType j;
162  IndexType lanczos_size = 0;
163  IndexType num_ortho;
164 
165  // In the following, beta[j] means beta[j-1] in the Demmel text
166  for (j=0; j < m; ++j)
167  {
168  // Update the size of Lanczos tridiagonal matrix
169  ++lanczos_size;
170 
171  // Normalize r and copy to the j-th column of V
172  if (j == 0)
173  {
175  r, n, 1.0/initial_beta, &V[(j % buffer_size)*n]);
176  }
177  else
178  {
180  r, n, 1.0/beta[j-1], &V[(j % buffer_size)*n]);
181  }
182 
183  // Multiply A to the j-th column of V, write into r
184  A->dot(&V[(j % buffer_size)*n], r);
185 
186  // alpha[j] is V[:, j] dot r
188  &V[(j % buffer_size)*n], r, n);
189 
190  // Subtract V[:,j] * alpha[j] from r
192  &V[(j % buffer_size)*n], n, alpha[j], r);
193 
194  // Subtract V[:,j-1] * beta[j] from r
195  if (j > 0)
196  {
198  &V[((j-1) % buffer_size)*n], n, beta[j-1], r);
199  }
200 
201  // Gram-Schmidt process (full re-orthogonalization)
202  if (orthogonalize != 0)
203  {
204  // Find how many column vectors are filled so far in the buffer V
205  if (j < buffer_size)
206  {
207  num_ortho = j+1;
208  }
209  else
210  {
211  num_ortho = buffer_size;
212  }
213 
214  // Gram-Schmidt process
216  &V[0], n, buffer_size, j%buffer_size, num_ortho, r);
217  }
218 
219  // beta is norm of r
221 
222  // Exit criterion when the vector r is zero. If each component of a
223  // zero vector has the tolerance epsilon, (which is called lanczos_tol
224  // here), the tolerance of norm of r is epsilon times sqrt of n.
225  if (beta[j] < lanczos_tol * sqrt(n))
226  {
227  break;
228  }
229  }
230 
231  // Free dynamic memory
232  delete[] V;
233  delete[] r;
234 
235  return lanczos_size;
236 }
237 
238 
239 // ===============================
240 // Explicit template instantiation
241 // ===============================
242 
243 // lanczos tridiagonalization
246  const float* v,
247  const LongIndexType n,
248  const IndexType m,
249  const float lanczos_tol,
250  const FlagType orthogonalize,
251  float* alpha,
252  float* beta);
253 
256  const double* v,
257  const LongIndexType n,
258  const IndexType m,
259  const double lanczos_tol,
260  const FlagType orthogonalize,
261  double* alpha,
262  double* beta);
263 
266  const long double* v,
267  const LongIndexType n,
268  const IndexType m,
269  const long double lanczos_tol,
270  const FlagType orthogonalize,
271  long double* alpha,
272  long double* beta);
IndexType c_lanczos_tridiagonalization(cLinearOperator< DataType > *A, const DataType *v, const LongIndexType n, const IndexType m, const DataType lanczos_tol, const FlagType orthogonalize, DataType *alpha, DataType *beta)
Tri-diagonalizes matrix A to T using the start vector v. is the Lanczos degree, which will be the siz...
template IndexType c_lanczos_tridiagonalization< long double >(cLinearOperator< long double > *A, const long double *v, const LongIndexType n, const IndexType m, const long double lanczos_tol, const FlagType orthogonalize, long double *alpha, long double *beta)
template IndexType c_lanczos_tridiagonalization< double >(cLinearOperator< double > *A, const double *v, const LongIndexType n, const IndexType m, const double lanczos_tol, const FlagType orthogonalize, double *alpha, double *beta)
template IndexType c_lanczos_tridiagonalization< float >(cLinearOperator< float > *A, const float *v, const LongIndexType n, const IndexType m, const float lanczos_tol, const FlagType orthogonalize, float *alpha, float *beta)
Base class for linear operators. This class serves as interface for all derived classes.
virtual void dot(const DataType *vector, DataType *product)=0
static void gram_schmidt_process(const DataType *V, const LongIndexType vector_size, const IndexType num_vectors, const IndexType last_vector, const FlagType num_ortho, DataType *r)
Modified Gram-Schmidt orthogonalization process to orthogonalize the vector v against a subset of the...
static void copy_vector(const DataType *input_vector, const LongIndexType vector_size, DataType *output_vector)
Copies a vector to a new vector. Result is written in-place.
static void copy_scaled_vector(const DataType *input_vector, const LongIndexType vector_size, const DataType scale, DataType *output_vector)
Scales a vector and stores to a new vector.
static void subtract_scaled_vector(const DataType *input_vector, const LongIndexType vector_size, const DataType scale, DataType *output_vector)
Subtracts the scaled input vector from the output vector.
static DataType inner_product(const DataType *vector1, const DataType *vector2, const LongIndexType vector_size)
Computes Euclidean inner product of two vectors.
static DataType euclidean_norm(const DataType *vector, const LongIndexType vector_size)
Computes the Euclidean norm of a 1D array.
int LongIndexType
Definition: types.h:60
int FlagType
Definition: types.h:68
int IndexType
Definition: types.h:65