OpenMD
3.2
Molecular Dynamics in the Open
Toggle main menu visibility
Loading...
Searching...
No Matches
LapackLinearAlgebra.hpp
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2004-present, The University of Notre Dame. All rights
3
* reserved. (BSD 3-clause; full text omitted in this sketch.)
4
*
5
* SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
6
* research, please cite:
7
* [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
8
*/
9
10
/*! \file math/LapackLinearAlgebra.hpp
11
\brief LAPACK-backed fast paths for the dynamic, double-precision dense
12
routines, dispatched by overload.
13
14
SKETCH / PROPOSAL -- conventions worked out, not yet build-tested.
15
16
The generic templates in LU.hpp and CholeskyDecomposition.hpp are kept as
17
the fallback for small fixed-size matrices (Mat3x3d, Mat6x6d in HydroProp,
18
...) and for non-RealType element types, where the packing + call overhead
19
of going out to LAPACK would lose to the inlined VTK/Crout code. Here we add
20
*non-template overloads* for exactly DynamicRectMatrix<RealType>: a
21
non-template overload is preferred over a function template for an exact
22
type match, so any call invertMatrix(A, AI) / CholeskyDecomposition(A, L)
23
with A,L of that concrete type routes here, while every fixed-size caller
24
keeps the generic template unchanged. No edits to the generic headers.
25
26
Include this header instead of (or after) LU.hpp/CholeskyDecomposition.hpp
27
at the call site (e.g. in RPYMobility.cpp) so the overloads are visible.
28
With HAVE_LAPACK undefined it simply forwards to the generics.
29
30
ASSUMPTIONS to confirm against the tree:
31
- DynamicRectMatrix<RealType> stores its data contiguously and exposes a
32
raw pointer (assumed getArray() below); if the accessor differs, only
33
the two `a = ...getArray()` lines change.
34
- Storage is row-major (OpenMD convention). Since the matrices we factor
35
here (the RPY mobility M and resistance R) are symmetric, the row/column
36
major mismatch with LAPACK is harmless, and for the general inverse the
37
"invert the transpose, read back transposed" identity makes a plain
38
dgetrf/dgetri on the row-major buffer return the correct inverse.
39
- RealType is double. For a single-precision build (RealType == float),
40
dispatch the s* entry points instead (a thin if-constexpr or a pair of
41
overloaded extern "C" wrappers); only the BLAS/LAPACK names change.
42
*/
43
44
#ifndef MATH_LAPACKLINEARALGEBRA_HPP
45
#define MATH_LAPACKLINEARALGEBRA_HPP
46
47
#include <algorithm>
48
#include <vector>
49
50
#include "config.h"
// provides HAVE_LAPACK
51
#include "math/CholeskyDecomposition.hpp"
52
#include "
math/DynamicRectMatrix.hpp
"
53
#include "math/LU.hpp"
54
55
#ifdef HAVE_LAPACK
56
57
extern
"C"
{
58
// LU factor / inverse (general)
59
void
dgetrf_(
const
int
* m,
const
int
* n,
double
* a,
const
int
* lda,
int
* ipiv,
60
int
* info);
61
void
dgetri_(
const
int
* n,
double
* a,
const
int
* lda,
const
int
* ipiv,
62
double
* work,
const
int
* lwork,
int
* info);
63
// Cholesky factor (symmetric positive definite)
64
void
dpotrf_(
const
char
* uplo,
const
int
* n,
double
* a,
const
int
* lda,
65
int
* info);
66
}
67
68
namespace
OpenMD
{
69
70
/**
71
* R = A^{-1} for a dynamic double matrix, via LAPACK LU.
72
* Non-template overload: chosen ahead of LU.hpp's invertMatrix template for
73
* this exact type. A is left intact; the result is written into AI. (Feeding
74
* the row-major buffer to column-major LAPACK factors A^T, whose inverse read
75
* back row-major is exactly A^{-1}, so no explicit transpose is needed.)
76
*/
77
inline
bool
invertMatrix
(
DynamicRectMatrix<RealType>
& A,
78
DynamicRectMatrix<RealType>
& AI) {
79
const
int
n =
static_cast<
int
>
(A.getNRow());
80
if
(n !=
static_cast<
int
>
(A.getNCol()) ||
81
n !=
static_cast<
int
>
(AI.getNRow()) ||
82
n !=
static_cast<
int
>
(AI.getNCol()))
83
return
false
;
84
if
(n == 0)
return
true
;
85
86
// factor/invert in AI's buffer, leaving A untouched
87
for
(
int
i = 0; i < n; ++i)
88
for
(
int
j = 0; j < n; ++j)
89
AI(i, j) = A(i, j);
90
91
RealType* a = AI.
getArrayPointer
();
// contiguous row-major
92
std::vector<int> ipiv(n);
93
int
info = 0, lda = n;
94
95
dgetrf_(&n, &n, a, &lda, ipiv.data(), &info);
96
if
(info != 0)
return
false
;
// singular (info>0) or bad arg (info<0)
97
98
// workspace query, then inversion
99
int
lwork = -1;
100
RealType wq = 0.0;
101
dgetri_(&n, a, &lda, ipiv.data(), &wq, &lwork, &info);
102
lwork = std::max(1,
static_cast<
int
>
(wq));
103
std::vector<RealType> work(
static_cast<
std::size_t
>
(lwork));
104
dgetri_(&n, a, &lda, ipiv.data(), work.data(), &lwork, &info);
105
return
info == 0;
106
}
107
108
/**
109
* L L^T = A for a dynamic, symmetric, double matrix, via LAPACK dpotrf.
110
* Returns the lower-triangular factor with the strict upper triangle zeroed,
111
* matching the generic CholeskyDecomposition contract (so a downstream S*Z
112
* may be a full matrix-vector product).
113
*
114
* Convention: our buffer is row-major; LAPACK reads it column-major, i.e. as
115
* A^T. A is symmetric here (A == A^T), so requesting the 'U' factor from
116
* LAPACK (column-major upper) yields, read back row-major, the lower factor
117
* we want.
118
*/
119
inline
void
CholeskyDecomposition(
DynamicRectMatrix<RealType>
& A,
120
DynamicRectMatrix<RealType>
& L) {
121
const
int
n =
static_cast<
int
>
(A.getNRow());
122
for
(
int
i = 0; i < n; ++i)
123
for
(
int
j = 0; j < n; ++j)
124
L(i, j) = A(i, j);
125
if
(n == 0)
return
;
126
127
RealType* l = L.
getArrayPointer
();
// contiguous row-major
128
int
info = 0, lda = n;
129
const
char
uplo =
'U'
;
// row-major lower factor <-> column-major upper
130
dpotrf_(&uplo, &n, l, &lda, &info);
131
132
if
(info != 0) {
133
// not positive definite: zero the factor so the caller's pivot check
134
// (S(k,k) > eps) trips deterministically instead of reading partial data.
135
for
(
int
i = 0; i < n; ++i)
136
for
(
int
j = 0; j < n; ++j)
137
L(i, j) = 0.0;
138
return
;
139
}
140
// dpotrf leaves the opposite triangle untouched; zero it to match the
141
// generic routine, which returns a clean lower-triangular factor.
142
for
(
int
i = 0; i < n; ++i)
143
for
(
int
j = i + 1; j < n; ++j)
144
L(i, j) = 0.0;
145
}
146
147
}
// namespace OpenMD
148
149
#endif
// HAVE_LAPACK
150
#endif
// MATH_LAPACKLINEARALGEBRA_HPP
DynamicRectMatrix.hpp
DynamicRectMatrix::getArrayPointer
Real * getArrayPointer()
Returns a pointer to the contiguous internal storage (row-major).
Definition
DynamicRectMatrix.hpp:140
OpenMD::DynamicRectMatrix
Rectangular matrix class with contiguous flat storage.
Definition
DynamicRectMatrix.hpp:78
OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Definition
ActionCorrFunc.cpp:63
OpenMD::invertMatrix
bool invertMatrix(MatrixType &A, MatrixType &AI)
Invert input square matrix A into matrix AI.
Definition
LU.hpp:101
math
LapackLinearAlgebra.hpp
Generated on
for OpenMD by
1.17.0