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