PSCF v1.1
TridiagonalSolver.cpp
1/*
2* PSCF - Polymer Self-Consistent Field Theory
3*
4* Copyright 2016 - 2022, The Regents of the University of Minnesota
5* Distributed under the terms of the GNU General Public License.
6*/
7
8#include <string>
9#include <iostream>
10
11#include "TridiagonalSolver.h"
12
13namespace Pscf
14{
15
16 /*
17 * Constructor.
18 */
20 {}
21
22 /*
23 * Destructor.
24 */
26 {}
27
28 /*
29 * Allocate memory.
30 */
32 {
33 d_.allocate(n);
34 u_.allocate(n-1);
35 l_.allocate(n-1);
36 y_.allocate(n);
37 n_ = n;
38 }
39
40 /*
41 * Compute the LU decomposition of a symmetric matrix for later use.
42 */
44 const DArray<double>& u)
45 {
46 // Copy to local arrays
47 for (int i = 0; i < n_ - 1; ++i) {
48 d_[i] = d[i];
49 u_[i] = u[i];
50 l_[i] = u[i];
51 }
52 d_[n_ - 1] = d[n_ - 1];
53 gaussElimination();
54 }
55
56 /*
57 * Compute the LU decomposition of a symmetric matrix for later use.
58 */
60 const DArray<double>& u,
61 const DArray<double>& l)
62 {
63 // Copy to local arrays
64 for (int i = 0; i < n_ - 1; ++i) {
65 d_[i] = d[i];
66 u_[i] = u[i];
67 l_[i] = l[i];
68 }
69 d_[n_ - 1] = d[n_ - 1];
70 gaussElimination();
71 }
72
73 void TridiagonalSolver::gaussElimination()
74 {
75 // Gauss elimination
76 double q;
77 for (int i = 0; i < n_ - 1; ++i) {
78 q = l_[i]/d_[i];
79 d_[i+1] -= q*u_[i];
80 l_[i] = q;
81 }
82
83 #if 0
84 std::cout << "\n";
85 for (int i=0; i < n_; ++i) {
86 std::cout << " " << d_[i];
87 }
88 std::cout << "\n";
89 for (int i=0; i < n_ - 1; ++i) {
90 std::cout << " " << u_[i];
91 }
92 std::cout << "\n";
93 for (int i=0; i < n_ - 1; ++i) {
94 std::cout << " " << l_[i];
95 }
96 std::cout << "\n";
97 #endif
98 }
99
100 /*
101 * Compute matrix product Ab = x for x, given known vector b.
102 */
104 {
105 // Compute Ub = y
106 for (int i = 0; i < n_ - 1; ++i) {
107 y_[i] = d_[i]*b[i] + u_[i]*b[i+1];
108 }
109 y_[n_ - 1] = d_[n_ - 1]*b[n_ - 1];
110
111 // Compute Ly = x
112 x[0] = y_[0];
113 for (int i = 1; i < n_; ++i) {
114 x[i] = y_[i] + l_[i-1]*y_[i-1];
115 }
116 }
117
118 /*
119 * Solve Ax = b for x, given known b.
120 */
122 {
123 // Solve Ly = b by forward substitution.
124 y_[0] = b[0];
125 for (int i = 1; i < n_; ++i) {
126 y_[i] = b[i] - l_[i-1]*y_[i-1];
127 }
128
129 // Solve Ux = y by back substitution.
130 x[n_ - 1] = y_[n_ - 1]/d_[n_ - 1];
131 for (int i = n_ - 2; i >= 0; --i) {
132 x[i] = (y_[i] - u_[i]*x[i+1])/d_[i];
133 }
134 }
135
136}
void multiply(const DArray< double > &b, DArray< double > &x)
Evaluate product Ab = x for known b to compute x.
void computeLU(const DArray< double > &d, const DArray< double > &u)
Compute LU decomposition of a symmetric tridiagonal matrix.
void solve(const DArray< double > &b, DArray< double > &x)
Solve Ax = b for known b to compute x.
void allocate(int n)
Allocate memory.
Dynamically allocatable contiguous array template.
Definition: DArray.h:32
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:199
C++ namespace for polymer self-consistent field theory (PSCF).