# SVD_BASIS Extract singular vectors from data

SVD_BASIS is a FORTRAN90 program which applies the singular value decomposition to a set of data vectors, to extract the leading "modes" of the data.

This procedure, originally devised by Karl Pearson, has arisen repeatedly in a variety of fields, and hence is known under various names, including:

• the Hotelling transform;
• the discrete Karhunen-Loeve transform (KLT)
• Principal Component Analysis (PCA)
• Principal Orthogonal Direction (POD)
• Proper Orthogonal Decomposition (POD)
• Singular Value Decomposition (SVD)

This program is intended as an intermediate application, in the following situation:

1. a "high fidelity" or "high resolution" PDE solver is used to determine many (say N = 500) solutions of a discretized PDE at various times, or parameter values. Each solution may be regarded as an M vector. Typically, each solution involves an M by M linear system, greatly reduced in complexity because of bandedness or sparsity.
2. This program is applied to extract L dominant modes from the N solutions. This is done using the singular value decomposition of the M by N matrix, each of whose columns is one of the original solution vectors.
3. a "reduced order model" program may then attempt to solve a discretized version of the PDE, using the L dominant modes as basis vectors. Typically, this means that a dense L byL linear system will be involved.

Thus, the program might read in 500 files, and write out 5 or 10 files of the corresponding size and "shape", representing the dominant solution modes.

The optional normalization step involves computing the average of all the solution vectors and subtracting that average from each solution. In this case, the average vector is treated as a special "mode 0", and also written out to a file.

To compute the singular value decomposition, we first construct the M by N matrix A using individual solution vectors as columns:

A = [ X1 | X2 | ... | XN ]

The singular value decomposition has the form:

A = U * S * V'
and is determined using the DGESVD routine from the linear algebra package LAPACK. The leading L columns of the orthogonal M by M matrix U, associated with the largest singular values S, are chosen to form the basis.

In most PDE's, the solution vector has some structure; perhaps there are 100 nodes, and at each node the solution has perhaps 4 components (horizontal and vertical velocity, pressure, and temperature, say). While the solution is therefore a vector of length 400, it's more natural to think of it as a sort of table of 100 items, each with 4 components. You can use that idea to organize your solution data files; in other words, your data files can each have 100 lines, containing 4 values on each line. As long as every line has the same number of values, and every data file has the same form, the program can figure out what's going on.

