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