LCOV - code coverage report
Current view: top level - src - pao_io.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 81.9 % 320 262
Test Date: 2026-10-15 00:55:44 Functions: 71.4 % 14 10

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines for reading and writing restart files.
      10              : !> \author Ole Schuett
      11              : ! **************************************************************************************************
      12              : MODULE pao_io
      13              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      14              :                                               get_atomic_kind
      15              :    USE basis_set_types,                 ONLY: gto_basis_set_type
      16              :    USE cell_types,                      ONLY: cell_type
      17              :    USE cp_dbcsr_api,                    ONLY: &
      18              :         dbcsr_convert_dbcsr_to_csr, dbcsr_copy, dbcsr_csr_create_from_dbcsr, &
      19              :         dbcsr_csr_dbcsr_blkrow_dist, dbcsr_csr_destroy, dbcsr_csr_type, dbcsr_csr_write, &
      20              :         dbcsr_desymmetrize, dbcsr_get_block_p, dbcsr_get_info, dbcsr_has_symmetry, dbcsr_release, &
      21              :         dbcsr_type
      22              :    USE cp_files,                        ONLY: close_file,&
      23              :                                               open_file
      24              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      25              :                                               cp_logger_get_default_io_unit,&
      26              :                                               cp_logger_type
      27              :    USE cp_output_handling,              ONLY: cp_p_file,&
      28              :                                               cp_print_key_finished_output,&
      29              :                                               cp_print_key_should_output,&
      30              :                                               cp_print_key_unit_nr
      31              :    USE dm_ls_scf_types,                 ONLY: ls_scf_env_type
      32              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      33              :                                               section_vals_type,&
      34              :                                               section_vals_val_get
      35              :    USE kinds,                           ONLY: default_path_length,&
      36              :                                               default_string_length,&
      37              :                                               dp
      38              :    USE message_passing,                 ONLY: mp_para_env_type
      39              :    USE pao_input,                       ONLY: id2str
      40              :    USE pao_param,                       ONLY: pao_param_count
      41              :    USE pao_types,                       ONLY: pao_env_type
      42              :    USE particle_types,                  ONLY: particle_type
      43              :    USE physcon,                         ONLY: angstrom
      44              :    USE qs_environment_types,            ONLY: get_qs_env,&
      45              :                                               qs_environment_type
      46              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      47              :                                               pao_potential_type,&
      48              :                                               qs_kind_type
      49              : #include "./base/base_uses.f90"
      50              : 
      51              :    IMPLICIT NONE
      52              : 
      53              :    PRIVATE
      54              : 
      55              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pao_io'
      56              : 
      57              :    PUBLIC :: pao_read_restart, pao_write_restart
      58              :    PUBLIC :: pao_read_raw, pao_kinds_ensure_equal
      59              :    PUBLIC :: pao_ioblock_type, pao_iokind_type
      60              :    PUBLIC :: pao_write_ks_matrix_csr, pao_write_s_matrix_csr
      61              :    PUBLIC :: pao_write_hcore_matrix_csr, pao_write_p_matrix_csr
      62              : 
      63              :    ! data types used by pao_read_raw()
      64              :    TYPE pao_ioblock_type
      65              :       REAL(dp), DIMENSION(:, :), ALLOCATABLE    :: p
      66              :    END TYPE pao_ioblock_type
      67              : 
      68              :    TYPE pao_iokind_type
      69              :       CHARACTER(LEN=default_string_length)     :: name = ""
      70              :       INTEGER                                  :: z = -1
      71              :       CHARACTER(LEN=default_string_length)     :: prim_basis_name = ""
      72              :       INTEGER                                  :: prim_basis_size = -1
      73              :       INTEGER                                  :: pao_basis_size = -1
      74              :       INTEGER                                  :: nparams = -1
      75              :       TYPE(pao_potential_type), ALLOCATABLE, DIMENSION(:) :: pao_potentials
      76              :    END TYPE pao_iokind_type
      77              : 
      78              :    INTEGER, PARAMETER, PRIVATE :: file_format_version = 4
      79              : 
      80              : CONTAINS
      81              : 
      82              : ! **************************************************************************************************
      83              : !> \brief Reads restart file
      84              : !> \param pao ...
      85              : !> \param qs_env ...
      86              : ! **************************************************************************************************
      87            2 :    SUBROUTINE pao_read_restart(pao, qs_env)
      88              :       TYPE(pao_env_type), POINTER                        :: pao
      89              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      90              : 
      91              :       REAL(KIND=dp), PARAMETER                           :: eps_cell = 1.0E-10_dp, &
      92              :                                                             eps_pos = 1.0E-10_dp
      93              : 
      94              :       CHARACTER(LEN=default_string_length)               :: param
      95              :       INTEGER                                            :: iatom, ikind, natoms
      96            2 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom2kind
      97            2 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_sizes, row_blk_sizes
      98              :       LOGICAL                                            :: found
      99              :       REAL(dp)                                           :: diff
     100            2 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: hmat, positions
     101            2 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block_X, buffer
     102              :       TYPE(cell_type), POINTER                           :: cell
     103              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     104            2 :       TYPE(pao_ioblock_type), ALLOCATABLE, DIMENSION(:)  :: xblocks
     105            2 :       TYPE(pao_iokind_type), ALLOCATABLE, DIMENSION(:)   :: kinds
     106            2 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     107              : 
     108            0 :       CPASSERT(LEN_TRIM(pao%restart_file) > 0)
     109            2 :       IF (pao%iw > 0) WRITE (pao%iw, '(A,A)') " PAO| Reading matrix_X from restart file: ", TRIM(pao%restart_file)
     110              : 
     111              :       CALL get_qs_env(qs_env, &
     112              :                       para_env=para_env, &
     113              :                       natom=natoms, &
     114              :                       cell=cell, &
     115            2 :                       particle_set=particle_set)
     116              : 
     117              :       ! read and check restart file on first rank only
     118            2 :       IF (para_env%is_source()) THEN
     119            1 :          CALL pao_read_raw(pao%restart_file, param, hmat, kinds, atom2kind, positions, xblocks)
     120              : 
     121              :          ! check cell
     122           13 :          IF (MAXVAL(ABS(hmat - cell%hmat)) > eps_cell) THEN
     123            0 :             CPWARN("Restarting from different cell")
     124              :          END IF
     125              : 
     126              :          ! check parametrization
     127            1 :          IF (TRIM(param) /= TRIM(ADJUSTL(id2str(pao%parameterization)))) THEN
     128            1 :             CPABORT("Restart PAO parametrization does not match")
     129              :          END IF
     130              : 
     131              :          ! check kinds
     132            2 :          DO ikind = 1, SIZE(kinds)
     133            2 :             CALL pao_kinds_ensure_equal(pao, qs_env, ikind, kinds(ikind))
     134              :          END DO
     135              : 
     136              :          ! check number of atoms
     137            1 :          IF (SIZE(positions, 1) /= natoms) THEN
     138            0 :             CPABORT("Number of atoms do not match")
     139              :          END IF
     140              : 
     141              :          ! check atom2kind
     142            3 :          DO iatom = 1, natoms
     143            3 :             IF (atom2kind(iatom) /= particle_set(iatom)%atomic_kind%kind_number) THEN
     144            0 :                CPABORT("Restart atomic kinds do not match.")
     145              :             END IF
     146              :          END DO
     147              : 
     148              :          ! check positions, warning only
     149            1 :          diff = 0.0_dp
     150            3 :          DO iatom = 1, natoms
     151            9 :             diff = MAX(diff, MAXVAL(ABS(positions(iatom, :) - particle_set(iatom)%r)))
     152              :          END DO
     153            1 :          CPWARN_IF(diff > eps_pos, "Restarting from different atom positions")
     154              : 
     155              :       END IF
     156              : 
     157              :       ! scatter xblocks across ranks to fill pao%matrix_X
     158              :       ! this could probably be done more efficiently
     159            2 :       CALL dbcsr_get_info(pao%matrix_X, row_blk_size=row_blk_sizes, col_blk_size=col_blk_sizes)
     160            6 :       DO iatom = 1, natoms
     161           16 :          ALLOCATE (buffer(row_blk_sizes(iatom), col_blk_sizes(iatom)))
     162            4 :          IF (para_env%is_source()) THEN
     163            2 :             CPASSERT(row_blk_sizes(iatom) == SIZE(xblocks(iatom)%p, 1))
     164            2 :             CPASSERT(col_blk_sizes(iatom) == SIZE(xblocks(iatom)%p, 2))
     165           18 :             buffer = xblocks(iatom)%p
     166              :          END IF
     167           68 :          CALL para_env%bcast(buffer)
     168            4 :          CALL dbcsr_get_block_p(matrix=pao%matrix_X, row=iatom, col=iatom, block=block_X, found=found)
     169            4 :          IF (ASSOCIATED(block_X)) THEN
     170           34 :             block_X = buffer
     171              :          END IF
     172           10 :          DEALLOCATE (buffer)
     173              :       END DO
     174              : 
     175              :       ! ALLOCATABLEs deallocate themselves
     176              : 
     177            7 :    END SUBROUTINE pao_read_restart
     178              : 
     179              : ! **************************************************************************************************
     180              : !> \brief Reads a restart file into temporary datastructures
     181              : !> \param filename ...
     182              : !> \param param ...
     183              : !> \param hmat ...
     184              : !> \param kinds ...
     185              : !> \param atom2kind ...
     186              : !> \param positions ...
     187              : !> \param xblocks ...
     188              : !> \param ml_range ...
     189              : ! **************************************************************************************************
     190           36 :    SUBROUTINE pao_read_raw(filename, param, hmat, kinds, atom2kind, positions, xblocks, ml_range)
     191              :       CHARACTER(LEN=default_path_length), INTENT(IN)     :: filename
     192              :       CHARACTER(LEN=default_string_length), INTENT(OUT)  :: param
     193              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: hmat
     194              :       TYPE(pao_iokind_type), ALLOCATABLE, DIMENSION(:)   :: kinds
     195              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom2kind
     196              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: positions
     197              :       TYPE(pao_ioblock_type), ALLOCATABLE, DIMENSION(:)  :: xblocks
     198              :       INTEGER, DIMENSION(2), INTENT(OUT), OPTIONAL       :: ml_range
     199              : 
     200              :       CHARACTER(LEN=default_string_length)               :: label, str_in
     201              :       INTEGER                                            :: i1, i2, iatom, ikind, ipot, natoms, &
     202              :                                                             nkinds, nparams, unit_nr, xblocks_read
     203              :       REAL(dp)                                           :: r1, r2
     204              :       REAL(dp), DIMENSION(3)                             :: pos_in
     205              :       REAL(dp), DIMENSION(3, 3)                          :: hmat_angstrom
     206              : 
     207           18 :       CPASSERT(.NOT. ALLOCATED(hmat))
     208           18 :       CPASSERT(.NOT. ALLOCATED(kinds))
     209           18 :       CPASSERT(.NOT. ALLOCATED(atom2kind))
     210           18 :       CPASSERT(.NOT. ALLOCATED(positions))
     211           18 :       CPASSERT(.NOT. ALLOCATED(xblocks))
     212              : 
     213           18 :       natoms = -1
     214           18 :       nkinds = -1
     215           18 :       xblocks_read = 0
     216              : 
     217              :       CALL open_file(file_name=filename, file_status="OLD", file_form="FORMATTED", &
     218           18 :                      file_action="READ", unit_number=unit_nr)
     219              : 
     220              :       ! check if file starts with proper header !TODO: introduce a more unique header
     221           18 :       READ (unit_nr, fmt=*) label, i1
     222           18 :       IF (TRIM(label) /= "Version") THEN
     223            0 :          CPABORT("PAO restart file appears to be corrupted.")
     224              :       END IF
     225           18 :       IF (i1 /= file_format_version) CPABORT("Restart PAO file format version is wrong")
     226              : 
     227              :       DO WHILE (.TRUE.)
     228          306 :          READ (unit_nr, fmt=*) label
     229          306 :          BACKSPACE (unit_nr)
     230              : 
     231          324 :          IF (TRIM(label) == "Parametrization") THEN
     232           18 :             READ (unit_nr, fmt=*) label, str_in
     233           18 :             param = str_in
     234              : 
     235          288 :          ELSE IF (TRIM(label) == "Cell") THEN
     236           18 :             READ (unit_nr, fmt=*) label, hmat_angstrom
     237           18 :             ALLOCATE (hmat(3, 3))
     238          234 :             hmat(:, :) = hmat_angstrom(:, :)/angstrom
     239              : 
     240          270 :          ELSE IF (TRIM(label) == "Nkinds") THEN
     241           18 :             READ (unit_nr, fmt=*) label, nkinds
     242           72 :             ALLOCATE (kinds(nkinds))
     243              : 
     244          252 :          ELSE IF (TRIM(label) == "Kind") THEN
     245           18 :             READ (unit_nr, fmt=*) label, ikind, str_in, i1
     246           18 :             CPASSERT(ALLOCATED(kinds))
     247           18 :             kinds(ikind)%name = str_in
     248           18 :             kinds(ikind)%z = i1
     249              : 
     250          234 :          ELSE IF (TRIM(label) == "PrimBasis") THEN
     251           18 :             READ (unit_nr, fmt=*) label, ikind, i1, str_in
     252           18 :             CPASSERT(ALLOCATED(kinds))
     253           18 :             kinds(ikind)%prim_basis_size = i1
     254           18 :             kinds(ikind)%prim_basis_name = str_in
     255              : 
     256          216 :          ELSE IF (TRIM(label) == "PaoBasis") THEN
     257           18 :             READ (unit_nr, fmt=*) label, ikind, i1
     258           18 :             CPASSERT(ALLOCATED(kinds))
     259           18 :             kinds(ikind)%pao_basis_size = i1
     260              : 
     261          198 :          ELSE IF (TRIM(label) == "NPaoPotentials") THEN
     262           18 :             READ (unit_nr, fmt=*) label, ikind, i1
     263           18 :             CPASSERT(ALLOCATED(kinds))
     264           72 :             ALLOCATE (kinds(ikind)%pao_potentials(i1))
     265              : 
     266          180 :          ELSE IF (TRIM(label) == "PaoPotential") THEN
     267           18 :             READ (unit_nr, fmt=*) label, ikind, ipot, i1, i2, r1, r2
     268           18 :             CPASSERT(ALLOCATED(kinds(ikind)%pao_potentials))
     269           18 :             kinds(ikind)%pao_potentials(ipot)%maxl = i1
     270           18 :             kinds(ikind)%pao_potentials(ipot)%max_projector = i2
     271           18 :             kinds(ikind)%pao_potentials(ipot)%beta = r1
     272           18 :             kinds(ikind)%pao_potentials(ipot)%weight = r2
     273              : 
     274          162 :          ELSE IF (TRIM(label) == "NParams") THEN
     275           18 :             READ (unit_nr, fmt=*) label, ikind, i1
     276           18 :             CPASSERT(ALLOCATED(kinds))
     277           18 :             kinds(ikind)%nparams = i1
     278              : 
     279          144 :          ELSE IF (TRIM(label) == "Natoms") THEN
     280           18 :             READ (unit_nr, fmt=*) label, natoms
     281          162 :             ALLOCATE (positions(natoms, 3), atom2kind(natoms), xblocks(natoms))
     282           54 :             positions = 0.0_dp; atom2kind = -1
     283           52 :             IF (PRESENT(ml_range)) ml_range = [1, natoms]
     284              : 
     285          126 :          ELSE IF (TRIM(label) == "MLRange") THEN
     286              :             ! Natoms entry has to come first
     287            0 :             CPASSERT(natoms > 0)
     288              :             ! range of atoms whose xblocks are used for machine learning
     289            0 :             READ (unit_nr, fmt=*) label, i1, i2
     290            0 :             IF (PRESENT(ml_range)) ml_range = [i1, i2]
     291              : 
     292          126 :          ELSE IF (TRIM(label) == "Atom") THEN
     293           36 :             READ (unit_nr, fmt=*) label, iatom, str_in, pos_in
     294           36 :             CPASSERT(ALLOCATED(kinds))
     295           36 :             DO ikind = 1, nkinds
     296           36 :                IF (TRIM(kinds(ikind)%name) == TRIM(str_in)) EXIT
     297              :             END DO
     298           36 :             CPASSERT(ALLOCATED(atom2kind) .AND. ALLOCATED(positions))
     299           36 :             atom2kind(iatom) = ikind
     300          144 :             positions(iatom, :) = pos_in/angstrom
     301              : 
     302           90 :          ELSE IF (TRIM(label) == "Xblock") THEN
     303           36 :             READ (unit_nr, fmt=*) label, iatom
     304           36 :             CPASSERT(ALLOCATED(kinds) .AND. ALLOCATED(atom2kind))
     305           36 :             ikind = atom2kind(iatom)
     306           36 :             nparams = kinds(ikind)%nparams
     307           36 :             CPASSERT(nparams >= 0)
     308          108 :             ALLOCATE (xblocks(iatom)%p(nparams, 1))
     309           36 :             BACKSPACE (unit_nr)
     310          324 :             READ (unit_nr, fmt=*) label, iatom, xblocks(iatom)%p
     311           36 :             xblocks_read = xblocks_read + 1
     312           36 :             CPASSERT(iatom == xblocks_read) ! ensure blocks are read in order
     313              : 
     314           54 :          ELSE IF (TRIM(label) == "THE_END") THEN
     315              :             EXIT
     316              :          ELSE
     317              :             !CPWARN("Skipping restart header with label: "//TRIM(label))
     318           36 :             READ (unit_nr, fmt=*) label ! just read again and ignore
     319              :          END IF
     320              :       END DO
     321           18 :       CALL close_file(unit_number=unit_nr)
     322              : 
     323           18 :       CPASSERT(xblocks_read == natoms) ! ensure we read all blocks
     324              : 
     325           18 :    END SUBROUTINE pao_read_raw
     326              : 
     327              : ! **************************************************************************************************
     328              : !> \brief Ensure that the kind read from the restart is equal to the kind curretly in use.
     329              : !> \param pao ...
     330              : !> \param qs_env ...
     331              : !> \param ikind ...
     332              : !> \param pao_kind ...
     333              : ! **************************************************************************************************
     334           72 :    SUBROUTINE pao_kinds_ensure_equal(pao, qs_env, ikind, pao_kind)
     335              :       TYPE(pao_env_type), POINTER                        :: pao
     336              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     337              :       INTEGER, INTENT(IN)                                :: ikind
     338              :       TYPE(pao_iokind_type), INTENT(IN)                  :: pao_kind
     339              : 
     340              :       CHARACTER(LEN=default_string_length)               :: name
     341              :       INTEGER                                            :: ipot, nparams, pao_basis_size, z
     342           18 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     343              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set
     344           18 :       TYPE(pao_potential_type), DIMENSION(:), POINTER    :: pao_potentials
     345           18 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     346              : 
     347              :       CALL get_qs_env(qs_env, &
     348              :                       atomic_kind_set=atomic_kind_set, &
     349           18 :                       qs_kind_set=qs_kind_set)
     350              : 
     351           18 :       IF (ikind > SIZE(atomic_kind_set) .OR. ikind > SIZE(qs_kind_set)) THEN
     352            0 :          CPABORT("Some kinds are missing.")
     353              :       END IF
     354              : 
     355           18 :       CALL get_atomic_kind(atomic_kind_set(ikind), z=z, name=name)
     356              :       CALL get_qs_kind(qs_kind_set(ikind), &
     357              :                        basis_set=basis_set, &
     358              :                        pao_basis_size=pao_basis_size, &
     359           18 :                        pao_potentials=pao_potentials)
     360           18 :       CALL pao_param_count(pao, qs_env, ikind=ikind, nparams=nparams)
     361              : 
     362           18 :       IF (pao_kind%nparams /= nparams) THEN
     363            0 :          CPABORT("Number of parameters do not match")
     364              :       END IF
     365           18 :       IF (TRIM(pao_kind%name) /= TRIM(name)) THEN
     366            0 :          CPABORT("Kind names do not match")
     367              :       END IF
     368           18 :       IF (pao_kind%z /= z) THEN
     369            0 :          CPABORT("Atomic numbers do not match")
     370              :       END IF
     371           18 :       IF (TRIM(pao_kind%prim_basis_name) /= TRIM(basis_set%name)) THEN
     372            0 :          CPABORT("Primary Basis-set name does not match")
     373              :       END IF
     374           18 :       IF (pao_kind%prim_basis_size /= basis_set%nsgf) THEN
     375            0 :          CPABORT("Primary Basis-set size does not match")
     376              :       END IF
     377           18 :       IF (pao_kind%pao_basis_size /= pao_basis_size) THEN
     378            0 :          CPABORT("PAO basis size does not match")
     379              :       END IF
     380           18 :       IF (SIZE(pao_kind%pao_potentials) /= SIZE(pao_potentials)) THEN
     381            0 :          CPABORT("Number of PAO_POTENTIALS does not match")
     382              :       END IF
     383              : 
     384           36 :       DO ipot = 1, SIZE(pao_potentials)
     385           18 :          IF (pao_kind%pao_potentials(ipot)%maxl /= pao_potentials(ipot)%maxl) THEN
     386            0 :             CPABORT("PAO_POT_MAXL does not match")
     387              :          END IF
     388           18 :          IF (pao_kind%pao_potentials(ipot)%max_projector /= pao_potentials(ipot)%max_projector) THEN
     389            0 :             CPABORT("PAO_POT_MAX_PROJECTOR does not match")
     390              :          END IF
     391           18 :          IF (pao_kind%pao_potentials(ipot)%beta /= pao_potentials(ipot)%beta) THEN
     392            0 :             CPWARN("PAO_POT_BETA does not match")
     393              :          END IF
     394           36 :          IF (pao_kind%pao_potentials(ipot)%weight /= pao_potentials(ipot)%weight) THEN
     395            0 :             CPWARN("PAO_POT_WEIGHT does not match")
     396              :          END IF
     397              :       END DO
     398              : 
     399           18 :    END SUBROUTINE pao_kinds_ensure_equal
     400              : 
     401              : ! **************************************************************************************************
     402              : !> \brief Writes restart file
     403              : !> \param pao ...
     404              : !> \param qs_env ...
     405              : !> \param energy ...
     406              : ! **************************************************************************************************
     407          158 :    SUBROUTINE pao_write_restart(pao, qs_env, energy)
     408              :       TYPE(pao_env_type), POINTER                        :: pao
     409              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     410              :       REAL(dp)                                           :: energy
     411              : 
     412              :       CHARACTER(len=*), PARAMETER :: printkey_section = 'DFT%LS_SCF%PAO%PRINT%RESTART', &
     413              :          routineN = 'pao_write_restart'
     414              : 
     415              :       INTEGER                                            :: handle, unit_max, unit_nr
     416              :       TYPE(cp_logger_type), POINTER                      :: logger
     417              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     418              :       TYPE(section_vals_type), POINTER                   :: input
     419              : 
     420          158 :       CALL timeset(routineN, handle)
     421          158 :       logger => cp_get_default_logger()
     422              : 
     423          158 :       CALL get_qs_env(qs_env, input=input, para_env=para_env)
     424              : 
     425              :       ! open file
     426              :       unit_nr = cp_print_key_unit_nr(logger, &
     427              :                                      input, &
     428              :                                      printkey_section, &
     429              :                                      extension=".pao", &
     430              :                                      file_action="WRITE", &
     431              :                                      file_position="REWIND", &
     432              :                                      file_status="UNKNOWN", &
     433          158 :                                      do_backup=.TRUE.)
     434              : 
     435              :       ! although just rank-0 writes the trajectory it requires collective MPI calls
     436          158 :       unit_max = unit_nr
     437          158 :       CALL para_env%max(unit_max)
     438          158 :       IF (unit_max > 0) THEN
     439           64 :          IF (pao%iw > 0) WRITE (pao%iw, '(A,A)') " PAO| Writing restart file."
     440           64 :          IF (unit_nr > 0) THEN
     441           32 :             CALL write_restart_header(pao, qs_env, energy, unit_nr)
     442              :          END IF
     443              : 
     444           64 :          CALL pao_write_diagonal_blocks(para_env, pao%matrix_X, "Xblock", unit_nr)
     445              : 
     446              :       END IF
     447              : 
     448              :       ! close file
     449          158 :       IF (unit_nr > 0) WRITE (unit_nr, '(A)') "THE_END"
     450          158 :       CALL cp_print_key_finished_output(unit_nr, logger, input, printkey_section)
     451              : 
     452          158 :       CALL timestop(handle)
     453          158 :    END SUBROUTINE pao_write_restart
     454              : 
     455              : ! **************************************************************************************************
     456              : !> \brief Write the digonal blocks of given DBCSR matrix into the provided unit_nr
     457              : !> \param para_env ...
     458              : !> \param matrix ...
     459              : !> \param label ...
     460              : !> \param unit_nr ...
     461              : ! **************************************************************************************************
     462           64 :    SUBROUTINE pao_write_diagonal_blocks(para_env, matrix, label, unit_nr)
     463              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     464              :       TYPE(dbcsr_type)                                   :: matrix
     465              :       CHARACTER(LEN=*), INTENT(IN)                       :: label
     466              :       INTEGER, INTENT(IN)                                :: unit_nr
     467              : 
     468              :       INTEGER                                            :: iatom, natoms
     469           64 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_sizes, row_blk_sizes
     470              :       LOGICAL                                            :: found
     471           64 :       REAL(dp), DIMENSION(:, :), POINTER                 :: local_block, mpi_buffer
     472              : 
     473              :       !TODO: this is a serial algorithm
     474           64 :       CALL dbcsr_get_info(matrix, row_blk_size=row_blk_sizes, col_blk_size=col_blk_sizes)
     475           64 :       CPASSERT(SIZE(row_blk_sizes) == SIZE(col_blk_sizes))
     476           64 :       natoms = SIZE(row_blk_sizes)
     477              : 
     478          192 :       DO iatom = 1, natoms
     479          512 :          ALLOCATE (mpi_buffer(row_blk_sizes(iatom), col_blk_sizes(iatom)))
     480          128 :          NULLIFY (local_block)
     481          128 :          CALL dbcsr_get_block_p(matrix=matrix, row=iatom, col=iatom, block=local_block, found=found)
     482          128 :          IF (ASSOCIATED(local_block)) THEN
     483          192 :             IF (SIZE(local_block) > 0) THEN
     484              :                ! catch corner-case
     485         1188 :                mpi_buffer(:, :) = local_block(:, :)
     486              :             END IF
     487              :          ELSE
     488          594 :             mpi_buffer(:, :) = 0.0_dp
     489              :          END IF
     490              : 
     491         2248 :          CALL para_env%sum(mpi_buffer)
     492          128 :          IF (unit_nr > 0) THEN
     493           64 :             WRITE (unit_nr, fmt="(A,1X,I10,1X)", advance='no') label, iatom
     494          594 :             WRITE (unit_nr, *) mpi_buffer
     495              :          END IF
     496          320 :          DEALLOCATE (mpi_buffer)
     497              :       END DO
     498              : 
     499              :       ! flush
     500           64 :       IF (unit_nr > 0) FLUSH (unit_nr)
     501              : 
     502           64 :    END SUBROUTINE pao_write_diagonal_blocks
     503              : 
     504              : ! **************************************************************************************************
     505              : !> \brief Writes header of restart file
     506              : !> \param pao ...
     507              : !> \param qs_env ...
     508              : !> \param energy ...
     509              : !> \param unit_nr ...
     510              : ! **************************************************************************************************
     511           32 :    SUBROUTINE write_restart_header(pao, qs_env, energy, unit_nr)
     512              :       TYPE(pao_env_type), POINTER                        :: pao
     513              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     514              :       REAL(dp)                                           :: energy
     515              :       INTEGER, INTENT(IN)                                :: unit_nr
     516              : 
     517              :       CHARACTER(LEN=default_string_length)               :: kindname
     518              :       INTEGER                                            :: iatom, ikind, ipot, nparams, &
     519              :                                                             pao_basis_size, z
     520           32 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     521              :       TYPE(cell_type), POINTER                           :: cell
     522              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set
     523           32 :       TYPE(pao_potential_type), DIMENSION(:), POINTER    :: pao_potentials
     524           32 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     525           32 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     526              : 
     527              :       CALL get_qs_env(qs_env, &
     528              :                       cell=cell, &
     529              :                       particle_set=particle_set, &
     530              :                       atomic_kind_set=atomic_kind_set, &
     531           32 :                       qs_kind_set=qs_kind_set)
     532              : 
     533           32 :       WRITE (unit_nr, "(A,5X,I0)") "Version", file_format_version
     534           32 :       WRITE (unit_nr, "(A,5X,F20.10)") "Energy", energy
     535           32 :       WRITE (unit_nr, "(A,5X,I0)") "Step", pao%istep
     536           32 :       WRITE (unit_nr, "(A,5X,A)") "Parametrization", id2str(pao%parameterization)
     537              : 
     538              :       ! write kinds
     539           32 :       WRITE (unit_nr, "(A,5X,I0)") "Nkinds", SIZE(atomic_kind_set)
     540           64 :       DO ikind = 1, SIZE(atomic_kind_set)
     541           32 :          CALL get_atomic_kind(atomic_kind_set(ikind), name=kindname, z=z)
     542              :          CALL get_qs_kind(qs_kind_set(ikind), &
     543              :                           pao_basis_size=pao_basis_size, &
     544              :                           pao_potentials=pao_potentials, &
     545           32 :                           basis_set=basis_set)
     546           32 :          CALL pao_param_count(pao, qs_env, ikind, nparams)
     547           32 :          WRITE (unit_nr, "(A,5X,I10,1X,A,1X,I3)") "Kind", ikind, TRIM(kindname), z
     548           32 :          WRITE (unit_nr, "(A,5X,I10,1X,I3)") "NParams", ikind, nparams
     549           32 :          WRITE (unit_nr, "(A,5X,I10,1X,I10,1X,A)") "PrimBasis", ikind, basis_set%nsgf, TRIM(basis_set%name)
     550           32 :          WRITE (unit_nr, "(A,5X,I10,1X,I3)") "PaoBasis", ikind, pao_basis_size
     551           32 :          WRITE (unit_nr, "(A,5X,I10,1X,I3)") "NPaoPotentials", ikind, SIZE(pao_potentials)
     552          129 :          DO ipot = 1, SIZE(pao_potentials)
     553           33 :             WRITE (unit_nr, "(A,5X,I10,1X,I3)", advance='no') "PaoPotential", ikind, ipot
     554           33 :             WRITE (unit_nr, "(1X,I3)", advance='no') pao_potentials(ipot)%maxl
     555           33 :             WRITE (unit_nr, "(1X,I3)", advance='no') pao_potentials(ipot)%max_projector
     556           33 :             WRITE (unit_nr, "(1X,F20.16)", advance='no') pao_potentials(ipot)%beta
     557           65 :             WRITE (unit_nr, "(1X,F20.16)") pao_potentials(ipot)%weight
     558              :          END DO
     559              :       END DO
     560              : 
     561              :       ! write cell
     562           32 :       WRITE (unit_nr, fmt="(A,5X)", advance='no') "Cell"
     563          416 :       WRITE (unit_nr, *) cell%hmat*angstrom
     564              : 
     565              :       ! write atoms
     566           32 :       WRITE (unit_nr, "(A,5X,I0)") "Natoms", SIZE(particle_set)
     567           96 :       DO iatom = 1, SIZE(particle_set)
     568           64 :          kindname = particle_set(iatom)%atomic_kind%name
     569           64 :          WRITE (unit_nr, fmt="(A,5X,I10,5X,A,1X)", advance='no') "Atom ", iatom, TRIM(kindname)
     570          288 :          WRITE (unit_nr, *) particle_set(iatom)%r*angstrom
     571              :       END DO
     572              : 
     573           32 :    END SUBROUTINE write_restart_header
     574              : 
     575              : !**************************************************************************************************
     576              : !> \brief writing the KS matrix (in terms of the PAO basis) in csr format into a file
     577              : !> \param qs_env qs environment
     578              : !> \param ls_scf_env ls environment
     579              : !> \author Mohammad Hossein Bani-Hashemian
     580              : ! **************************************************************************************************
     581          254 :    SUBROUTINE pao_write_ks_matrix_csr(qs_env, ls_scf_env)
     582              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     583              :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
     584              : 
     585              :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_write_ks_matrix_csr'
     586              : 
     587              :       CHARACTER(LEN=default_path_length)                 :: file_name, fileformat
     588              :       INTEGER                                            :: handle, ispin, output_unit, unit_nr
     589              :       LOGICAL                                            :: bin, do_kpoints, do_ks_csr_write, uptr
     590              :       REAL(KIND=dp)                                      :: thld
     591              :       TYPE(cp_logger_type), POINTER                      :: logger
     592              :       TYPE(dbcsr_csr_type)                               :: ks_mat_csr
     593              :       TYPE(dbcsr_type)                                   :: matrix_ks_nosym
     594              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     595              : 
     596          254 :       CALL timeset(routineN, handle)
     597              : 
     598          254 :       NULLIFY (dft_section)
     599              : 
     600          254 :       logger => cp_get_default_logger()
     601          254 :       output_unit = cp_logger_get_default_io_unit(logger)
     602              : 
     603          254 :       CALL get_qs_env(qs_env, input=input)
     604          254 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     605              :       do_ks_csr_write = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
     606          254 :                                                          "PRINT%KS_CSR_WRITE"), cp_p_file)
     607              : 
     608              :       ! NOTE: k-points has to be treated differently later. k-points has KS matrix as double pointer.
     609          254 :       CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints)
     610              : 
     611          254 :       IF (do_ks_csr_write .AND. (.NOT. do_kpoints)) THEN
     612            0 :          CALL section_vals_val_get(dft_section, "PRINT%KS_CSR_WRITE%THRESHOLD", r_val=thld)
     613            0 :          CALL section_vals_val_get(dft_section, "PRINT%KS_CSR_WRITE%UPPER_TRIANGULAR", l_val=uptr)
     614            0 :          CALL section_vals_val_get(dft_section, "PRINT%KS_CSR_WRITE%BINARY", l_val=bin)
     615              : 
     616            0 :          IF (bin) THEN
     617            0 :             fileformat = "UNFORMATTED"
     618              :          ELSE
     619            0 :             fileformat = "FORMATTED"
     620              :          END IF
     621              : 
     622            0 :          DO ispin = 1, SIZE(ls_scf_env%matrix_ks)
     623              : 
     624            0 :             IF (dbcsr_has_symmetry(ls_scf_env%matrix_ks(ispin))) THEN
     625            0 :                CALL dbcsr_desymmetrize(ls_scf_env%matrix_ks(ispin), matrix_ks_nosym)
     626              :             ELSE
     627            0 :                CALL dbcsr_copy(matrix_ks_nosym, ls_scf_env%matrix_ks(ispin))
     628              :             END IF
     629              : 
     630            0 :             CALL dbcsr_csr_create_from_dbcsr(matrix_ks_nosym, ks_mat_csr, dbcsr_csr_dbcsr_blkrow_dist)
     631            0 :             CALL dbcsr_convert_dbcsr_to_csr(matrix_ks_nosym, ks_mat_csr)
     632              : 
     633            0 :             WRITE (file_name, '(A,I0)') "PAO_KS_SPIN_", ispin
     634              :             unit_nr = cp_print_key_unit_nr(logger, dft_section, "PRINT%KS_CSR_WRITE", &
     635              :                                            extension=".csr", middle_name=TRIM(file_name), &
     636            0 :                                            file_status="REPLACE", file_form=fileformat)
     637            0 :             CALL dbcsr_csr_write(ks_mat_csr, unit_nr, upper_triangle=uptr, threshold=thld, binary=bin)
     638              : 
     639            0 :             CALL cp_print_key_finished_output(unit_nr, logger, dft_section, "PRINT%KS_CSR_WRITE")
     640              : 
     641            0 :             CALL dbcsr_csr_destroy(ks_mat_csr)
     642            0 :             CALL dbcsr_release(matrix_ks_nosym)
     643              :          END DO
     644              :       END IF
     645              : 
     646          254 :       CALL timestop(handle)
     647              : 
     648          254 :    END SUBROUTINE pao_write_ks_matrix_csr
     649              : 
     650              : !**************************************************************************************************
     651              : !> \brief writing the overlap matrix (in terms of the PAO basis) in csr format into a file
     652              : !> \param qs_env qs environment
     653              : !> \param ls_scf_env ls environment
     654              : !> \author Mohammad Hossein Bani-Hashemian
     655              : ! **************************************************************************************************
     656          254 :    SUBROUTINE pao_write_s_matrix_csr(qs_env, ls_scf_env)
     657              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     658              :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
     659              : 
     660              :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_write_s_matrix_csr'
     661              : 
     662              :       CHARACTER(LEN=default_path_length)                 :: file_name, fileformat
     663              :       INTEGER                                            :: handle, output_unit, unit_nr
     664              :       LOGICAL                                            :: bin, do_kpoints, do_s_csr_write, uptr
     665              :       REAL(KIND=dp)                                      :: thld
     666              :       TYPE(cp_logger_type), POINTER                      :: logger
     667              :       TYPE(dbcsr_csr_type)                               :: s_mat_csr
     668              :       TYPE(dbcsr_type)                                   :: matrix_s_nosym
     669              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     670              : 
     671          254 :       CALL timeset(routineN, handle)
     672              : 
     673          254 :       NULLIFY (dft_section)
     674              : 
     675          254 :       logger => cp_get_default_logger()
     676          254 :       output_unit = cp_logger_get_default_io_unit(logger)
     677              : 
     678          254 :       CALL get_qs_env(qs_env, input=input)
     679          254 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     680              :       do_s_csr_write = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
     681          254 :                                                         "PRINT%S_CSR_WRITE"), cp_p_file)
     682              : 
     683              :       ! NOTE: k-points has to be treated differently later. k-points has overlap matrix as double pointer.
     684          254 :       CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints)
     685              : 
     686          254 :       IF (do_s_csr_write .AND. (.NOT. do_kpoints)) THEN
     687            0 :          CALL section_vals_val_get(dft_section, "PRINT%S_CSR_WRITE%THRESHOLD", r_val=thld)
     688            0 :          CALL section_vals_val_get(dft_section, "PRINT%S_CSR_WRITE%UPPER_TRIANGULAR", l_val=uptr)
     689            0 :          CALL section_vals_val_get(dft_section, "PRINT%S_CSR_WRITE%BINARY", l_val=bin)
     690              : 
     691            0 :          IF (bin) THEN
     692            0 :             fileformat = "UNFORMATTED"
     693              :          ELSE
     694            0 :             fileformat = "FORMATTED"
     695              :          END IF
     696              : 
     697            0 :          IF (dbcsr_has_symmetry(ls_scf_env%matrix_s)) THEN
     698            0 :             CALL dbcsr_desymmetrize(ls_scf_env%matrix_s, matrix_s_nosym)
     699              :          ELSE
     700            0 :             CALL dbcsr_copy(matrix_s_nosym, ls_scf_env%matrix_s)
     701              :          END IF
     702              : 
     703            0 :          CALL dbcsr_csr_create_from_dbcsr(matrix_s_nosym, s_mat_csr, dbcsr_csr_dbcsr_blkrow_dist)
     704            0 :          CALL dbcsr_convert_dbcsr_to_csr(matrix_s_nosym, s_mat_csr)
     705              : 
     706            0 :          WRITE (file_name, '(A,I0)') "PAO_S"
     707              :          unit_nr = cp_print_key_unit_nr(logger, dft_section, "PRINT%S_CSR_WRITE", &
     708              :                                         extension=".csr", middle_name=TRIM(file_name), &
     709            0 :                                         file_status="REPLACE", file_form=fileformat)
     710            0 :          CALL dbcsr_csr_write(s_mat_csr, unit_nr, upper_triangle=uptr, threshold=thld, binary=bin)
     711              : 
     712            0 :          CALL cp_print_key_finished_output(unit_nr, logger, dft_section, "PRINT%S_CSR_WRITE")
     713              : 
     714            0 :          CALL dbcsr_csr_destroy(s_mat_csr)
     715            0 :          CALL dbcsr_release(matrix_s_nosym)
     716              :       END IF
     717              : 
     718          254 :       CALL timestop(handle)
     719              : 
     720          254 :    END SUBROUTINE pao_write_s_matrix_csr
     721              : 
     722              : !**************************************************************************************************
     723              : !> \brief writing the core Hamiltonian matrix (NYA)
     724              : !> \param qs_env qs environment
     725              : !> \param ls_scf_env ls environment
     726              : !> \author Mohammad Hossein Bani-Hashemian
     727              : ! **************************************************************************************************
     728          254 :    SUBROUTINE pao_write_hcore_matrix_csr(qs_env, ls_scf_env)
     729              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     730              :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
     731              : 
     732              :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_write_hcore_matrix_csr'
     733              : 
     734              :       INTEGER                                            :: handle, output_unit
     735              :       LOGICAL                                            :: do_h_csr_write, do_kpoints
     736              :       TYPE(cp_logger_type), POINTER                      :: logger
     737              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     738              : 
     739              :       MARK_USED(ls_scf_env)
     740              : 
     741          254 :       CALL timeset(routineN, handle)
     742              : 
     743          254 :       NULLIFY (dft_section)
     744              : 
     745          254 :       logger => cp_get_default_logger()
     746          254 :       output_unit = cp_logger_get_default_io_unit(logger)
     747              : 
     748          254 :       CALL get_qs_env(qs_env, input=input)
     749          254 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     750              :       do_h_csr_write = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
     751          254 :                                                         "PRINT%HCORE_CSR_WRITE"), cp_p_file)
     752              : 
     753              :       ! NOTE: k-points has to be treated differently later. k-points has KS matrix as double pointer.
     754          254 :       CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints)
     755              : 
     756          254 :       IF (do_h_csr_write .AND. (.NOT. do_kpoints)) THEN
     757            0 :          CALL cp_warn(__LOCATION__, "Writing the PAO Core Hamiltonian matrix in CSR format NYA")
     758              :       END IF
     759              : 
     760          254 :       CALL timestop(handle)
     761              : 
     762          254 :    END SUBROUTINE pao_write_hcore_matrix_csr
     763              : 
     764              : !**************************************************************************************************
     765              : !> \brief writing the density matrix (NYA)
     766              : !> \param qs_env qs environment
     767              : !> \param ls_scf_env ls environment
     768              : !> \author Mohammad Hossein Bani-Hashemian
     769              : ! **************************************************************************************************
     770          254 :    SUBROUTINE pao_write_p_matrix_csr(qs_env, ls_scf_env)
     771              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     772              :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
     773              : 
     774              :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_write_p_matrix_csr'
     775              : 
     776              :       INTEGER                                            :: handle, output_unit
     777              :       LOGICAL                                            :: do_kpoints, do_p_csr_write
     778              :       TYPE(cp_logger_type), POINTER                      :: logger
     779              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     780              : 
     781              :       MARK_USED(ls_scf_env)
     782              : 
     783          254 :       CALL timeset(routineN, handle)
     784              : 
     785          254 :       NULLIFY (dft_section)
     786              : 
     787          254 :       logger => cp_get_default_logger()
     788          254 :       output_unit = cp_logger_get_default_io_unit(logger)
     789              : 
     790          254 :       CALL get_qs_env(qs_env, input=input)
     791          254 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     792              :       do_p_csr_write = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
     793          254 :                                                         "PRINT%P_CSR_WRITE"), cp_p_file)
     794              : 
     795              :       ! NOTE: k-points has to be treated differently later. k-points has KS matrix as double pointer.
     796          254 :       CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints)
     797              : 
     798          254 :       IF (do_p_csr_write .AND. (.NOT. do_kpoints)) THEN
     799            0 :          CALL cp_warn(__LOCATION__, "Writing the PAO density matrix in CSR format NYA")
     800              :       END IF
     801              : 
     802          254 :       CALL timestop(handle)
     803              : 
     804          254 :    END SUBROUTINE pao_write_p_matrix_csr
     805              : 
     806            0 : END MODULE pao_io
        

Generated by: LCOV version 2.0-1