The program assumes that each solution vector is stored in a separate data file and that the files are numbered consecutively, such as data01.txt, data02,txt, ... In a data file, comments (beginning with '#") and blank lines are allowed. Except for comment lines, each line of the file is assumed to represent all the component values of the solution at a particular node.

Here, for instance, is a tiny data file for a problem with just 3 nodes, and 4 solution components at each node:

```      #  This is solution file number 1
#
1   2   3   4
5   6   7   8
9  10  11  12
```

The program is interactive, but requires only a very small amount of input:

• L, the number of basis vectors to be extracted from the data;
• the name of the first input data file in the first set.
• the name of the first input data file in the second set, if any. (you are allowed to define a master data set composed of several groups of files, each consisting of a sequence of consecutive file names)
• a BLANK line, when there are no more sets of data to be added.
• "Y" if the vectors should be averaged, the average subtracted from all vectors, and the average written out as an extra "mode 0" vector;
• "Y" if the output files may include some initial comment lines, which will be indicated by initial "#" characters.

The program computes L basis vectors, and writes each one to a separate file, starting with svd_001.txt, svd_002.txt and so on. The basis vectors are written with the same component and node structure that was encountered on the solution files. Each vector will have unit Euclidean norm.

### Languages:

SVD_BASIS is available in a C++ version and a FORTRAN90 version and a MATLAB version.

### Related Data and Programs:

BRAIN_SENSOR_POD, a MATLAB program which applies the method of Proper Orthogonal Decomposition to seek underlying patterns in sets of 40 sensor readings of brain activity.

BURGERS, a dataset which contains 40 successive solutions to the Burgers equation. This data can be analyzed using SVD_BASIS.

CVT_BASIS, a FORTRAN90 program which uses discrete Centroidal Voronoi Tessellation (CVT) techniques to produce a small set of basis vectors that are good cluster centers for a large set of data vectors;

LAPACK_EXAMPLES, a FORTRAN90 program which demonstrates the use of the LAPACK linear algebra library.

POD_BASIS_FLOW, a FORTRAN90 program which is based on the same algorithm used by SVD_BASIS, but specialized to handle solution data from a particular set of fluid flow problems.

SVD_BASIS_WEIGHT, a FORTRAN90 program which is similar to SVD_BASIS, but which allows the user to assign weights to each data vector.

SVD_DEMO, a FORTRAN90 program which demonstrates the singular value decomposition for a simple example.

SVD_SNOWFALL, a FORTRAN90 program which reads a file containing historical snowfall data and analyzes the data with the Singular Value Decomposition (SVD), and plots created by GNUPLOT.

SVD_TRUNCATED, a FORTRAN90 program which demonstrates the computation of the reduced or truncated Singular Value Decomposition (SVD) that is useful for cases when one dimension of the matrix is much smaller than the other.

### Reference:

1. Edward Anderson, Zhaojun Bai, Christian Bischof, Susan Blackford, James Demmel, Jack Dongarra, Jeremy Du Croz, Anne Greenbaum, Sven Hammarling, Alan McKenney, Danny Sorensen,
LAPACK User's Guide,
Third Edition,
SIAM, 1999,
ISBN: 0898714478,
LC: QA76.73.F25L36
2. Gal Berkooz, Philip Holmes, John Lumley,
The proper orthogonal decomposition in the analysis of turbulent flows,
Annual Review of Fluid Mechanics,
Volume 25, 1993, pages 539-575.
3. John Burkardt, Max Gunzburger, Hyung-Chun Lee,
Centroidal Voronoi Tessellation-Based Reduced-Order Modelling of Complex Systems,
SIAM Journal on Scientific Computing,
Volume 28, Number 2, 2006, pages 459-484.
4. Lawrence Sirovich,
Turbulence and the dynamics of coherent structures, Parts I-III,
Quarterly of Applied Mathematics,
Volume 45, Number 3, 1987, pages 561-590.

### Examples and Tests:

The user's input, and the program's output are here:

The input data consists of 5 files:

The output data consists of 4 files, the first containing the average, and the next three containing the SVD basis vectors:

### List of Routines:

• MAIN is the main program for SVD_BASIS.
• BASIS_WRITE writes a basis vector to a file.
• CH_CAP capitalizes a single character.
• CH_EQI is a case insensitive comparison of two characters for equality.
• CH_IS_DIGIT is TRUE if a character is a decimal digit.
• CH_TO_DIGIT returns the integer value of a base 10 digit.
• DIGIT_INC increments a decimal digit.
• DIGIT_TO_CH returns the character representation of a decimal digit.
• FILE_COLUMN_COUNT counts the number of columns in the first line of a file.
• FILE_EXIST reports whether a file exists.
• FILE_NAME_INC_NOWRAP increments a partially numeric filename.
• FILE_ROW_COUNT counts the number of row records in a file.
• GET_UNIT returns a free FORTRAN unit number.
• I4_INPUT prints a prompt string and reads an I4 from the user.
• R8MAT_PRINT prints an R8MAT.
• R8MAT_PRINT_SOME prints some of an R8MAT.
• S_INPUT prints a prompt string and reads a string from the user.
• S_TO_I4 reads an I4 from a string.
• S_TO_R8 reads an R8 from a string.
• S_TO_R8VEC reads an R8VEC from a string.
• S_WORD_COUNT counts the number of "words" in a string.
• SINGULAR_VECTORS computes the desired singular values.
• TIMESTAMP prints the current YMDHMS date as a time stamp.

You can go up one level to the FORTRAN90 source codes.

Last revised on 22 November 2011.