18 USE dbcsr_api,
ONLY: dbcsr_add,&
32 #include "./base/base_uses.f90"
38 INTEGER,
PARAMETER :: diis_error_orthogonal = 1
40 INTEGER,
PARAMETER :: diis_env_dbcsr = 1
41 INTEGER,
PARAMETER :: diis_env_domain = 2
43 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'almo_scf_diis_types'
45 PUBLIC :: almo_scf_diis_type, &
49 INTERFACE almo_scf_diis_init
50 MODULE PROCEDURE almo_scf_diis_init_dbcsr
51 MODULE PROCEDURE almo_scf_diis_init_domain
54 TYPE almo_scf_diis_type
56 INTEGER :: diis_env_type = 0
58 INTEGER :: buffer_length = 0
59 INTEGER :: max_buffer_length = 0
62 TYPE(dbcsr_type),
DIMENSION(:),
ALLOCATABLE :: m_var
63 TYPE(dbcsr_type),
DIMENSION(:),
ALLOCATABLE :: m_err
66 TYPE(domain_submatrix_type),
DIMENSION(:, :),
ALLOCATABLE :: d_var
67 TYPE(domain_submatrix_type),
DIMENSION(:, :),
ALLOCATABLE :: d_err
70 TYPE(domain_submatrix_type),
DIMENSION(:),
ALLOCATABLE :: m_b
73 INTEGER :: in_point = 0
78 INTEGER :: error_type = 0
80 END TYPE almo_scf_diis_type
95 SUBROUTINE almo_scf_diis_init_dbcsr(diis_env, sample_err, sample_var, error_type, &
98 TYPE(almo_scf_diis_type),
INTENT(INOUT) :: diis_env
99 TYPE(dbcsr_type),
INTENT(IN) :: sample_err, sample_var
100 INTEGER,
INTENT(IN) :: error_type, max_length
102 CHARACTER(len=*),
PARAMETER :: routineN =
'almo_scf_diis_init_dbcsr'
104 INTEGER :: handle, idomain, im, ndomains
106 CALL timeset(routinen, handle)
108 IF (max_length .LE. 0)
THEN
109 cpabort(
"DIIS: max_length is less than zero")
112 diis_env%diis_env_type = diis_env_dbcsr
114 diis_env%max_buffer_length = max_length
115 diis_env%buffer_length = 0
116 diis_env%error_type = error_type
117 diis_env%in_point = 1
119 ALLOCATE (diis_env%m_err(diis_env%max_buffer_length))
120 ALLOCATE (diis_env%m_var(diis_env%max_buffer_length))
123 DO im = 1, diis_env%max_buffer_length
124 CALL dbcsr_create(diis_env%m_err(im), &
126 CALL dbcsr_create(diis_env%m_var(im), &
133 ALLOCATE (diis_env%m_b(ndomains))
134 CALL init_submatrices(diis_env%m_b)
136 diis_env%m_b(:)%domain = 100
137 DO idomain = 1, ndomains
138 IF (diis_env%m_b(idomain)%domain .GT. 0)
THEN
139 ALLOCATE (diis_env%m_b(idomain)%mdata(1, 1))
140 diis_env%m_b(idomain)%mdata(:, :) = 0.0_dp
144 CALL timestop(handle)
146 END SUBROUTINE almo_scf_diis_init_dbcsr
158 SUBROUTINE almo_scf_diis_init_domain(diis_env, sample_err, error_type, &
161 TYPE(almo_scf_diis_type),
INTENT(INOUT) :: diis_env
162 TYPE(domain_submatrix_type),
DIMENSION(:), &
163 INTENT(IN) :: sample_err
164 INTEGER,
INTENT(IN) :: error_type, max_length
166 CHARACTER(len=*),
PARAMETER :: routineN =
'almo_scf_diis_init_domain'
168 INTEGER :: handle, idomain, ndomains
170 CALL timeset(routinen, handle)
172 IF (max_length .LE. 0)
THEN
173 cpabort(
"DIIS: max_length is less than zero")
176 diis_env%diis_env_type = diis_env_domain
178 diis_env%max_buffer_length = max_length
179 diis_env%buffer_length = 0
180 diis_env%error_type = error_type
181 diis_env%in_point = 1
183 ndomains =
SIZE(sample_err)
185 ALLOCATE (diis_env%d_err(diis_env%max_buffer_length, ndomains))
186 ALLOCATE (diis_env%d_var(diis_env%max_buffer_length, ndomains))
189 CALL init_submatrices(diis_env%d_var)
190 CALL init_submatrices(diis_env%d_err)
193 ALLOCATE (diis_env%m_b(ndomains))
194 CALL init_submatrices(diis_env%m_b)
197 diis_env%m_b(:)%domain = sample_err(:)%domain
198 DO idomain = 1, ndomains
199 IF (diis_env%m_b(idomain)%domain .GT. 0)
THEN
200 ALLOCATE (diis_env%m_b(idomain)%mdata(1, 1))
201 diis_env%m_b(idomain)%mdata(:, :) = 0.0_dp
205 CALL timestop(handle)
207 END SUBROUTINE almo_scf_diis_init_domain
221 TYPE(almo_scf_diis_type),
INTENT(INOUT) :: diis_env
222 TYPE(dbcsr_type),
INTENT(IN),
OPTIONAL :: var, err
223 TYPE(domain_submatrix_type),
DIMENSION(:), &
224 INTENT(IN),
OPTIONAL :: d_var, d_err
226 CHARACTER(len=*),
PARAMETER :: routinen =
'almo_scf_diis_push'
228 INTEGER :: handle, idomain, in_point, irow, &
229 ndomains, old_buffer_length
230 REAL(kind=
dp) :: trace0
231 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: m_b_tmp
233 CALL timeset(routinen, handle)
235 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
236 IF (.NOT. (
PRESENT(var) .AND.
PRESENT(err)))
THEN
237 cpabort(
"provide DBCSR matrices")
239 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
240 IF (.NOT. (
PRESENT(d_var) .AND.
PRESENT(d_err)))
THEN
241 cpabort(
"provide domain submatrices")
244 cpabort(
"illegal DIIS ENV type")
247 in_point = diis_env%in_point
250 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
251 CALL dbcsr_copy(diis_env%m_var(in_point), var)
252 CALL dbcsr_copy(diis_env%m_err(in_point), err)
253 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
254 CALL copy_submatrices(d_var, diis_env%d_var(in_point, :), copy_data=.true.)
255 CALL copy_submatrices(d_err, diis_env%d_err(in_point, :), copy_data=.true.)
259 old_buffer_length = diis_env%buffer_length
260 diis_env%buffer_length = diis_env%buffer_length + 1
261 IF (diis_env%buffer_length .GT. diis_env%max_buffer_length) &
262 diis_env%buffer_length = diis_env%max_buffer_length
287 ndomains =
SIZE(diis_env%m_b)
288 IF (old_buffer_length .LT. diis_env%buffer_length)
THEN
289 ALLOCATE (m_b_tmp(diis_env%buffer_length + 1, diis_env%buffer_length + 1))
290 DO idomain = 1, ndomains
291 IF (diis_env%m_b(idomain)%domain .GT. 0)
THEN
292 m_b_tmp(:, :) = 0.0_dp
293 m_b_tmp(1:diis_env%buffer_length, 1:diis_env%buffer_length) = &
294 diis_env%m_b(idomain)%mdata(:, :)
295 DEALLOCATE (diis_env%m_b(idomain)%mdata)
296 ALLOCATE (diis_env%m_b(idomain)%mdata(diis_env%buffer_length + 1, &
297 diis_env%buffer_length + 1))
298 diis_env%m_b(idomain)%mdata(:, :) = m_b_tmp(:, :)
303 DO idomain = 1, ndomains
304 IF (diis_env%m_b(idomain)%domain .GT. 0)
THEN
305 diis_env%m_b(idomain)%mdata(1, in_point + 1) = -1.0_dp
306 diis_env%m_b(idomain)%mdata(in_point + 1, 1) = -1.0_dp
307 DO irow = 1, diis_env%buffer_length
308 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
309 trace0 = almo_scf_diis_error_overlap(diis_env, &
310 a=diis_env%m_err(irow), b=diis_env%m_err(in_point))
311 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
312 trace0 = almo_scf_diis_error_overlap(diis_env, &
313 d_a=diis_env%d_err(irow, idomain), &
314 d_b=diis_env%d_err(in_point, idomain))
316 diis_env%m_b(idomain)%mdata(irow + 1, in_point + 1) = trace0
317 diis_env%m_b(idomain)%mdata(in_point + 1, irow + 1) = trace0
323 diis_env%in_point = diis_env%in_point + 1
324 IF (diis_env%in_point .GT. diis_env%max_buffer_length) diis_env%in_point = 1
326 CALL timestop(handle)
340 TYPE(almo_scf_diis_type),
INTENT(INOUT) :: diis_env
341 TYPE(dbcsr_type),
INTENT(INOUT),
OPTIONAL :: extr_var
342 TYPE(domain_submatrix_type),
DIMENSION(:), &
343 INTENT(INOUT),
OPTIONAL :: d_extr_var
345 CHARACTER(len=*),
PARAMETER :: routinen =
'almo_scf_diis_extrapolate'
347 INTEGER :: handle, idomain, im, info, lwork, &
349 REAL(kind=
dp) :: checksum
350 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: coeff, eigenvalues, tmp1, work
351 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: m_b_copy
352 TYPE(cp_logger_type),
POINTER :: logger
354 CALL timeset(routinen, handle)
358 IF (logger%para_env%is_source())
THEN
364 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
365 IF (.NOT.
PRESENT(extr_var))
THEN
366 cpabort(
"provide DBCSR matrix")
368 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
369 IF (.NOT.
PRESENT(d_extr_var))
THEN
370 cpabort(
"provide domain submatrices")
373 cpabort(
"illegal DIIS ENV type")
377 ALLOCATE (eigenvalues(diis_env%buffer_length + 1))
378 ALLOCATE (m_b_copy(diis_env%buffer_length + 1, diis_env%buffer_length + 1))
380 ndomains =
SIZE(diis_env%m_b)
382 DO idomain = 1, ndomains
384 IF (diis_env%m_b(idomain)%domain .GT. 0)
THEN
386 m_b_copy(:, :) = diis_env%m_b(idomain)%mdata(:, :)
390 ALLOCATE (work(max(1, lwork)))
391 CALL dsyev(
'V',
'L', diis_env%buffer_length + 1, m_b_copy, &
392 diis_env%buffer_length + 1, eigenvalues, work, lwork, info)
397 ALLOCATE (work(max(1, lwork)))
398 CALL dsyev(
'V',
'L', diis_env%buffer_length + 1, m_b_copy, &
399 diis_env%buffer_length + 1, eigenvalues, work, lwork, info)
400 IF (info .NE. 0)
THEN
401 cpabort(
"DSYEV failed")
412 ALLOCATE (tmp1(diis_env%buffer_length + 1))
413 ALLOCATE (coeff(diis_env%buffer_length + 1))
414 tmp1(:) = -1.0_dp*m_b_copy(1, :)/eigenvalues(:)
415 coeff(:) = matmul(m_b_copy, tmp1)
427 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
428 CALL dbcsr_set(extr_var, 0.0_dp)
429 DO im = 1, diis_env%buffer_length
430 CALL dbcsr_add(extr_var, diis_env%m_var(im), &
431 1.0_dp, coeff(im + 1))
432 checksum = checksum + coeff(im + 1)
434 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
435 CALL copy_submatrices(diis_env%d_var(1, idomain), &
436 d_extr_var(idomain), &
438 CALL set_submatrices(d_extr_var(idomain), 0.0_dp)
439 DO im = 1, diis_env%buffer_length
440 CALL add_submatrices(1.0_dp, d_extr_var(idomain), &
441 coeff(im + 1), diis_env%d_var(im, idomain), &
443 checksum = checksum + coeff(im + 1)
454 DEALLOCATE (eigenvalues)
455 DEALLOCATE (m_b_copy)
457 CALL timestop(handle)
473 FUNCTION almo_scf_diis_error_overlap(diis_env, A, B, d_A, d_B)
475 TYPE(almo_scf_diis_type),
INTENT(INOUT) :: diis_env
476 TYPE(dbcsr_type),
INTENT(INOUT),
OPTIONAL :: a, b
477 TYPE(domain_submatrix_type),
INTENT(INOUT), &
479 REAL(kind=
dp) :: almo_scf_diis_error_overlap
481 CHARACTER(len=*),
PARAMETER :: routinen =
'almo_scf_diis_error_overlap'
484 REAL(kind=
dp) :: trace
486 CALL timeset(routinen, handle)
488 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
489 IF (.NOT. (
PRESENT(a) .AND.
PRESENT(b)))
THEN
490 cpabort(
"provide DBCSR matrices")
492 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
493 IF (.NOT. (
PRESENT(d_a) .AND.
PRESENT(d_b)))
THEN
494 cpabort(
"provide domain submatrices")
497 cpabort(
"illegal DIIS ENV type")
500 SELECT CASE (diis_env%error_type)
501 CASE (diis_error_orthogonal)
502 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
503 CALL dbcsr_dot(a, b, trace)
504 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
505 cpassert(
SIZE(d_a%mdata, 1) .EQ.
SIZE(d_b%mdata, 1))
506 cpassert(
SIZE(d_a%mdata, 2) .EQ.
SIZE(d_b%mdata, 2))
507 cpassert(d_a%domain .EQ. d_b%domain)
508 cpassert(d_a%domain .GT. 0)
509 cpassert(d_b%domain .GT. 0)
510 trace = sum(d_a%mdata(:, :)*d_b%mdata(:, :))
513 cpabort(
"Vector type is unknown")
516 almo_scf_diis_error_overlap = trace
518 CALL timestop(handle)
520 END FUNCTION almo_scf_diis_error_overlap
530 TYPE(almo_scf_diis_type),
INTENT(INOUT) :: diis_env
532 CHARACTER(len=*),
PARAMETER :: routinen =
'almo_scf_diis_release'
534 INTEGER :: handle, im
536 CALL timeset(routinen, handle)
539 DO im = 1, diis_env%max_buffer_length
540 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr)
THEN
541 CALL dbcsr_release(diis_env%m_err(im))
542 CALL dbcsr_release(diis_env%m_var(im))
543 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
544 CALL release_submatrices(diis_env%d_var(im, :))
545 CALL release_submatrices(diis_env%d_err(im, :))
549 IF (diis_env%diis_env_type .EQ. diis_env_domain)
THEN
550 CALL release_submatrices(diis_env%m_b(:))
553 IF (
ALLOCATED(diis_env%m_b))
DEALLOCATE (diis_env%m_b)
554 IF (
ALLOCATED(diis_env%m_err))
DEALLOCATE (diis_env%m_err)
555 IF (
ALLOCATED(diis_env%m_var))
DEALLOCATE (diis_env%m_var)
556 IF (
ALLOCATED(diis_env%d_err))
DEALLOCATE (diis_env%d_err)
557 IF (
ALLOCATED(diis_env%d_var))
DEALLOCATE (diis_env%d_var)
559 CALL timestop(handle)
A DIIS implementation for the ALMO-based SCF methods.
subroutine, public almo_scf_diis_release(diis_env)
destroys the diis structure
subroutine, public almo_scf_diis_extrapolate(diis_env, extr_var, d_extr_var)
extrapolates the variable using the saved history
subroutine, public almo_scf_diis_push(diis_env, var, err, d_var, d_err)
adds a variable-error pair to the diis structure
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Subroutines to handle submatrices.
Types to handle submatrices.
Defines the basic variable types.
integer, parameter, public dp