(git:97501a3)
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-2025 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! **************************************************************************************************
22 USE cp_fm_types, ONLY: cp_fm_type
24 USE kinds, ONLY: dp,&
25 sp
26#include "../base/base_uses.f90"
27
28 IMPLICIT NONE
29 PRIVATE
30
31 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
32 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_fm_cholesky'
33
36
37 ! The following saved variables are Cholesky decomposition global
38 ! Stores the default library for Cholesky decomposition
39 INTEGER, SAVE, PUBLIC :: cholesky_type = 0
40 ! Minimum matrix size for the use of the DLAF Cholesky decomposition.
41 ! ScaLAPACK is used as fallback for all smaller cases.
42 INTEGER, SAVE, PUBLIC :: dlaf_cholesky_n_min = 0
43 ! Constants for the diag_type above
44 INTEGER, PARAMETER, PUBLIC :: fm_cholesky_type_scalapack = 101, &
47
48!***
49CONTAINS
50
51! **************************************************************************************************
52!> \brief used to replace a symmetric positive def. matrix M with its cholesky
53!> decomposition U: M = U^T * U, with U upper triangular
54!> \param matrix the matrix to replace with its cholesky decomposition
55!> \param n the number of row (and columns) of the matrix &
56!> (defaults to the min(size(matrix)))
57!> \param info_out ...
58!> \par History
59!> 05.2002 created [JVdV]
60!> 12.2002 updated, added n optional parm [fawzi]
61!> \author Joost
62! **************************************************************************************************
63 SUBROUTINE cp_fm_cholesky_decompose(matrix, n, info_out)
64 TYPE(cp_fm_type), INTENT(IN) :: matrix
65 INTEGER, INTENT(in), OPTIONAL :: n
66 INTEGER, INTENT(out), OPTIONAL :: info_out
67
68 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_decompose'
69
70 INTEGER :: handle, info, my_n
71 REAL(kind=dp), DIMENSION(:, :), POINTER :: a
72 REAL(kind=sp), DIMENSION(:, :), POINTER :: a_sp
73#if defined(__parallel)
74 INTEGER, DIMENSION(9) :: desca
75#endif
76
77 CALL timeset(routinen, handle)
78
79 my_n = min(matrix%matrix_struct%nrow_global, &
80 matrix%matrix_struct%ncol_global)
81 IF (PRESENT(n)) THEN
82 cpassert(n <= my_n)
83 my_n = n
84 END IF
85
86 a => matrix%local_data
87 a_sp => matrix%local_data_sp
88
89#if defined(__parallel)
90 desca(:) = matrix%matrix_struct%descriptor(:)
91#if defined(__DLAF)
92 IF (cholesky_type == fm_cholesky_type_dlaf .AND. matrix%matrix_struct%nrow_global >= dlaf_cholesky_n_min) THEN
93 ! Initialize DLA-Future on-demand; if already initialized, does nothing
95
96 ! Create DLAF grid from BLACS context; if already present, does nothing
97 CALL cp_dlaf_create_grid(matrix%matrix_struct%context%get_handle())
98
99 IF (matrix%use_sp) THEN
100 CALL cp_pspotrf_dlaf('U', my_n, a_sp(:, :), 1, 1, desca, info)
101 ELSE
102 CALL cp_pdpotrf_dlaf('U', my_n, a(:, :), 1, 1, desca, info)
103 END IF
104 ELSE
105#endif
106 IF (matrix%use_sp) THEN
107 CALL pspotrf('U', my_n, a_sp(1, 1), 1, 1, desca, info)
108 ELSE
109 CALL pdpotrf('U', my_n, a(1, 1), 1, 1, desca, info)
110 END IF
111#if defined(__DLAF)
112 END IF
113#endif
114#else
115 IF (matrix%use_sp) THEN
116 CALL spotrf('U', my_n, a_sp(1, 1), SIZE(a_sp, 1), info)
117 ELSE
118 CALL dpotrf('U', my_n, a(1, 1), SIZE(a, 1), info)
119 END IF
120#endif
121
122 IF (PRESENT(info_out)) THEN
123 info_out = info
124 ELSE IF (info /= 0) THEN
125 CALL cp_abort(__location__, &
126 "Cholesky decompose failed: the matrix is not positive definite or ill-conditioned.")
127 END IF
128
129 CALL timestop(handle)
130
131 END SUBROUTINE cp_fm_cholesky_decompose
132
133! **************************************************************************************************
134!> \brief used to replace the cholesky decomposition by the inverse
135!> \param matrix the matrix to invert (must be an upper triangular matrix)
136!> \param n size of the matrix to invert (defaults to the min(size(matrix)))
137!> \param info_out ...
138!> \par History
139!> 05.2002 created [JVdV]
140!> \author Joost VandeVondele
141! **************************************************************************************************
142 SUBROUTINE cp_fm_cholesky_invert(matrix, n, info_out)
143 TYPE(cp_fm_type), INTENT(IN) :: matrix
144 INTEGER, INTENT(in), OPTIONAL :: n
145 INTEGER, INTENT(OUT), OPTIONAL :: info_out
146
147 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_invert'
148 REAL(kind=dp), DIMENSION(:, :), POINTER :: a
149 REAL(kind=sp), DIMENSION(:, :), POINTER :: a_sp
150 INTEGER :: info, handle
151 INTEGER :: my_n
152#if defined(__parallel)
153 INTEGER, DIMENSION(9) :: desca
154#endif
155
156 CALL timeset(routinen, handle)
157
158 my_n = min(matrix%matrix_struct%nrow_global, &
159 matrix%matrix_struct%ncol_global)
160 IF (PRESENT(n)) THEN
161 cpassert(n <= my_n)
162 my_n = n
163 END IF
164
165 a => matrix%local_data
166 a_sp => matrix%local_data_sp
167
168#if defined(__parallel)
169
170 desca(:) = matrix%matrix_struct%descriptor(:)
171
172#if defined(__DLAF)
173 IF (cholesky_type == fm_cholesky_type_dlaf .AND. matrix%matrix_struct%nrow_global >= dlaf_cholesky_n_min) THEN
174 ! Initialize DLA-Future on-demand; if already initialized, does nothing
175 CALL cp_dlaf_initialize()
176
177 ! Create DLAF grid from BLACS context; if already present, does nothing
178 CALL cp_dlaf_create_grid(matrix%matrix_struct%context%get_handle())
179
180 IF (matrix%use_sp) THEN
181 CALL cp_pspotri_dlaf('U', my_n, a_sp(:, :), 1, 1, desca, info)
182 ELSE
183 CALL cp_pdpotri_dlaf('U', my_n, a(:, :), 1, 1, desca, info)
184 END IF
185 ELSE
186#endif
187 IF (matrix%use_sp) THEN
188 CALL pspotri('U', my_n, a_sp(1, 1), 1, 1, desca, info)
189 ELSE
190 CALL pdpotri('U', my_n, a(1, 1), 1, 1, desca, info)
191 END IF
192#if defined(__DLAF)
193 END IF
194#endif
195
196#else
197
198 IF (matrix%use_sp) THEN
199 CALL spotri('U', my_n, a_sp(1, 1), SIZE(a_sp, 1), info)
200 ELSE
201 CALL dpotri('U', my_n, a(1, 1), SIZE(a, 1), info)
202 END IF
203
204#endif
205
206 IF (PRESENT(info_out)) THEN
207 info_out = info
208 ELSE
209 IF (info /= 0) &
210 cpabort("Cholesky invert failed: the matrix is not positive definite or ill-conditioned.")
211 END IF
212
213 CALL timestop(handle)
214
215 END SUBROUTINE cp_fm_cholesky_invert
216
217! **************************************************************************************************
218!> \brief reduce a matrix pencil A,B to normal form
219!> B has to be cholesky decomposed with cp_fm_cholesky_decompose
220!> before calling this routine
221!> A,B -> inv(U^T)*A*inv(U),1
222!> (AX=BX -> inv(U^T)*A*inv(U)*U*X=U*X hence evecs U*X)
223!> \param matrix the symmetric matrix A
224!> \param matrixb the cholesky decomposition of matrix B
225!> \param itype ...
226!> \par History
227!> 05.2002 created [JVdV]
228!> \author Joost VandeVondele
229! **************************************************************************************************
230 SUBROUTINE cp_fm_cholesky_reduce(matrix, matrixb, itype)
231 TYPE(cp_fm_type), INTENT(IN) :: matrix, matrixb
232 INTEGER, OPTIONAL :: itype
233
234 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_reduce'
235 REAL(kind=dp), DIMENSION(:, :), POINTER :: a, b
236 INTEGER :: info, handle
237 INTEGER :: n, my_itype
238#if defined(__parallel)
239 REAL(kind=dp) :: scale
240 INTEGER, DIMENSION(9) :: desca, descb
241#endif
242
243 CALL timeset(routinen, handle)
244
245 n = matrix%matrix_struct%nrow_global
246
247 my_itype = 1
248 IF (PRESENT(itype)) my_itype = itype
249
250 a => matrix%local_data
251 b => matrixb%local_data
252
253#if defined(__parallel)
254
255 desca(:) = matrix%matrix_struct%descriptor(:)
256 descb(:) = matrixb%matrix_struct%descriptor(:)
257
258 CALL pdsygst(my_itype, 'U', n, a(1, 1), 1, 1, desca, b(1, 1), 1, 1, descb, scale, info)
259
260 ! this is supposed to be one in current version of lapack
261 ! if not, eigenvalues have to be scaled by this number
262 IF (scale /= 1.0_dp) &
263 cpabort("scale not equal 1 (scale="//cp_to_string(scale)//")")
264#else
265
266 CALL dsygst(my_itype, 'U', n, a(1, 1), n, b(1, 1), n, info)
267
268#endif
269
270 cpassert(info == 0)
271
272 CALL timestop(handle)
273
274 END SUBROUTINE cp_fm_cholesky_reduce
275
276!
277! op can be "SOLVE" (out = U^-1 * in ) or "MULTIPLY" (out = U * in )
278! pos can be "LEFT" or "RIGHT" (U at the left or at the right)
279!
280! DEPRECATED, see cp_fm_basic_linalg:cp_fm_triangular_multiply
281!
282! **************************************************************************************************
283!> \brief ...
284!> \param matrix ...
285!> \param neig ...
286!> \param matrixb ...
287!> \param matrixout ...
288!> \param op ...
289!> \param pos ...
290!> \param transa ...
291! **************************************************************************************************
292 SUBROUTINE cp_fm_cholesky_restore(matrix, neig, matrixb, matrixout, op, pos, transa)
293 TYPE(cp_fm_type), INTENT(IN) :: matrix, matrixb, matrixout
294 INTEGER, INTENT(IN) :: neig
295 CHARACTER(LEN=*), INTENT(IN) :: op
296 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: pos
297 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: transa
298
299 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_cholesky_restore'
300 REAL(kind=dp), DIMENSION(:, :), POINTER :: a, b, out
301 REAL(kind=sp), DIMENSION(:, :), POINTER :: a_sp, b_sp, out_sp
302 INTEGER :: itype, handle
303 INTEGER :: n
304 REAL(kind=dp) :: alpha
305 INTEGER :: myprow, mypcol
306 TYPE(cp_blacs_env_type), POINTER :: context
307 CHARACTER :: chol_pos, chol_transa
308#if defined(__parallel)
309 INTEGER :: i
310 INTEGER, DIMENSION(9) :: desca, descb, descout
311#endif
312
313 CALL timeset(routinen, handle)
314
315 context => matrix%matrix_struct%context
316 myprow = context%mepos(1)
317 mypcol = context%mepos(2)
318 n = matrix%matrix_struct%nrow_global
319 itype = 1
320 IF (op /= "SOLVE" .AND. op /= "MULTIPLY") &
321 cpabort("wrong argument op")
322
323 IF (PRESENT(pos)) THEN
324 SELECT CASE (pos)
325 CASE ("LEFT")
326 chol_pos = 'L'
327 CASE ("RIGHT")
328 chol_pos = 'R'
329 CASE DEFAULT
330 cpabort("wrong argument pos")
331 END SELECT
332 ELSE
333 chol_pos = 'L'
334 END IF
335
336 chol_transa = 'N'
337 IF (PRESENT(transa)) chol_transa = transa
338
339 IF ((matrix%use_sp .NEQV. matrixb%use_sp) .OR. (matrix%use_sp .NEQV. matrixout%use_sp)) &
340 cpabort("not the same precision")
341
342 ! notice b is the cholesky guy
343 a => matrix%local_data
344 b => matrixb%local_data
345 out => matrixout%local_data
346 a_sp => matrix%local_data_sp
347 b_sp => matrixb%local_data_sp
348 out_sp => matrixout%local_data_sp
349
350#if defined(__parallel)
351
352 desca(:) = matrix%matrix_struct%descriptor(:)
353 descb(:) = matrixb%matrix_struct%descriptor(:)
354 descout(:) = matrixout%matrix_struct%descriptor(:)
355 alpha = 1.0_dp
356 DO i = 1, neig
357 IF (matrix%use_sp) THEN
358 CALL pscopy(n, a_sp(1, 1), 1, i, desca, 1, out_sp(1, 1), 1, i, descout, 1)
359 ELSE
360 CALL pdcopy(n, a(1, 1), 1, i, desca, 1, out(1, 1), 1, i, descout, 1)
361 END IF
362 END DO
363 IF (op .EQ. "SOLVE") THEN
364 IF (matrix%use_sp) THEN
365 CALL pstrsm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), 1, 1, descb, &
366 out_sp(1, 1), 1, 1, descout)
367 ELSE
368 CALL pdtrsm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), 1, 1, descb, out(1, 1), 1, 1, descout)
369 END IF
370 ELSE
371 IF (matrix%use_sp) THEN
372 CALL pstrmm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), 1, 1, descb, &
373 out_sp(1, 1), 1, 1, descout)
374 ELSE
375 CALL pdtrmm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), 1, 1, descb, out(1, 1), 1, 1, descout)
376 END IF
377 END IF
378#else
379
380 alpha = 1.0_dp
381 IF (matrix%use_sp) THEN
382 CALL scopy(neig*n, a_sp(1, 1), 1, out_sp(1, 1), 1)
383 ELSE
384 CALL dcopy(neig*n, a(1, 1), 1, out(1, 1), 1)
385 END IF
386 IF (op .EQ. "SOLVE") THEN
387 IF (matrix%use_sp) THEN
388 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)
389 ELSE
390 CALL dtrsm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), SIZE(b, 1), out(1, 1), n)
391 END IF
392 ELSE
393 IF (matrix%use_sp) THEN
394 CALL strmm(chol_pos, 'U', chol_transa, 'N', n, neig, real(alpha, sp), b_sp(1, 1), n, out_sp(1, 1), n)
395 ELSE
396 CALL dtrmm(chol_pos, 'U', chol_transa, 'N', n, neig, alpha, b(1, 1), n, out(1, 1), n)
397 END IF
398 END IF
399
400#endif
401
402 CALL timestop(handle)
403
404 END SUBROUTINE cp_fm_cholesky_restore
405
406END MODULE cp_fm_cholesky
methods related to the blacs parallel environment
subroutine, public cp_dlaf_create_grid(blacs_context)
Create DLA-Future grid from BLACS context.
subroutine, public cp_dlaf_initialize()
Initialize DLA-Future and pika runtime.
various cholesky decomposition related routines
integer, parameter, public fm_cholesky_type_dlaf
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,...
integer, parameter, public fm_cholesky_type_default
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...
integer, parameter, public fm_cholesky_type_scalapack
integer, save, public dlaf_cholesky_n_min
integer, save, public cholesky_type
subroutine, public cp_fm_cholesky_restore(matrix, neig, matrixb, matrixout, op, pos, transa)
...
subroutine, public cp_pspotri_dlaf(uplo, n, a, ia, ja, desca, info)
Inverse from Cholesky factorization using DLA-Future.
subroutine, public cp_pdpotrf_dlaf(uplo, n, a, ia, ja, desca, info)
Cholesky factorization using DLA-Future.
subroutine, public cp_pdpotri_dlaf(uplo, n, a, ia, ja, desca, info)
Inverse from 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