(git:374b731)
Loading...
Searching...
No Matches
cp_fm_cholesky.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief various cholesky decomposition related routines
10!> \par History
11!> 09.2002 created [fawzi]
12!> \author Fawzi Mohamed
13! **************************************************************************************************
16 USE cp_fm_types, ONLY: cp_fm_type
18 USE kinds, ONLY: dp, &
19 sp
20#ifdef __DLAF
22#endif
23#include "../base/base_uses.f90"
24
25 IMPLICIT NONE
26 PRIVATE
27
28 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
29 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_fm_cholesky'
30
33
34!***
35CONTAINS
36
37! **************************************************************************************************
38!> \brief used to replace a symmetric positive def. matrix M with its cholesky
39!> decomposition U: M = U^T * U, with U upper triangular
40!> \param matrix the matrix to replace with its cholesky decomposition
41!> \param n the number of row (and columns) of the matrix &
42!> (defaults to the min(size(matrix)))
43!> \param info_out ...
44!> \par History
45!> 05.2002 created [JVdV]
46!> 12.2002 updated, added n optional parm [fawzi]
47!> \author Joost
48! **************************************************************************************************
49 SUBROUTINE cp_fm_cholesky_decompose(matrix, n, info_out)
50 TYPE(cp_fm_type), INTENT(IN) :: matrix
51 INTEGER, INTENT(in), OPTIONAL :: n
52 INTEGER, INTENT(out), OPTIONAL :: info_out
53
54 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_decompose'
55
56 INTEGER :: handle, info, my_n
57 REAL(kind=dp), DIMENSION(:, :), POINTER :: a
58 REAL(kind=sp), DIMENSION(:, :), POINTER :: a_sp
59#if defined(__SCALAPACK)
60 INTEGER, DIMENSION(9) :: desca
61#endif
62
63 CALL timeset(routinen, handle)
64
65 my_n = min(matrix%matrix_struct%nrow_global, &
66 matrix%matrix_struct%ncol_global)
67 IF (PRESENT(n)) THEN
68 cpassert(n <= my_n)
69 my_n = n
70 END IF
71
72 a => matrix%local_data
73 a_sp => matrix%local_data_sp
74
75#if defined(__SCALAPACK)
76 desca(:) = matrix%matrix_struct%descriptor(:)
77#if defined(__DLAF)
78 IF (matrix%use_sp) THEN
79 CALL cp_pspotrf_dlaf('U', my_n, a_sp(:, :), 1, 1, desca, info)
80 ELSE
81 CALL cp_pdpotrf_dlaf('U', my_n, a(:, :), 1, 1, desca, info)
82 END IF
83#else
84 IF (matrix%use_sp) THEN
85 CALL pspotrf('U', my_n, a_sp(1, 1), 1, 1, desca, info)
86 ELSE
87 CALL pdpotrf('U', my_n, a(1, 1), 1, 1, desca, info)
88 END IF
89#endif
90#else
91
92 IF (matrix%use_sp) THEN
93 CALL spotrf('U', my_n, a_sp(1, 1), SIZE(a_sp, 1), info)
94 ELSE
95 CALL dpotrf('U', my_n, a(1, 1), SIZE(a, 1), info)
96 END IF
97
98#endif
99
100 IF (PRESENT(info_out)) THEN
101 info_out = info
102 ELSE
103 IF (info /= 0) &
104 CALL cp_abort(__location__, &
105 "Cholesky decompose failed: the matrix is not positive definite or ill-conditioned.")
106 END IF
107
108 CALL timestop(handle)
109
110 END SUBROUTINE cp_fm_cholesky_decompose
111
112! **************************************************************************************************
113!> \brief used to replace the cholesky decomposition by the inverse
114!> \param matrix the matrix to invert (must be an upper triangular matrix)
115!> \param n size of the matrix to invert (defaults to the min(size(matrix)))
116!> \param info_out ...
117!> \par History
118!> 05.2002 created [JVdV]
119!> \author Joost VandeVondele
120! **************************************************************************************************
121 SUBROUTINE cp_fm_cholesky_invert(matrix, n, info_out)
122 TYPE(cp_fm_type), INTENT(IN) :: matrix
123 INTEGER, INTENT(in), OPTIONAL :: n
124 INTEGER, INTENT(OUT), OPTIONAL :: info_out
125
126 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_invert'
127 REAL(kind=dp), DIMENSION(:, :), POINTER :: a
128 REAL(kind=sp), DIMENSION(:, :), POINTER :: a_sp
129 INTEGER :: info, handle
130 INTEGER :: my_n
131#if defined(__SCALAPACK)
132 INTEGER, DIMENSION(9) :: desca
133#endif
134
135 CALL timeset(routinen, handle)
136
137 my_n = min(matrix%matrix_struct%nrow_global, &
138 matrix%matrix_struct%ncol_global)
139 IF (PRESENT(n)) THEN
140 cpassert(n <= my_n)
141 my_n = n
142 END IF
143
144 a => matrix%local_data
145 a_sp => matrix%local_data_sp
146
147#if defined(__SCALAPACK)
148
149 desca(:) = matrix%matrix_struct%descriptor(:)
150
151 IF (matrix%use_sp) THEN
152 CALL pspotri('U', my_n, a_sp(1, 1), 1, 1, desca, info)
153 ELSE
154 CALL pdpotri('U', my_n, a(1, 1), 1, 1, desca, info)
155 END IF
156
157#else
158
159 IF (matrix%use_sp) THEN
160 CALL spotri('U', my_n, a_sp(1, 1), SIZE(a_sp, 1), info)
161 ELSE
162 CALL dpotri('U', my_n, a(1, 1), SIZE(a, 1), info)
163 END IF
164
165#endif
166
167 IF (PRESENT(info_out)) THEN
168 info_out = info
169 ELSE
170 IF (info /= 0) &
171 cpabort("Cholesky invert failed: the matrix is not positive definite or ill-conditioned.")
172 END IF
173
174 CALL timestop(handle)
175
176 END SUBROUTINE cp_fm_cholesky_invert
177
178! **************************************************************************************************
179!> \brief reduce a matrix pencil A,B to normal form
180!> B has to be cholesky decomposed with cp_fm_cholesky_decompose
181!> before calling this routine
182!> A,B -> inv(U^T)*A*inv(U),1
183!> (AX=BX -> inv(U^T)*A*inv(U)*U*X=U*X hence evecs U*X)
184!> \param matrix the symmetric matrix A
185!> \param matrixb the cholesky decomposition of matrix B
186!> \param itype ...
187!> \par History
188!> 05.2002 created [JVdV]
189!> \author Joost VandeVondele
190! **************************************************************************************************
191 SUBROUTINE cp_fm_cholesky_reduce(matrix, matrixb, itype)
192 TYPE(cp_fm_type), INTENT(IN) :: matrix, matrixb
193 INTEGER, OPTIONAL :: itype
194
195 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_reduce'
196 REAL(kind=dp), DIMENSION(:, :), POINTER :: a, b
197 INTEGER :: info, handle
198 INTEGER :: n, my_itype
199#if defined(__SCALAPACK)
200 REAL(kind=dp) :: scale
201 INTEGER, DIMENSION(9) :: desca, descb
202#endif
203
204 CALL timeset(routinen, handle)
205
206 n = matrix%matrix_struct%nrow_global
207
208 my_itype = 1
209 IF (PRESENT(itype)) my_itype = itype
210
211 a => matrix%local_data
212 b => matrixb%local_data
213
214#if defined(__SCALAPACK)
215
216 desca(:) = matrix%matrix_struct%descriptor(:)
217 descb(:) = matrixb%matrix_struct%descriptor(:)
218
219 CALL pdsygst(my_itype, 'U', n, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb, scale, info)
220
221 ! this is supposed to be one in current version of lapack
222 ! if not, eigenvalues have to be scaled by this number
223 IF (scale /= 1.0_dp) &
224 cpabort("scale not equal 1 (scale="//cp_to_string(scale)//")")
225#else
226
227 CALL dsygst(my_itype, 'U', n, a(1, 1), n, b(1, 1), n, info)
228
229#endif
230
231 cpassert(info == 0)
232
233 CALL timestop(handle)
234
235 END SUBROUTINE cp_fm_cholesky_reduce
236
237!
238! op can be "SOLVE" (out = U^-1 * in ) or "MULTIPLY" (out = U * in )
239! pos can be "LEFT" or "RIGHT" (U at the left or at the right)
240!
241! DEPRECATED, see cp_fm_basic_linalg:cp_fm_triangular_multiply
242!
243! **************************************************************************************************
244!> \brief ...
245!> \param matrix ...
246!> \param neig ...
247!> \param matrixb ...
248!> \param matrixout ...
249!> \param op ...
250!> \param pos ...
251!> \param transa ...
252! **************************************************************************************************
253 SUBROUTINE cp_fm_cholesky_restore(matrix, neig, matrixb, matrixout, op, pos, transa)
254 TYPE(cp_fm_type), INTENT(IN) :: matrix, matrixb, matrixout
255 INTEGER, INTENT(IN) :: neig
256 CHARACTER(LEN=*), INTENT(IN) :: op
257 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: pos
258 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: transa
259
260 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_restore'
261 REAL(kind=dp), DIMENSION(:, :), POINTER :: a, b, out
262 REAL(kind=sp), DIMENSION(:, :), POINTER :: a_sp, b_sp, out_sp
263 INTEGER :: itype, handle
264 INTEGER :: n
265 REAL(kind=dp) :: alpha
266 INTEGER :: myprow, mypcol
267 TYPE(cp_blacs_env_type), POINTER :: context
268 CHARACTER :: chol_pos, chol_transa
269#if defined(__SCALAPACK)
270 INTEGER :: i
271 INTEGER, DIMENSION(9) :: desca, descb, descout
272#endif
273
274 CALL timeset(routinen, handle)
275
276 context => matrix%matrix_struct%context
277 myprow = context%mepos(1)
278 mypcol = context%mepos(2)
279 n = matrix%matrix_struct%nrow_global
280 itype = 1
281 IF (op /= "SOLVE" .AND. op /= "MULTIPLY") &
282 cpabort("wrong argument op")
283
284 IF (PRESENT(pos)) THEN
285 SELECT CASE (pos)
286 CASE ("LEFT")
287 chol_pos = 'L'
288 CASE ("RIGHT")
289 chol_pos = 'R'
290 CASE DEFAULT
291 cpabort("wrong argument pos")
292 END SELECT
293 ELSE
294 chol_pos = 'L'
295 END IF
296
297 chol_transa = 'N'
298 IF (PRESENT(transa)) chol_transa = transa
299
300 IF ((matrix%use_sp .NEQV. matrixb%use_sp) .OR. (matrix%use_sp .NEQV. matrixout%use_sp)) &
301 cpabort("not the same precision")
302
303 ! notice b is the cholesky guy
304 a => matrix%local_data
305 b => matrixb%local_data
306 out => matrixout%local_data
307 a_sp => matrix%local_data_sp
308 b_sp => matrixb%local_data_sp
309 out_sp => matrixout%local_data_sp
310
311#if defined(__SCALAPACK)
312
313 desca(:) = matrix%matrix_struct%descriptor(:)
314 descb(:) = matrixb%matrix_struct%descriptor(:)
315 descout(:) = matrixout%matrix_struct%descriptor(:)
316 alpha = 1.0_dp
317 DO i = 1, neig
318 IF (matrix%use_sp) THEN
319 CALL pscopy(n, a_sp(1, 1), 1, i, desca, 1, out_sp(1, 1), 1, i, descout, 1)
320 ELSE
321 CALL pdcopy(n, a(1, 1), 1, i, desca, 1, out(1, 1), 1, i, descout, 1)
322 END IF
323 END DO
324 IF (op .EQ. "SOLVE") THEN
325 IF (matrix%use_sp) THEN
326 CALL pstrsm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), 1, 1, descb, &
327 out_sp(1, 1), 1, 1, descout)
328 ELSE
329 CALL pdtrsm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), 1, 1, descb, out(1, 1), 1, 1, descout)
330 END IF
331 ELSE
332 IF (matrix%use_sp) THEN
333 CALL pstrmm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), 1, 1, descb, &
334 out_sp(1, 1), 1, 1, descout)
335 ELSE
336 CALL pdtrmm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), 1, 1, descb, out(1, 1), 1, 1, descout)
337 END IF
338 END IF
339#else
340
341 alpha = 1.0_dp
342 IF (matrix%use_sp) THEN
343 CALL scopy(neig*n, a_sp(1, 1), 1, out_sp(1, 1), 1)
344 ELSE
345 CALL dcopy(neig*n, a(1, 1), 1, out(1, 1), 1)
346 END IF
347 IF (op .EQ. "SOLVE") THEN
348 IF (matrix%use_sp) THEN
349 CALL strsm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), SIZE(b_sp, 1), out_sp(1, 1), n)
350 ELSE
351 CALL dtrsm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), SIZE(b, 1), out(1, 1), n)
352 END IF
353 ELSE
354 IF (matrix%use_sp) THEN
355 CALL strmm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), n, out_sp(1, 1), n)
356 ELSE
357 CALL dtrmm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), n, out(1, 1), n)
358 END IF
359 END IF
360
361#endif
362
363 CALL timestop(handle)
364
365 END SUBROUTINE cp_fm_cholesky_restore
366
367END MODULE cp_fm_cholesky
methods related to the blacs parallel environment
various cholesky decomposition related routines
subroutine, public cp_fm_cholesky_invert(matrix, n, info_out)
used to replace the cholesky decomposition by the inverse
subroutine, public cp_fm_cholesky_decompose(matrix, n, info_out)
used to replace a symmetric positive def. matrix M with its cholesky decomposition U: M = U^T * U,...
subroutine, public cp_fm_cholesky_reduce(matrix, matrixb, itype)
reduce a matrix pencil A,B to normal form B has to be cholesky decomposed with cp_fm_cholesky_decompo...
subroutine, public cp_fm_cholesky_restore(matrix, neig, matrixb, matrixout, op, pos, transa)
...
subroutine, public cp_pdpotrf_dlaf(uplo, n, a, ia, ja, desca, info)
Cholesky factorization using DLA-Future.
subroutine, public cp_pspotrf_dlaf(uplo, n, a, ia, ja, desca, info)
Cholesky factorization using DLA-Future.
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
various routines to log and control the output. The idea is that decisions about where to log should ...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public sp
Definition kinds.F:33
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
represent a full matrix