OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
LU.hpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45/*=========================================================================
46
47 Program: Visualization Toolkit
48 Module: Excerpted from vtkMath.cxx
49
50 Copyright (c) 1993-2015 Ken Martin, Will Schroeder, Bill Lorensen
51 All rights reserved.
52
53 Redistribution and use in source and binary forms, with or without
54 modification, are permitted provided that the following conditions are met:
55
56 * Redistributions of source code must retain the above copyright notice,
57 this list of conditions and the following disclaimer.
58
59 * Redistributions in binary form must reproduce the above copyright notice,
60 this list of conditions and the following disclaimer in the documentation
61 and/or other materials provided with the distribution.
62
63 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
64 of any contributors may be used to endorse or promote products derived
65 from this software without specific prior written permission.
66
67 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
68 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
69 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
70 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
71 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
72 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
73 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
74 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
75 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
76 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
77
78 =========================================================================*/
79#ifndef MATH_LU_HPP
80#define MATH_LU_HPP
81
82#include <iostream>
83#include <limits>
84
85namespace OpenMD {
86
87 constexpr double SMALL_NUMBER = 1.0e-12;
88 constexpr int MAX_SCRATCH_ARRAY_SIZE = 10;
89
90 /**
91 * Invert input square matrix A into matrix AI.
92 * @param A input square matrix
93 * @param AI output square matrix
94 * @return true if inverse is computed, otherwise return false
95 * @note A is modified during the inversion
96 */
97 template<class MatrixType>
98 bool invertMatrix(MatrixType& A, MatrixType& AI) {
99 using Real = typename MatrixType::ElemType;
100
101 if (A.getNRow() != A.getNCol() || A.getNRow() != AI.getNRow() ||
102 A.getNCol() != AI.getNCol()) {
103 return false;
104 }
105
106 int size = A.getNRow();
107
108 // Check on allocation of working vectors
109 //
110 int iScratch[MAX_SCRATCH_ARRAY_SIZE];
111 int* index = (size <= MAX_SCRATCH_ARRAY_SIZE ? iScratch : new int[size]);
112 Real dScratch[MAX_SCRATCH_ARRAY_SIZE];
113 Real* column = (size <= MAX_SCRATCH_ARRAY_SIZE ? dScratch : new Real[size]);
114
115 bool retVal = invertMatrix(A, AI, size, index, column);
116
117 if (size > MAX_SCRATCH_ARRAY_SIZE) {
118 delete[] index;
119 delete[] column;
120 }
121 return retVal;
122 }
123
124 /**
125 * Invert input square matrix A into matrix AI (Thread safe versions).
126 * @param A input square matrix
127 * @param AI output square matrix
128 * @param size size of the matrix and temporary arrays
129 * @param tmp1Size temporary array
130 * @param tmp2Size temporary array
131 * @return true if inverse is computed, otherwise return false
132 * @note A is modified during the inversion.
133 */
134 template<class MatrixType>
135 bool invertMatrix(MatrixType& A, MatrixType& AI, unsigned int size,
136 int* tmp1Size,
137 typename MatrixType::ElemPoinerType tmp2Size) {
138 if (A.getNRow() != A.getNCol() || A.getNRow() != AI.getNRow() ||
139 A.getNCol() != AI.getNCol() || A.getNRow() != size) {
140 return false;
141 }
142
143 unsigned int i, j;
144
145 //
146 // Factor matrix; then begin solving for inverse one column at a time.
147 // Note: tmp1Size returned value is used later, tmp2Size is just working
148 // memory whose values are not used in LUSolveLinearSystem
149 //
150 if (LUFactorLinearSystem(A, tmp1Size, size, tmp2Size) == 0) {
151 return false;
152 }
153
154 for (j = 0; j < size; ++j) {
155 for (i = 0; i < size; ++i) {
156 tmp2Size[i] = 0.0;
157 }
158 tmp2Size[j] = 1.0;
159
160 LUSolveLinearSystem(A, tmp1Size, tmp2Size, size);
161
162 for (i = 0; i < size; i++) {
163 AI(i, j) = tmp2Size[i];
164 }
165 }
166
167 return true;
168 }
169
170 /**
171 * Factor linear equations Ax = b using LU decompostion A = LU where L is
172 * lower triangular matrix and U is upper triangular matrix.
173 * @param A input square matrix
174 * @param index pivot indices
175 * @param size size of the matrix and temporary arrays
176 * @param tmpSize temporary array
177 * @return true if inverse is computed, otherwise return false
178 * @note A is modified during the inversion.
179 */
180 template<class MatrixType>
181 int LUFactorLinearSystem(MatrixType& A, int* index, int size,
182 typename MatrixType::ElemPoinerType tmpSize) {
183 using Real = typename MatrixType::ElemType;
184
185 int i, j, k;
186 int maxI = 0;
187 Real largest, temp1, temp2, sum;
188
189 //
190 // Loop over rows to get implicit scaling information
191 //
192 for (i = 0; i < size; ++i) {
193 for (largest = 0.0, j = 0; j < size; ++j) {
194 if ((temp2 = std::abs(A(i, j))) > largest) { largest = temp2; }
195 }
196
197 if (largest == 0.0) {
198 std::cerr << "Unable to factor linear system";
199 return 0;
200 }
201 tmpSize[i] = 1.0 / largest;
202 }
203 //
204 // Loop over all columns using Crout's method
205 //
206 for (j = 0; j < size; ++j) {
207 for (i = 0; i < j; ++i) {
208 sum = A(i, j);
209 for (k = 0; k < i; ++k) {
210 sum -= A(i, k) * A(k, j);
211 }
212 A(i, j) = sum;
213 }
214 //
215 // Begin search for largest pivot element
216 //
217 for (largest = 0.0, i = j; i < size; ++i) {
218 sum = A(i, j);
219 for (k = 0; k < j; ++k) {
220 sum -= A(i, k) * A(k, j);
221 }
222 A(i, j) = sum;
223
224 if ((temp1 = tmpSize[i] * std::abs(sum)) >= largest) {
225 largest = temp1;
226 maxI = i;
227 }
228 }
229 //
230 // Check for row interchange
231 //
232 if (j != maxI) {
233 for (k = 0; k < size; ++k) {
234 std::swap(A(maxI, k), A(j, k));
235 }
236 tmpSize[maxI] = tmpSize[j];
237 }
238 //
239 // Divide by pivot element and perform elimination
240 //
241 index[j] = maxI;
242
243 if (std::abs(A(j, j)) <= SMALL_NUMBER) {
244 std::cerr << "Unable to factor linear system";
245 return false;
246 }
247
248 if (j != (size - 1)) {
249 temp1 = 1.0 / A(j, j);
250 for (i = j + 1; i < size; ++i) {
251 A(i, j) *= temp1;
252 }
253 }
254 }
255
256 return 1;
257 }
258
259 /**
260 * Solve linear equations Ax = b using LU decompostion A = LU where L is
261 * lower triangular matrix and U is upper triangular matrix.
262 * @param A input square matrix
263 * @param index pivot indices
264 * @param x vector
265 * @param size size of the matrix and temporary arrays
266 * @return true if inverse is computed, otherwise return false
267 * @note A=LU and index[] are generated from method LUFactorLinearSystem).
268 * Also, solution vector is written directly over input load vector.
269 */
270 template<class MatrixType>
271 void LUSolveLinearSystem(MatrixType& A, int* index,
272 typename MatrixType::ElemPoinerType x, int size) {
273 using Real = typename MatrixType::ElemType;
274
275 int i, j, ii, idx;
276 Real sum;
277 //
278 // Proceed with forward and backsubstitution for L and U
279 // matrices. First, forward substitution.
280 //
281 for (ii = -1, i = 0; i < size; ++i) {
282 idx = index[i];
283 sum = x[idx];
284 x[idx] = x[i];
285
286 if (ii >= 0) {
287 for (j = ii; j <= (i - 1); ++j) {
288 sum -= A(i, j) * x[j];
289 }
290 } else if (sum != 0.0) {
291 ii = i;
292 }
293
294 x[i] = sum;
295 }
296 //
297 // Now, back substitution
298 //
299 for (i = size - 1; i >= 0; i--) {
300 sum = x[i];
301 for (j = i + 1; j < size; ++j) {
302 sum -= A(i, j) * x[j];
303 }
304 x[i] = sum / A(i, i);
305 }
306 }
307} // namespace OpenMD
308
309#endif
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
void LUSolveLinearSystem(MatrixType &A, int *index, typename MatrixType::ElemPoinerType x, int size)
Solve linear equations Ax = b using LU decompostion A = LU where L is lower triangular matrix and U i...
Definition LU.hpp:271
int LUFactorLinearSystem(MatrixType &A, int *index, int size, typename MatrixType::ElemPoinerType tmpSize)
Factor linear equations Ax = b using LU decompostion A = LU where L is lower triangular matrix and U ...
Definition LU.hpp:181
bool invertMatrix(MatrixType &A, MatrixType &AI)
Invert input square matrix A into matrix AI.
Definition LU.hpp:98