imate
C++/CUDA Reference
Loading...
Searching...
No Matches
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> // std::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
116template <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 re-orthogonalization, 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, static_cast<DataType>(1.0)/initial_beta,
176 &V[(j % buffer_size)*n]);
177 }
178 else
179 {
181 r, n, static_cast<DataType>(1.0)/beta[j-1],
182 &V[(j % buffer_size)*n]);
183 }
184
185 // Multiply A to the j-th column of V, write into r
186 A->dot(&V[(j % buffer_size)*n], r);
187
188 // alpha[j] is V[:, j] dot r
190 &V[(j % buffer_size)*n], r, n);
191
192 // Subtract V[:,j] * alpha[j] from r
194 &V[(j % buffer_size)*n], n, alpha[j], r);
195
196 // Subtract V[:,j-1] * beta[j] from r
197 if (j > 0)
198 {
200 &V[((j-1) % buffer_size)*n], n, beta[j-1], r);
201 }
202
203 // Gram-Schmidt process (full re-orthogonalization)
204 if (orthogonalize != 0)
205 {
206 // Find how many column vectors are filled so far in the buffer V
207 if (j < buffer_size)
208 {
209 num_ortho = j+1;
210 }
211 else
212 {
213 num_ortho = buffer_size;
214 }
215
216 // Gram-Schmidt process
218 &V[0], n, buffer_size, j%buffer_size, num_ortho, r);
219 }
220
221 // beta is norm of r
223
224 // Exit criterion when the vector r is zero. If each component of a
225 // zero vector has the tolerance epsilon, (which is called lanczos_tol
226 // here), the tolerance of norm of r is epsilon times sqrt of n.
227 if (beta[j] < lanczos_tol * static_cast<DataType>(std::sqrt(n)))
228 {
229 break;
230 }
231 }
232
233 // Free dynamic memory
234 delete[] V;
235 delete[] r;
236
237 return lanczos_size;
238}
239
240
241// ===============================
242// Explicit template instantiation
243// ===============================
244
245// lanczos tridiagonalization
248 const float* v,
249 const LongIndexType n,
250 const IndexType m,
251 const float lanczos_tol,
252 const FlagType orthogonalize,
253 float* alpha,
254 float* beta);
255
258 const double* v,
259 const LongIndexType n,
260 const IndexType m,
261 const double lanczos_tol,
262 const FlagType orthogonalize,
263 double* alpha,
264 double* beta);
265
268 const long double* v,
269 const LongIndexType n,
270 const IndexType m,
271 const long double lanczos_tol,
272 const FlagType orthogonalize,
273 long double* alpha,
274 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_scaled_vector(const DataType *RESTRICT input_vector, const LongIndexType vector_size, const DataType scale, DataType *RESTRICT output_vector)
Scales a vector and stores to a new vector.
static DataType inner_product(const DataType *RESTRICT vector1, const DataType *RESTRICT vector2, const LongIndexType vector_size)
Computes Euclidean inner product of two vectors.
static void copy_vector(const DataType *RESTRICT input_vector, const LongIndexType vector_size, DataType *RESTRICT output_vector)
Copies a vector to a new vector. Result is written in-place.
static void subtract_scaled_vector(const DataType *RESTRICT input_vector, const LongIndexType vector_size, const DataType scale, DataType *RESTRICT output_vector)
Subtracts the scaled input vector from the output vector.
static DataType euclidean_norm(const DataType *RESTRICT 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