1!--------------------------------------------------------------------------------------------------! 2! CP2K: A general program to perform molecular dynamics simulations ! 3! Copyright (C) 2000 - 2019 CP2K developers group ! 4!--------------------------------------------------------------------------------------------------! 5 6! ************************************************************************************************** 7!> \brief A DIIS implementation for the ALMO-based SCF methods 8!> \par History 9!> 2011.12 created [Rustam Z Khaliullin] 10!> \author Rustam Z Khaliullin 11! ************************************************************************************************** 12MODULE almo_scf_diis_types 13 USE cp_log_handling, ONLY: cp_get_default_logger,& 14 cp_logger_get_default_unit_nr,& 15 cp_logger_type 16 USE dbcsr_api, ONLY: dbcsr_add,& 17 dbcsr_copy,& 18 dbcsr_create,& 19 dbcsr_dot,& 20 dbcsr_release,& 21 dbcsr_set,& 22 dbcsr_type 23 USE domain_submatrix_methods, ONLY: add_submatrices,& 24 copy_submatrices,& 25 init_submatrices,& 26 release_submatrices,& 27 set_submatrices 28 USE domain_submatrix_types, ONLY: domain_submatrix_type 29 USE kinds, ONLY: dp 30#include "./base/base_uses.f90" 31 32 IMPLICIT NONE 33 34 PRIVATE 35 36 INTEGER, PARAMETER :: diis_error_orthogonal = 1 37 38 INTEGER, PARAMETER :: diis_env_dbcsr = 1 39 INTEGER, PARAMETER :: diis_env_domain = 2 40 41 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'almo_scf_diis_types' 42 43 PUBLIC :: almo_scf_diis_type, & 44 almo_scf_diis_init, almo_scf_diis_release, almo_scf_diis_push, & 45 almo_scf_diis_extrapolate 46 47 INTERFACE almo_scf_diis_init 48 MODULE PROCEDURE almo_scf_diis_init_dbcsr 49 MODULE PROCEDURE almo_scf_diis_init_domain 50 END INTERFACE 51 52 TYPE almo_scf_diis_type 53 54 INTEGER :: diis_env_type 55 56 INTEGER :: buffer_length 57 INTEGER :: max_buffer_length 58 !INTEGER, DIMENSION(:), ALLOCATABLE :: history_index 59 60 TYPE(dbcsr_type), DIMENSION(:), ALLOCATABLE :: m_var 61 TYPE(dbcsr_type), DIMENSION(:), ALLOCATABLE :: m_err 62 63 ! first dimension is history index, second - domain index 64 TYPE(domain_submatrix_type), DIMENSION(:, :), ALLOCATABLE :: d_var 65 TYPE(domain_submatrix_type), DIMENSION(:, :), ALLOCATABLE :: d_err 66 67 ! distributed matrix of error overlaps 68 TYPE(domain_submatrix_type), DIMENSION(:), ALLOCATABLE :: m_b 69 70 ! insertion point 71 INTEGER :: in_point 72 73 ! in order to calculate the overlap between error vectors 74 ! it is desirable to know tensorial properties of the error 75 ! vector, e.g. convariant, contravariant, orthogonal 76 INTEGER :: error_type 77 78 END TYPE almo_scf_diis_type 79 80CONTAINS 81 82! ************************************************************************************************** 83!> \brief initializes the diis structure 84!> \param diis_env ... 85!> \param sample_err ... 86!> \param sample_var ... 87!> \param error_type ... 88!> \param max_length ... 89!> \par History 90!> 2011.12 created [Rustam Z Khaliullin] 91!> \author Rustam Z Khaliullin 92! ************************************************************************************************** 93 SUBROUTINE almo_scf_diis_init_dbcsr(diis_env, sample_err, sample_var, error_type, & 94 max_length) 95 96 TYPE(almo_scf_diis_type), INTENT(INOUT) :: diis_env 97 TYPE(dbcsr_type), INTENT(IN) :: sample_err, sample_var 98 INTEGER, INTENT(IN) :: error_type, max_length 99 100 CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_diis_init_dbcsr', & 101 routineP = moduleN//':'//routineN 102 103 INTEGER :: handle, idomain, im, ndomains 104 105 CALL timeset(routineN, handle) 106 107 IF (max_length .LE. 0) THEN 108 CPABORT("DIIS: max_length is less than zero") 109 END IF 110 111 diis_env%diis_env_type = diis_env_dbcsr 112 113 diis_env%max_buffer_length = max_length 114 diis_env%buffer_length = 0 115 diis_env%error_type = error_type 116 diis_env%in_point = 1 117 118 ALLOCATE (diis_env%m_err(diis_env%max_buffer_length)) 119 ALLOCATE (diis_env%m_var(diis_env%max_buffer_length)) 120 121 ! create matrices 122 DO im = 1, diis_env%max_buffer_length 123 CALL dbcsr_create(diis_env%m_err(im), & 124 template=sample_err) 125 CALL dbcsr_create(diis_env%m_var(im), & 126 template=sample_var) 127 ENDDO 128 129 ! current B matrices are only 1-by-1, they will be expanded on-the-fly 130 ! only one matrix is used with dbcsr version of DIIS 131 ndomains = 1 132 ALLOCATE (diis_env%m_b(ndomains)) 133 CALL init_submatrices(diis_env%m_b) 134 ! hack into d_b structure to gain full control 135 diis_env%m_b(:)%domain = 100 ! arbitrary positive number 136 DO idomain = 1, ndomains 137 IF (diis_env%m_b(idomain)%domain .GT. 0) THEN 138 ALLOCATE (diis_env%m_b(idomain)%mdata(1, 1)) 139 diis_env%m_b(idomain)%mdata(:, :) = 0.0_dp 140 ENDIF 141 ENDDO 142 143 CALL timestop(handle) 144 145 END SUBROUTINE almo_scf_diis_init_dbcsr 146 147! ************************************************************************************************** 148!> \brief initializes the diis structure 149!> \param diis_env ... 150!> \param sample_err ... 151!> \param error_type ... 152!> \param max_length ... 153!> \par History 154!> 2011.12 created [Rustam Z Khaliullin] 155!> \author Rustam Z Khaliullin 156! ************************************************************************************************** 157 SUBROUTINE almo_scf_diis_init_domain(diis_env, sample_err, error_type, & 158 max_length) 159 160 TYPE(almo_scf_diis_type), INTENT(INOUT) :: diis_env 161 TYPE(domain_submatrix_type), DIMENSION(:), & 162 INTENT(IN) :: sample_err 163 INTEGER, INTENT(IN) :: error_type, max_length 164 165 CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_diis_init_domain', & 166 routineP = moduleN//':'//routineN 167 168 INTEGER :: handle, idomain, ndomains 169 170 CALL timeset(routineN, handle) 171 172 IF (max_length .LE. 0) THEN 173 CPABORT("DIIS: max_length is less than zero") 174 END IF 175 176 diis_env%diis_env_type = diis_env_domain 177 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 182 183 ndomains = SIZE(sample_err) 184 185 ALLOCATE (diis_env%d_err(diis_env%max_buffer_length, ndomains)) 186 ALLOCATE (diis_env%d_var(diis_env%max_buffer_length, ndomains)) 187 188 ! create matrices 189 CALL init_submatrices(diis_env%d_var) 190 CALL init_submatrices(diis_env%d_err) 191 192 ! current B matrices are only 1-by-1, they will be expanded on-the-fly 193 ALLOCATE (diis_env%m_b(ndomains)) 194 CALL init_submatrices(diis_env%m_b) 195 ! hack into d_b structure to gain full control 196 ! distribute matrices as the err/var matrices 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 202 ENDIF 203 ENDDO 204 205 CALL timestop(handle) 206 207 END SUBROUTINE almo_scf_diis_init_domain 208 209! ************************************************************************************************** 210!> \brief adds a variable-error pair to the diis structure 211!> \param diis_env ... 212!> \param var ... 213!> \param err ... 214!> \param d_var ... 215!> \param d_err ... 216!> \par History 217!> 2011.12 created [Rustam Z Khaliullin] 218!> \author Rustam Z Khaliullin 219! ************************************************************************************************** 220 SUBROUTINE almo_scf_diis_push(diis_env, var, err, d_var, d_err) 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 225 226 CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_diis_push', & 227 routineP = moduleN//':'//routineN 228 229 INTEGER :: handle, idomain, in_point, irow, & 230 ndomains, old_buffer_length 231 REAL(KIND=dp) :: trace0 232 REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: m_b_tmp 233 234 CALL timeset(routineN, handle) 235 236 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 237 IF (.NOT. (PRESENT(var) .AND. PRESENT(err))) THEN 238 CPABORT("provide DBCSR matrices") 239 ENDIF 240 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 241 IF (.NOT. (PRESENT(d_var) .AND. PRESENT(d_err))) THEN 242 CPABORT("provide domain submatrices") 243 ENDIF 244 ELSE 245 CPABORT("illegal DIIS ENV type") 246 ENDIF 247 248 in_point = diis_env%in_point 249 250 ! store a var-error pair 251 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 252 CALL dbcsr_copy(diis_env%m_var(in_point), var) 253 CALL dbcsr_copy(diis_env%m_err(in_point), err) 254 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 255 CALL copy_submatrices(d_var, diis_env%d_var(in_point, :), copy_data=.TRUE.) 256 CALL copy_submatrices(d_err, diis_env%d_err(in_point, :), copy_data=.TRUE.) 257 ENDIF 258 259 ! update the buffer length 260 old_buffer_length = diis_env%buffer_length 261 diis_env%buffer_length = diis_env%buffer_length + 1 262 IF (diis_env%buffer_length .GT. diis_env%max_buffer_length) & 263 diis_env%buffer_length = diis_env%max_buffer_length 264 265 !!!! resize B matrix 266 !!!IF (old_buffer_length.lt.diis_env%buffer_length) THEN 267 !!! ALLOCATE(m_b_tmp(diis_env%buffer_length+1,diis_env%buffer_length+1)) 268 !!! m_b_tmp(1:diis_env%buffer_length,1:diis_env%buffer_length)=& 269 !!! diis_env%m_b(:,:) 270 !!! DEALLOCATE(diis_env%m_b) 271 !!! ALLOCATE(diis_env%m_b(diis_env%buffer_length+1,& 272 !!! diis_env%buffer_length+1)) 273 !!! diis_env%m_b(:,:)=m_b_tmp(:,:) 274 !!! DEALLOCATE(m_b_tmp) 275 !!!ENDIF 276 !!!! update B matrix elements 277 !!!diis_env%m_b(1,in_point+1)=-1.0_dp 278 !!!diis_env%m_b(in_point+1,1)=-1.0_dp 279 !!!DO irow=1,diis_env%buffer_length 280 !!! trace0=almo_scf_diis_error_overlap(diis_env,& 281 !!! A=diis_env%m_err(irow),B=diis_env%m_err(in_point)) 282 !!! 283 !!! diis_env%m_b(irow+1,in_point+1)=trace0 284 !!! diis_env%m_b(in_point+1,irow+1)=trace0 285 !!!ENDDO 286 287 ! resize B matrix and update its elements 288 ndomains = SIZE(diis_env%m_b) 289 IF (old_buffer_length .LT. diis_env%buffer_length) THEN 290 ALLOCATE (m_b_tmp(diis_env%buffer_length + 1, diis_env%buffer_length + 1)) 291 DO idomain = 1, ndomains 292 IF (diis_env%m_b(idomain)%domain .GT. 0) THEN 293 m_b_tmp(:, :) = 0.0_dp 294 m_b_tmp(1:diis_env%buffer_length, 1:diis_env%buffer_length) = & 295 diis_env%m_b(idomain)%mdata(:, :) 296 DEALLOCATE (diis_env%m_b(idomain)%mdata) 297 ALLOCATE (diis_env%m_b(idomain)%mdata(diis_env%buffer_length + 1, & 298 diis_env%buffer_length + 1)) 299 diis_env%m_b(idomain)%mdata(:, :) = m_b_tmp(:, :) 300 ENDIF 301 ENDDO 302 DEALLOCATE (m_b_tmp) 303 ENDIF 304 DO idomain = 1, ndomains 305 IF (diis_env%m_b(idomain)%domain .GT. 0) THEN 306 diis_env%m_b(idomain)%mdata(1, in_point + 1) = -1.0_dp 307 diis_env%m_b(idomain)%mdata(in_point + 1, 1) = -1.0_dp 308 DO irow = 1, diis_env%buffer_length 309 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 310 trace0 = almo_scf_diis_error_overlap(diis_env, & 311 A=diis_env%m_err(irow), B=diis_env%m_err(in_point)) 312 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 313 trace0 = almo_scf_diis_error_overlap(diis_env, & 314 d_A=diis_env%d_err(irow, idomain), & 315 d_B=diis_env%d_err(in_point, idomain)) 316 ENDIF 317 diis_env%m_b(idomain)%mdata(irow + 1, in_point + 1) = trace0 318 diis_env%m_b(idomain)%mdata(in_point + 1, irow + 1) = trace0 319 ENDDO ! loop over prev errors 320 ENDIF 321 ENDDO ! loop over domains 322 323 ! update the insertion point for the next "PUSH" 324 diis_env%in_point = diis_env%in_point + 1 325 IF (diis_env%in_point .GT. diis_env%max_buffer_length) diis_env%in_point = 1 326 327 CALL timestop(handle) 328 329 END SUBROUTINE almo_scf_diis_push 330 331! ************************************************************************************************** 332!> \brief extrapolates the variable using the saved history 333!> \param diis_env ... 334!> \param extr_var ... 335!> \param d_extr_var ... 336!> \par History 337!> 2011.12 created [Rustam Z Khaliullin] 338!> \author Rustam Z Khaliullin 339! ************************************************************************************************** 340 SUBROUTINE almo_scf_diis_extrapolate(diis_env, extr_var, d_extr_var) 341 TYPE(almo_scf_diis_type), INTENT(INOUT) :: diis_env 342 TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL :: extr_var 343 TYPE(domain_submatrix_type), DIMENSION(:), & 344 INTENT(INOUT), OPTIONAL :: d_extr_var 345 346 CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_diis_extrapolate', & 347 routineP = moduleN//':'//routineN 348 349 INTEGER :: handle, idomain, im, INFO, LWORK, & 350 ndomains, unit_nr 351 REAL(KIND=dp) :: checksum 352 REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coeff, eigenvalues, tmp1, WORK 353 REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: m_b_copy 354 TYPE(cp_logger_type), POINTER :: logger 355 356 CALL timeset(routineN, handle) 357 358 ! get a useful output_unit 359 logger => cp_get_default_logger() 360 IF (logger%para_env%ionode) THEN 361 unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.) 362 ELSE 363 unit_nr = -1 364 ENDIF 365 366 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 367 IF (.NOT. PRESENT(extr_var)) THEN 368 CPABORT("provide DBCSR matrix") 369 ENDIF 370 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 371 IF (.NOT. PRESENT(d_extr_var)) THEN 372 CPABORT("provide domain submatrices") 373 ENDIF 374 ELSE 375 CPABORT("illegal DIIS ENV type") 376 ENDIF 377 378 ! Prepare data 379 ALLOCATE (eigenvalues(diis_env%buffer_length + 1)) 380 ALLOCATE (m_b_copy(diis_env%buffer_length + 1, diis_env%buffer_length + 1)) 381 382 ndomains = SIZE(diis_env%m_b) 383 384 DO idomain = 1, ndomains 385 386 IF (diis_env%m_b(idomain)%domain .GT. 0) THEN 387 388 m_b_copy(:, :) = diis_env%m_b(idomain)%mdata(:, :) 389 390 ! Query the optimal workspace for dsyev 391 LWORK = -1 392 ALLOCATE (WORK(MAX(1, LWORK))) 393 CALL DSYEV('V', 'L', diis_env%buffer_length + 1, m_b_copy, & 394 diis_env%buffer_length + 1, eigenvalues, WORK, LWORK, INFO) 395 LWORK = INT(WORK(1)) 396 DEALLOCATE (WORK) 397 398 ! Allocate the workspace and solve the eigenproblem 399 ALLOCATE (WORK(MAX(1, LWORK))) 400 CALL DSYEV('V', 'L', diis_env%buffer_length + 1, m_b_copy, & 401 diis_env%buffer_length + 1, eigenvalues, WORK, LWORK, INFO) 402 IF (INFO .NE. 0) THEN 403 CPABORT("DSYEV failed") 404 END IF 405 DEALLOCATE (WORK) 406 407 ! use the eigensystem to invert (implicitly) B matrix 408 ! and compute the extrapolation coefficients 409 !! ALLOCATE(tmp1(diis_env%buffer_length+1,1)) 410 !! ALLOCATE(coeff(diis_env%buffer_length+1,1)) 411 !! tmp1(:,1)=-1.0_dp*m_b_copy(1,:)/eigenvalues(:) 412 !! coeff=MATMUL(m_b_copy,tmp1) 413 !! DEALLOCATE(tmp1) 414 ALLOCATE (tmp1(diis_env%buffer_length + 1)) 415 ALLOCATE (coeff(diis_env%buffer_length + 1)) 416 tmp1(:) = -1.0_dp*m_b_copy(1, :)/eigenvalues(:) 417 coeff(:) = MATMUL(m_b_copy, tmp1) 418 DEALLOCATE (tmp1) 419 420 !IF (unit_nr.gt.0) THEN 421 ! DO im=1,diis_env%buffer_length+1 422 ! WRITE(unit_nr,*) diis_env%m_b(idomain)%mdata(im,:) 423 ! ENDDO 424 ! WRITE (unit_nr,*) coeff(:,1) 425 !ENDIF 426 427 ! extrapolate the variable 428 checksum = 0.0_dp 429 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 430 CALL dbcsr_set(extr_var, 0.0_dp) 431 DO im = 1, diis_env%buffer_length 432 CALL dbcsr_add(extr_var, diis_env%m_var(im), & 433 1.0_dp, coeff(im + 1)) 434 checksum = checksum + coeff(im + 1) 435 ENDDO 436 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 437 CALL copy_submatrices(diis_env%d_var(1, idomain), & 438 d_extr_var(idomain), & 439 copy_data=.FALSE.) 440 CALL set_submatrices(d_extr_var(idomain), 0.0_dp) 441 DO im = 1, diis_env%buffer_length 442 CALL add_submatrices(1.0_dp, d_extr_var(idomain), & 443 coeff(im + 1), diis_env%d_var(im, idomain), & 444 'N') 445 checksum = checksum + coeff(im + 1) 446 ENDDO 447 ENDIF 448 !WRITE(*,*) checksum 449 450 DEALLOCATE (coeff) 451 452 ENDIF ! domain is local to this mpi node 453 454 ENDDO ! loop over domains 455 456 DEALLOCATE (eigenvalues) 457 DEALLOCATE (m_b_copy) 458 459 CALL timestop(handle) 460 461 END SUBROUTINE almo_scf_diis_extrapolate 462 463! ************************************************************************************************** 464!> \brief computes elements of b-matrix 465!> \param diis_env ... 466!> \param A ... 467!> \param B ... 468!> \param d_A ... 469!> \param d_B ... 470!> \return ... 471!> \par History 472!> 2013.02 created [Rustam Z Khaliullin] 473!> \author Rustam Z Khaliullin 474! ************************************************************************************************** 475 FUNCTION almo_scf_diis_error_overlap(diis_env, A, B, d_A, d_B) 476 477 TYPE(almo_scf_diis_type), INTENT(INOUT) :: diis_env 478 TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL :: A, B 479 TYPE(domain_submatrix_type), INTENT(INOUT), & 480 OPTIONAL :: d_A, d_B 481 REAL(KIND=dp) :: almo_scf_diis_error_overlap 482 483 CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_diis_error_overlap', & 484 routineP = moduleN//':'//routineN 485 486 INTEGER :: handle 487 REAL(KIND=dp) :: trace 488 489 CALL timeset(routineN, handle) 490 491 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 492 IF (.NOT. (PRESENT(A) .AND. PRESENT(B))) THEN 493 CPABORT("provide DBCSR matrices") 494 ENDIF 495 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 496 IF (.NOT. (PRESENT(d_A) .AND. PRESENT(d_B))) THEN 497 CPABORT("provide domain submatrices") 498 ENDIF 499 ELSE 500 CPABORT("illegal DIIS ENV type") 501 ENDIF 502 503 SELECT CASE (diis_env%error_type) 504 CASE (diis_error_orthogonal) 505 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 506 CALL dbcsr_dot(A, B, trace) 507 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 508 CPASSERT(SIZE(d_A%mdata, 1) .EQ. SIZE(d_B%mdata, 1)) 509 CPASSERT(SIZE(d_A%mdata, 2) .EQ. SIZE(d_B%mdata, 2)) 510 CPASSERT(d_A%domain .EQ. d_B%domain) 511 CPASSERT(d_A%domain .GT. 0) 512 CPASSERT(d_B%domain .GT. 0) 513 trace = SUM(d_A%mdata(:, :)*d_B%mdata(:, :)) 514 ENDIF 515 CASE DEFAULT 516 CPABORT("Vector type is unknown") 517 END SELECT 518 519 almo_scf_diis_error_overlap = trace 520 521 CALL timestop(handle) 522 523 END FUNCTION almo_scf_diis_error_overlap 524 525! ************************************************************************************************** 526!> \brief destroys the diis structure 527!> \param diis_env ... 528!> \par History 529!> 2011.12 created [Rustam Z Khaliullin] 530!> \author Rustam Z Khaliullin 531! ************************************************************************************************** 532 SUBROUTINE almo_scf_diis_release(diis_env) 533 TYPE(almo_scf_diis_type), INTENT(INOUT) :: diis_env 534 535 CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_diis_release', & 536 routineP = moduleN//':'//routineN 537 538 INTEGER :: handle, im 539 540 CALL timeset(routineN, handle) 541 542 ! release matrices 543 DO im = 1, diis_env%max_buffer_length 544 IF (diis_env%diis_env_type .EQ. diis_env_dbcsr) THEN 545 CALL dbcsr_release(diis_env%m_err(im)) 546 CALL dbcsr_release(diis_env%m_var(im)) 547 ELSE IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 548 CALL release_submatrices(diis_env%d_var(im, :)) 549 CALL release_submatrices(diis_env%d_err(im, :)) 550 ENDIF 551 ENDDO 552 553 IF (diis_env%diis_env_type .EQ. diis_env_domain) THEN 554 CALL release_submatrices(diis_env%m_b(:)) 555 ENDIF 556 557 IF (ALLOCATED(diis_env%m_b)) DEALLOCATE (diis_env%m_b) 558 IF (ALLOCATED(diis_env%m_err)) DEALLOCATE (diis_env%m_err) 559 IF (ALLOCATED(diis_env%m_var)) DEALLOCATE (diis_env%m_var) 560 IF (ALLOCATED(diis_env%d_err)) DEALLOCATE (diis_env%d_err) 561 IF (ALLOCATED(diis_env%d_var)) DEALLOCATE (diis_env%d_var) 562 563 CALL timestop(handle) 564 565 END SUBROUTINE almo_scf_diis_release 566 567END MODULE almo_scf_diis_types 568 569