LCOV - code coverage report
Current view: top level - src - cell_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:1155b05) Lines: 85.8 % 408 350
Test Date: 2026-03-21 06:31:29 Functions: 93.3 % 15 14

            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 Handles all functions related to the CELL
      10              : !> \par History
      11              : !>      11.2008 Teodoro Laino [tlaino] - deeply cleaning cell_type from units
      12              : !>      10.2014 Moved many routines to cell_types.F.
      13              : !> \author Matthias KracK (16.01.2002, based on a earlier version of CJM, JGH)
      14              : ! **************************************************************************************************
      15              : MODULE cell_methods
      16              :    USE cell_types,                      ONLY: &
      17              :         cell_clone, cell_release, cell_sym_cubic, cell_sym_hexagonal_gamma_120, &
      18              :         cell_sym_hexagonal_gamma_60, cell_sym_monoclinic, cell_sym_monoclinic_gamma_ab, &
      19              :         cell_sym_none, cell_sym_orthorhombic, cell_sym_rhombohedral, cell_sym_tetragonal_ab, &
      20              :         cell_sym_tetragonal_ac, cell_sym_tetragonal_bc, cell_sym_triclinic, cell_type, get_cell, &
      21              :         plane_distance, use_perd_none, use_perd_x, use_perd_xy, use_perd_xyz, use_perd_xz, &
      22              :         use_perd_y, use_perd_yz, use_perd_z
      23              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      24              :                                               cp_logger_type
      25              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      26              :                                               cp_print_key_unit_nr
      27              :    USE cp_parser_methods,               ONLY: parser_get_next_line,&
      28              :                                               parser_get_object,&
      29              :                                               parser_search_string
      30              :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      31              :                                               parser_create,&
      32              :                                               parser_release
      33              :    USE cp_units,                        ONLY: cp_unit_from_cp2k,&
      34              :                                               cp_unit_to_cp2k
      35              :    USE input_constants,                 ONLY: &
      36              :         do_cell_cif, do_cell_cp2k, do_cell_extxyz, do_cell_pdb, do_cell_xsc, do_coord_cif, &
      37              :         do_coord_cp2k, do_coord_pdb, do_coord_xyz
      38              :    USE input_cp2k_subsys,               ONLY: create_cell_section
      39              :    USE input_enumeration_types,         ONLY: enum_i2c,&
      40              :                                               enumeration_type
      41              :    USE input_keyword_types,             ONLY: keyword_get,&
      42              :                                               keyword_type
      43              :    USE input_section_types,             ONLY: &
      44              :         section_get_keyword, section_release, section_type, section_vals_get, &
      45              :         section_vals_get_subs_vals, section_vals_type, section_vals_val_get, section_vals_val_set, &
      46              :         section_vals_val_unset
      47              :    USE kinds,                           ONLY: default_path_length,&
      48              :                                               default_string_length,&
      49              :                                               dp
      50              :    USE machine,                         ONLY: default_output_unit
      51              :    USE mathconstants,                   ONLY: degree,&
      52              :                                               sqrt3
      53              :    USE mathlib,                         ONLY: angle,&
      54              :                                               det_3x3,&
      55              :                                               inv_3x3
      56              :    USE message_passing,                 ONLY: mp_para_env_type
      57              :    USE string_utilities,                ONLY: uppercase
      58              : #include "./base/base_uses.f90"
      59              : 
      60              :    IMPLICIT NONE
      61              : 
      62              :    PRIVATE
      63              : 
      64              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cell_methods'
      65              : 
      66              :    PUBLIC :: cell_create, &
      67              :              init_cell, &
      68              :              read_cell, &
      69              :              read_cell_cif, &
      70              :              read_cell_cp2k, &
      71              :              read_cell_extxyz, &
      72              :              read_cell_pdb, &
      73              :              read_cell_xsc, &
      74              :              set_cell_param, &
      75              :              write_cell, &
      76              :              write_cell_low
      77              : 
      78              : CONTAINS
      79              : 
      80              : ! **************************************************************************************************
      81              : !> \brief allocates and initializes a cell
      82              : !> \param cell the cell to initialize
      83              : !> \param hmat the h matrix that defines the cell
      84              : !> \param periodic periodicity of the cell
      85              : !> \param tag ...
      86              : !> \par History
      87              : !>      09.2003 created [fawzi]
      88              : !> \author Fawzi Mohamed
      89              : ! **************************************************************************************************
      90        82855 :    SUBROUTINE cell_create(cell, hmat, periodic, tag)
      91              : 
      92              :       TYPE(cell_type), POINTER                           :: cell
      93              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN), &
      94              :          OPTIONAL                                        :: hmat
      95              :       INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL        :: periodic
      96              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: tag
      97              : 
      98            0 :       CPASSERT(.NOT. ASSOCIATED(cell))
      99      2485650 :       ALLOCATE (cell)
     100        82855 :       cell%ref_count = 1
     101        82855 :       IF (PRESENT(periodic)) THEN
     102         1340 :          cell%perd = periodic
     103              :       ELSE
     104       330080 :          cell%perd = 1
     105              :       END IF
     106              :       cell%orthorhombic = .FALSE.
     107              :       cell%symmetry_id = cell_sym_none
     108        82855 :       IF (PRESENT(hmat)) CALL init_cell(cell, hmat)
     109        82855 :       IF (PRESENT(tag)) cell%tag = tag
     110              : 
     111        82855 :    END SUBROUTINE cell_create
     112              : 
     113              : ! **************************************************************************************************
     114              : !> \brief   Initialise/readjust a simulation cell after hmat has been changed
     115              : !> \param cell ...
     116              : !> \param hmat ...
     117              : !> \param periodic ...
     118              : !> \date    16.01.2002
     119              : !> \author  Matthias Krack
     120              : !> \version 1.0
     121              : ! **************************************************************************************************
     122       346263 :    SUBROUTINE init_cell(cell, hmat, periodic)
     123              : 
     124              :       TYPE(cell_type), POINTER                           :: cell
     125              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN), &
     126              :          OPTIONAL                                        :: hmat
     127              :       INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL        :: periodic
     128              : 
     129              :       REAL(KIND=dp), PARAMETER                           :: eps_hmat = 1.0E-14_dp
     130              : 
     131              :       INTEGER                                            :: dim
     132              :       REAL(KIND=dp)                                      :: a, acosa, acosah, acosg, alpha, asina, &
     133              :                                                             asinah, asing, beta, gamma, norm, &
     134              :                                                             norm_c
     135              :       REAL(KIND=dp), DIMENSION(3)                        :: abc
     136              : 
     137       346263 :       CPASSERT(ASSOCIATED(cell))
     138              : 
     139       450915 :       IF (PRESENT(hmat)) cell%hmat(:, :) = hmat(:, :)
     140       346347 :       IF (PRESENT(periodic)) cell%perd(:) = periodic(:)
     141              : 
     142       346263 :       cell%deth = ABS(det_3x3(cell%hmat))
     143              : 
     144       346263 :       IF (cell%deth < 1.0E-10_dp) THEN
     145            0 :          CALL write_cell_low(cell, "angstrom", default_output_unit)
     146              :          CALL cp_abort(__LOCATION__, &
     147              :                        "An invalid set of cell vectors was specified. "// &
     148            0 :                        "The cell volume is too small")
     149              :       END IF
     150              : 
     151       350329 :       SELECT CASE (cell%symmetry_id)
     152              :       CASE (cell_sym_cubic, &
     153              :             cell_sym_tetragonal_ab, &
     154              :             cell_sym_tetragonal_ac, &
     155              :             cell_sym_tetragonal_bc, &
     156              :             cell_sym_orthorhombic)
     157         4066 :          CALL get_cell(cell=cell, abc=abc)
     158         4066 :          abc(2) = plane_distance(0, 1, 0, cell=cell)
     159         4066 :          abc(3) = plane_distance(0, 0, 1, cell=cell)
     160         4066 :          SELECT CASE (cell%symmetry_id)
     161              :          CASE (cell_sym_cubic)
     162         5376 :             abc(1:3) = SUM(abc(1:3))/3.0_dp
     163              :          CASE (cell_sym_tetragonal_ab, &
     164              :                cell_sym_tetragonal_ac, &
     165              :                cell_sym_tetragonal_bc)
     166         4066 :             SELECT CASE (cell%symmetry_id)
     167              :             CASE (cell_sym_tetragonal_ab)
     168         1322 :                a = 0.5_dp*(abc(1) + abc(2))
     169         1322 :                abc(1) = a
     170         1322 :                abc(2) = a
     171              :             CASE (cell_sym_tetragonal_ac)
     172          633 :                a = 0.5_dp*(abc(1) + abc(3))
     173          633 :                abc(1) = a
     174          633 :                abc(3) = a
     175              :             CASE (cell_sym_tetragonal_bc)
     176          612 :                a = 0.5_dp*(abc(2) + abc(3))
     177          612 :                abc(2) = a
     178         2567 :                abc(3) = a
     179              :             END SELECT
     180              :          END SELECT
     181         4066 :          cell%hmat(1, 1) = abc(1); cell%hmat(1, 2) = 0.0_dp; cell%hmat(1, 3) = 0.0_dp
     182         4066 :          cell%hmat(2, 1) = 0.0_dp; cell%hmat(2, 2) = abc(2); cell%hmat(2, 3) = 0.0_dp
     183         4066 :          cell%hmat(3, 1) = 0.0_dp; cell%hmat(3, 2) = 0.0_dp; cell%hmat(3, 3) = abc(3)
     184              :       CASE (cell_sym_hexagonal_gamma_60, cell_sym_hexagonal_gamma_120)
     185         2638 :          CALL get_cell(cell=cell, abc=abc)
     186         2638 :          a = 0.5_dp*(abc(1) + abc(2))
     187         2638 :          acosg = 0.5_dp*a
     188         2638 :          asing = sqrt3*acosg
     189         2638 :          IF (cell%symmetry_id == cell_sym_hexagonal_gamma_120) acosg = -acosg
     190         2638 :          cell%hmat(1, 1) = a; cell%hmat(1, 2) = acosg; cell%hmat(1, 3) = 0.0_dp
     191         2638 :          cell%hmat(2, 1) = 0.0_dp; cell%hmat(2, 2) = asing; cell%hmat(2, 3) = 0.0_dp
     192         2638 :          cell%hmat(3, 1) = 0.0_dp; cell%hmat(3, 2) = 0.0_dp; cell%hmat(3, 3) = abc(3)
     193              :       CASE (cell_sym_rhombohedral)
     194          665 :          CALL get_cell(cell=cell, abc=abc)
     195         2660 :          a = SUM(abc(1:3))/3.0_dp
     196              :          alpha = (angle(cell%hmat(:, 3), cell%hmat(:, 2)) + &
     197              :                   angle(cell%hmat(:, 1), cell%hmat(:, 3)) + &
     198          665 :                   angle(cell%hmat(:, 1), cell%hmat(:, 2)))/3.0_dp
     199          665 :          acosa = a*COS(alpha)
     200          665 :          asina = a*SIN(alpha)
     201          665 :          acosah = a*COS(0.5_dp*alpha)
     202          665 :          asinah = a*SIN(0.5_dp*alpha)
     203          665 :          norm = acosa/acosah
     204          665 :          norm_c = SQRT(1.0_dp - norm*norm)
     205          665 :          cell%hmat(1, 1) = a; cell%hmat(1, 2) = acosa; cell%hmat(1, 3) = acosah*norm
     206          665 :          cell%hmat(2, 1) = 0.0_dp; cell%hmat(2, 2) = asina; cell%hmat(2, 3) = asinah*norm
     207          665 :          cell%hmat(3, 1) = 0.0_dp; cell%hmat(3, 2) = 0.0_dp; cell%hmat(3, 3) = a*norm_c
     208              :       CASE (cell_sym_monoclinic)
     209          873 :          CALL get_cell(cell=cell, abc=abc)
     210          873 :          beta = angle(cell%hmat(:, 1), cell%hmat(:, 3))
     211          873 :          cell%hmat(1, 1) = abc(1); cell%hmat(1, 2) = 0.0_dp; cell%hmat(1, 3) = abc(3)*COS(beta)
     212          873 :          cell%hmat(2, 1) = 0.0_dp; cell%hmat(2, 2) = abc(2); cell%hmat(2, 3) = 0.0_dp
     213          873 :          cell%hmat(3, 1) = 0.0_dp; cell%hmat(3, 2) = 0.0_dp; cell%hmat(3, 3) = abc(3)*SIN(beta)
     214              :       CASE (cell_sym_monoclinic_gamma_ab)
     215              :          ! Cell symmetry with a = b, alpha = beta = 90 degree and gammma not equal 90 degree
     216          742 :          CALL get_cell(cell=cell, abc=abc)
     217          742 :          a = 0.5_dp*(abc(1) + abc(2))
     218          742 :          gamma = angle(cell%hmat(:, 1), cell%hmat(:, 2))
     219          742 :          acosg = a*COS(gamma)
     220          742 :          asing = a*SIN(gamma)
     221          742 :          cell%hmat(1, 1) = a; cell%hmat(1, 2) = acosg; cell%hmat(1, 3) = 0.0_dp
     222          742 :          cell%hmat(2, 1) = 0.0_dp; cell%hmat(2, 2) = asing; cell%hmat(2, 3) = 0.0_dp
     223       347005 :          cell%hmat(3, 1) = 0.0_dp; cell%hmat(3, 2) = 0.0_dp; cell%hmat(3, 3) = abc(3)
     224              :       CASE (cell_sym_triclinic)
     225              :          ! Nothing to do
     226              :       END SELECT
     227              : 
     228              :       ! Do we have an (almost) orthorhombic cell?
     229              :       IF ((ABS(cell%hmat(1, 2)) < eps_hmat) .AND. (ABS(cell%hmat(1, 3)) < eps_hmat) .AND. &
     230              :           (ABS(cell%hmat(2, 1)) < eps_hmat) .AND. (ABS(cell%hmat(2, 3)) < eps_hmat) .AND. &
     231       346263 :           (ABS(cell%hmat(3, 1)) < eps_hmat) .AND. (ABS(cell%hmat(3, 2)) < eps_hmat)) THEN
     232       320624 :          cell%orthorhombic = .TRUE.
     233              :       ELSE
     234        25639 :          cell%orthorhombic = .FALSE.
     235              :       END IF
     236              : 
     237              :       ! Retain an exact orthorhombic cell
     238              :       ! (off-diagonal elements must remain zero identically to keep QS fast)
     239       346263 :       IF (cell%orthorhombic) THEN
     240       320624 :          cell%hmat(1, 2) = 0.0_dp
     241       320624 :          cell%hmat(1, 3) = 0.0_dp
     242       320624 :          cell%hmat(2, 1) = 0.0_dp
     243       320624 :          cell%hmat(2, 3) = 0.0_dp
     244       320624 :          cell%hmat(3, 1) = 0.0_dp
     245       320624 :          cell%hmat(3, 2) = 0.0_dp
     246              :       END IF
     247              : 
     248      1385052 :       dim = COUNT(cell%perd == 1)
     249       346263 :       IF ((dim == 1) .AND. (.NOT. cell%orthorhombic)) THEN
     250            0 :          CPABORT("Non-orthorhombic and not periodic")
     251              :       END IF
     252              : 
     253              :       ! Update deth and hmat_inv with enforced symmetry
     254       346263 :       cell%deth = ABS(det_3x3(cell%hmat))
     255       346263 :       IF (cell%deth < 1.0E-10_dp) THEN
     256              :          CALL cp_abort(__LOCATION__, &
     257              :                        "An invalid set of cell vectors was obtained after applying "// &
     258            0 :                        "the requested cell symmetry. The cell volume is too small")
     259              :       END IF
     260      4501419 :       cell%h_inv = inv_3x3(cell%hmat)
     261              : 
     262       346263 :    END SUBROUTINE init_cell
     263              : 
     264              : ! **************************************************************************************************
     265              : !> \brief ...
     266              : !> \param cell ...
     267              : !> \param cell_ref ...
     268              : !> \param use_ref_cell ...
     269              : !> \param cell_section ...
     270              : !> \param topology_section ...
     271              : !> \param check_for_ref ...
     272              : !> \param para_env ...
     273              : !> \par History
     274              : !>      03.2005 created [teo]
     275              : !>      03.2026 revamped logic with pdb and extxyz parsers
     276              : !> \author Teodoro Laino
     277              : ! **************************************************************************************************
     278       185373 :    RECURSIVE SUBROUTINE read_cell(cell, cell_ref, use_ref_cell, cell_section, &
     279              :                                   topology_section, check_for_ref, para_env)
     280              : 
     281              :       TYPE(cell_type), POINTER                           :: cell, cell_ref
     282              :       LOGICAL, INTENT(INOUT), OPTIONAL                   :: use_ref_cell
     283              :       TYPE(section_vals_type), OPTIONAL, POINTER         :: cell_section, topology_section
     284              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_for_ref
     285              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     286              : 
     287              :       REAL(KIND=dp), PARAMETER                           :: eps = EPSILON(0.0_dp)
     288              : 
     289              :       CHARACTER(LEN=default_path_length)                 :: cell_file_name, coord_file_name
     290              :       INTEGER                                            :: cell_file_format, coord_file_format, &
     291              :                                                             my_per
     292        20597 :       INTEGER, DIMENSION(:), POINTER                     :: multiple_unit_cell
     293              :       LOGICAL :: cell_read_a, cell_read_abc, cell_read_alpha_beta_gamma, cell_read_b, cell_read_c, &
     294              :          cell_read_file, my_check_ref, tmp_comb_abc, tmp_comb_cell, tmp_comb_top, topo_read_coord
     295              :       REAL(KIND=dp), DIMENSION(3)                        :: read_ang, read_len
     296              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: read_mat
     297        20597 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cell_par
     298              :       TYPE(cell_type), POINTER                           :: cell_tmp
     299              :       TYPE(section_vals_type), POINTER                   :: cell_ref_section
     300              : 
     301        20597 :       my_check_ref = .TRUE.
     302        20597 :       NULLIFY (cell_ref_section, cell_par, cell_tmp, multiple_unit_cell)
     303              :       ! cell_tmp is only for transferring matrix of cell vectors from
     304              :       ! individual file parser subroutines to read_mat here, assuming
     305              :       ! that unit conversion has been done in those subroutines.
     306        20597 :       CALL cell_create(cell_tmp)
     307        20597 :       IF (.NOT. ASSOCIATED(cell)) CALL cell_create(cell, tag="CELL")
     308        20597 :       IF (.NOT. ASSOCIATED(cell_ref)) CALL cell_create(cell_ref, tag="CELL_REF")
     309        20597 :       IF (PRESENT(check_for_ref)) my_check_ref = check_for_ref
     310              : 
     311        20597 :       cell%deth = 0.0_dp
     312        20597 :       cell%orthorhombic = .FALSE.
     313        82388 :       cell%perd(:) = 1
     314        20597 :       cell%symmetry_id = cell_sym_none
     315       267761 :       cell%hmat(:, :) = 0.0_dp
     316       267761 :       cell%h_inv(:, :) = 0.0_dp
     317              :       cell_read_file = .FALSE.
     318              :       cell_read_a = .FALSE.
     319              :       cell_read_b = .FALSE.
     320              :       cell_read_c = .FALSE.
     321              :       cell_read_abc = .FALSE.
     322              :       cell_read_alpha_beta_gamma = .FALSE.
     323        20597 :       read_mat(:, :) = 0.0_dp
     324        20597 :       read_ang(:) = 0.0_dp
     325        20597 :       read_len(:) = 0.0_dp
     326              : 
     327              :       ! Precedence of retrieving cell information from input:
     328              :       ! 1. CELL/CELL_FILE_NAME
     329              :       ! 2. CELL/ABC and optionally CELL/ALPHA_BETA_GAMMA
     330              :       ! 3. CELL/A, CELL/B, CELL/C
     331              :       ! 4. TOPOLOGY/COORD_FILE_NAME, if topology_section is present
     332              :       ! The actual order of processing is 4 -> 1 -> 2 -> 3, with
     333              :       ! case 4 merged to case 1 (if file format permits) first.
     334              :       ! Store data into either read_mat or read_ang and read_len
     335              :       ! in CP2K units, which will be converted to cell%hmat and A, B, C.
     336        20597 :       CALL section_vals_val_get(cell_section, "A", explicit=cell_read_a)
     337        20597 :       CALL section_vals_val_get(cell_section, "B", explicit=cell_read_b)
     338        20597 :       CALL section_vals_val_get(cell_section, "C", explicit=cell_read_c)
     339        20597 :       CALL section_vals_val_get(cell_section, "ABC", explicit=cell_read_abc)
     340        20597 :       CALL section_vals_val_get(cell_section, "ALPHA_BETA_GAMMA", explicit=cell_read_alpha_beta_gamma)
     341        20597 :       CALL section_vals_val_get(cell_section, "CELL_FILE_NAME", explicit=cell_read_file)
     342              : 
     343              :       ! Case 4
     344        20597 :       tmp_comb_top = (.NOT. (cell_read_file .OR. cell_read_abc))
     345        11691 :       tmp_comb_top = (tmp_comb_top .AND. (.NOT. cell_read_a))
     346            0 :       tmp_comb_top = (tmp_comb_top .AND. (.NOT. cell_read_b))
     347            0 :       tmp_comb_top = (tmp_comb_top .AND. (.NOT. cell_read_c))
     348              :       IF (tmp_comb_top) THEN
     349              :          CALL cp_warn(__LOCATION__, &
     350              :                       "None of the keywords CELL_FILE_NAME, ABC, or A, B, C "// &
     351              :                       "are specified in CELL section. CP2K will now attempt to read "// &
     352              :                       "TOPOLOGY/COORD_FILE_NAME if its format can be parsed for "// &
     353            0 :                       "cell information.")
     354            0 :          IF (ASSOCIATED(topology_section)) THEN
     355            0 :             CALL section_vals_val_get(topology_section, "COORD_FILE_NAME", explicit=topo_read_coord)
     356            0 :             IF (topo_read_coord) THEN
     357            0 :                CALL section_vals_val_get(topology_section, "COORD_FILE_NAME", c_val=coord_file_name)
     358            0 :                CALL section_vals_val_get(topology_section, "COORD_FILE_FORMAT", i_val=coord_file_format)
     359            0 :                SELECT CASE (coord_file_format) ! Add formats with both cell and coord parser manually
     360              :                CASE (do_coord_cif)
     361            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_NAME", c_val=coord_file_name)
     362            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_FORMAT", i_val=do_cell_cif)
     363              :                CASE (do_coord_cp2k)
     364            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_NAME", c_val=coord_file_name)
     365            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_FORMAT", i_val=do_cell_cp2k)
     366              :                CASE (do_coord_pdb)
     367            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_NAME", c_val=coord_file_name)
     368            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_FORMAT", i_val=do_cell_pdb)
     369              :                CASE (do_coord_xyz)
     370            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_NAME", c_val=coord_file_name)
     371            0 :                   CALL section_vals_val_set(cell_section, "CELL_FILE_FORMAT", i_val=do_cell_extxyz)
     372              :                CASE DEFAULT
     373              :                   CALL cp_abort(__LOCATION__, &
     374              :                                 "COORD_FILE_FORMAT is not set to one of the implemented "// &
     375            0 :                                 "CELL_FILE_FORMAT options and cannot be parsed for cell information!")
     376              :                END SELECT
     377              :             ELSE
     378              :                CALL cp_abort(__LOCATION__, &
     379            0 :                              "COORD_FILE_NAME is not set, so no cell information is available!")
     380              :             END IF
     381              :          ELSE
     382              :             CALL cp_warn(__LOCATION__, &
     383              :                          "TOPOLOGY section is not available, so COORD_FILE_NAME cannot "// &
     384            0 :                          "be parsed for cell information in lieu of missing CELL settings.")
     385              :          END IF
     386              :       END IF
     387              :       ! Former logic in SUBROUTINE read_cell_from_external_file is moved here
     388        20597 :       CALL section_vals_val_get(cell_section, "CELL_FILE_NAME", explicit=cell_read_file)
     389        20597 :       IF (cell_read_file) THEN ! Case 1
     390           16 :          tmp_comb_cell = (cell_read_abc .OR. (cell_read_a .OR. (cell_read_b .OR. cell_read_c)))
     391              :          IF (tmp_comb_cell) &
     392              :             CALL cp_warn(__LOCATION__, &
     393              :                          "Cell Information provided through A, B, C, or ABC in conjunction "// &
     394              :                          "with CELL_FILE_NAME. The definition in external file will override "// &
     395            0 :                          "other ones.")
     396           16 :          CALL section_vals_val_get(cell_section, "CELL_FILE_NAME", c_val=cell_file_name)
     397           16 :          CALL section_vals_val_get(cell_section, "CELL_FILE_FORMAT", i_val=cell_file_format)
     398            2 :          SELECT CASE (cell_file_format)
     399              :          CASE (do_cell_cp2k)
     400            2 :             CALL read_cell_cp2k(cell_file_name, cell_tmp, para_env)
     401              :          CASE (do_cell_xsc)
     402            0 :             CALL read_cell_xsc(cell_file_name, cell_tmp, para_env)
     403              :          CASE (do_cell_extxyz)
     404            2 :             CALL read_cell_extxyz(cell_file_name, cell_tmp, para_env)
     405              :          CASE (do_cell_pdb)
     406            2 :             CALL read_cell_pdb(cell_file_name, cell_tmp, para_env)
     407              :          CASE (do_cell_cif)
     408           10 :             CALL read_cell_cif(cell_file_name, cell_tmp, para_env)
     409              :          CASE DEFAULT
     410              :             CALL cp_abort(__LOCATION__, &
     411              :                           "CELL_FILE_FORMAT is not set to one of the implemented "// &
     412           16 :                           "options and cannot be parsed for cell information!")
     413              :          END SELECT
     414          208 :          read_mat = cell_tmp%hmat
     415              :       ELSE
     416        20581 :          IF (cell_read_abc) THEN ! Case 2
     417         8890 :             CALL section_vals_val_get(cell_section, "ABC", r_vals=cell_par)
     418        35560 :             read_len = cell_par
     419         8890 :             CALL section_vals_val_get(cell_section, "ALPHA_BETA_GAMMA", r_vals=cell_par)
     420        35560 :             read_ang = cell_par
     421         8890 :             IF (cell_read_a .OR. cell_read_b .OR. cell_read_c) &
     422              :                CALL cp_warn(__LOCATION__, &
     423              :                             "Cell information provided through vectors A, B or C in conjunction with ABC. "// &
     424            0 :                             "The definition of the ABC keyword will override the one provided by A, B and C.")
     425              :          ELSE ! Case 3
     426        11691 :             tmp_comb_abc = ((cell_read_a .EQV. cell_read_b) .AND. (cell_read_b .EQV. cell_read_c))
     427              :             IF (tmp_comb_abc) THEN
     428        11691 :                CALL section_vals_val_get(cell_section, "A", r_vals=cell_par)
     429        46764 :                read_mat(:, 1) = cell_par(:)
     430        11691 :                CALL section_vals_val_get(cell_section, "B", r_vals=cell_par)
     431        46764 :                read_mat(:, 2) = cell_par(:)
     432        11691 :                CALL section_vals_val_get(cell_section, "C", r_vals=cell_par)
     433        46764 :                read_mat(:, 3) = cell_par(:)
     434        11691 :                IF (cell_read_alpha_beta_gamma) &
     435              :                   CALL cp_warn(__LOCATION__, &
     436              :                                "The keyword ALPHA_BETA_GAMMA is ignored because it was used without the "// &
     437            0 :                                "keyword ABC.")
     438              :             ELSE
     439              :                CALL cp_abort(__LOCATION__, &
     440              :                              "Neither of the keywords CELL_FILE_NAME or ABC are specified, "// &
     441            0 :                              "and cell vector settings in A, B, C are incomplete!")
     442              :             END IF
     443              :          END IF
     444              :       END IF
     445        20597 :       CALL cell_release(cell_tmp)
     446              : 
     447              :       ! Convert read_mat or read_len and read_ang to actual cell%hmat
     448       127525 :       IF (ANY(read_mat(:, :) > eps)) THEN
     449              :          ! Make a warning before storing cell vectors that
     450              :          ! do not form a triangular matrix.
     451              :          IF ((ABS(read_mat(2, 1)) > eps) .OR. &
     452        11707 :              (ABS(read_mat(3, 1)) > eps) .OR. &
     453              :              (ABS(read_mat(3, 2)) > eps)) &
     454              :             CALL cp_warn(__LOCATION__, &
     455              :                          "Cell vectors are read but cell matrix is not "// &
     456              :                          "a lower triangle, not conforming to the program "// &
     457              :                          "convention that A lies along the X-axis and "// &
     458          868 :                          "B is in the XY plane.")
     459       152191 :          cell%hmat = read_mat
     460              :       ELSE
     461        17780 :          IF (ANY(read_ang(:) > eps) .AND. ANY(read_len(:) > eps)) THEN
     462              :             CALL set_cell_param(cell, cell_length=read_len, cell_angle=read_ang, &
     463         8890 :                                 do_init_cell=.FALSE.)
     464              :          ELSE
     465              :             CALL cp_abort(__LOCATION__, &
     466            0 :                           "No meaningful cell information is read from parser!")
     467              :          END IF
     468              :       END IF
     469              :       ! Reset cell section so that only A, B, C are kept
     470        20597 :       CALL reset_cell_section_by_cell_mat(cell, cell_section)
     471              : 
     472              :       ! Multiple unit cell
     473        20597 :       CALL section_vals_val_get(cell_section, "MULTIPLE_UNIT_CELL", i_vals=multiple_unit_cell)
     474        81508 :       IF (ANY(multiple_unit_cell /= 1)) CALL set_multiple_unit_cell(cell, multiple_unit_cell)
     475              : 
     476        20597 :       CALL section_vals_val_get(cell_section, "PERIODIC", i_val=my_per)
     477            0 :       SELECT CASE (my_per)
     478              :       CASE (use_perd_x)
     479            0 :          cell%perd = [1, 0, 0]
     480              :       CASE (use_perd_y)
     481            0 :          cell%perd = [0, 1, 0]
     482              :       CASE (use_perd_z)
     483           32 :          cell%perd = [0, 0, 1]
     484              :       CASE (use_perd_xy)
     485          112 :          cell%perd = [1, 1, 0]
     486              :       CASE (use_perd_xz)
     487           48 :          cell%perd = [1, 0, 1]
     488              :       CASE (use_perd_yz)
     489          192 :          cell%perd = [0, 1, 1]
     490              :       CASE (use_perd_xyz)
     491        52972 :          cell%perd = [1, 1, 1]
     492              :       CASE (use_perd_none)
     493        29032 :          cell%perd = [0, 0, 0]
     494              :       CASE DEFAULT
     495        20597 :          CPABORT("")
     496              :       END SELECT
     497              : 
     498              :       ! Load requested cell symmetry
     499        20597 :       CALL section_vals_val_get(cell_section, "SYMMETRY", i_val=cell%symmetry_id)
     500              : 
     501              :       ! Initialize cell
     502        20597 :       CALL init_cell(cell)
     503              : 
     504        20597 :       IF (my_check_ref) THEN
     505              :          ! Recursive check for reference cell requested
     506        20151 :          cell_ref_section => section_vals_get_subs_vals(cell_section, "CELL_REF")
     507        20151 :          IF (parsed_cp2k_input(cell_ref_section, check_this_section=.TRUE.)) THEN
     508           52 :             IF (PRESENT(use_ref_cell)) use_ref_cell = .TRUE.
     509              :             CALL read_cell(cell_ref, cell_ref, use_ref_cell=use_ref_cell, &
     510              :                            cell_section=cell_ref_section, check_for_ref=.FALSE., &
     511           52 :                            para_env=para_env)
     512              :          ELSE
     513        20099 :             CALL cell_clone(cell, cell_ref, tag="CELL_REF")
     514        20099 :             IF (PRESENT(use_ref_cell)) use_ref_cell = .FALSE.
     515              :          END IF
     516              :       END IF
     517              : 
     518        20597 :    END SUBROUTINE read_cell
     519              : 
     520              : ! **************************************************************************************************
     521              : !> \brief utility function to ease the transition to the new input.
     522              : !>      returns true if the new input was parsed
     523              : !> \param input_file the parsed input file
     524              : !> \param check_this_section ...
     525              : !> \return ...
     526              : !> \author fawzi
     527              : ! **************************************************************************************************
     528        20151 :    FUNCTION parsed_cp2k_input(input_file, check_this_section) RESULT(res)
     529              : 
     530              :       TYPE(section_vals_type), POINTER                   :: input_file
     531              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_this_section
     532              :       LOGICAL                                            :: res
     533              : 
     534              :       LOGICAL                                            :: my_check
     535              :       TYPE(section_vals_type), POINTER                   :: glob_section
     536              : 
     537        20151 :       my_check = .FALSE.
     538        20151 :       IF (PRESENT(check_this_section)) my_check = check_this_section
     539        20151 :       res = ASSOCIATED(input_file)
     540        20151 :       IF (res) THEN
     541        20151 :          CPASSERT(input_file%ref_count > 0)
     542        20151 :          IF (.NOT. my_check) THEN
     543            0 :             glob_section => section_vals_get_subs_vals(input_file, "GLOBAL")
     544            0 :             CALL section_vals_get(glob_section, explicit=res)
     545              :          ELSE
     546        20151 :             CALL section_vals_get(input_file, explicit=res)
     547              :          END IF
     548              :       END IF
     549              : 
     550        20151 :    END FUNCTION parsed_cp2k_input
     551              : 
     552              : ! **************************************************************************************************
     553              : !> \brief   Sets the cell using the internal parameters (a,b,c) (alpha,beta,gamma)
     554              : !>          using the convention: a parallel to the x axis, b in the x-y plane and
     555              : !>          and c univoquely determined; gamma is the angle between a and b; beta
     556              : !>          is the angle between c and a and alpha is the angle between c and b
     557              : !> \param cell ...
     558              : !> \param cell_length ...
     559              : !> \param cell_angle ...
     560              : !> \param periodic ...
     561              : !> \param do_init_cell ...
     562              : !> \date    03.2008
     563              : !> \author  Teodoro Laino
     564              : ! **************************************************************************************************
     565         8918 :    SUBROUTINE set_cell_param(cell, cell_length, cell_angle, periodic, do_init_cell)
     566              : 
     567              :       TYPE(cell_type), POINTER                           :: cell
     568              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: cell_length, cell_angle
     569              :       INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL        :: periodic
     570              :       LOGICAL, INTENT(IN)                                :: do_init_cell
     571              : 
     572              :       REAL(KIND=dp), PARAMETER                           :: eps = EPSILON(0.0_dp)
     573              : 
     574              :       REAL(KIND=dp)                                      :: cos_alpha, cos_beta, cos_gamma, sin_gamma
     575              : 
     576         8918 :       CPASSERT(ASSOCIATED(cell))
     577        35672 :       CPASSERT(ALL(cell_angle /= 0.0_dp))
     578              : 
     579         8918 :       cos_gamma = COS(cell_angle(3)); IF (ABS(cos_gamma) < eps) cos_gamma = 0.0_dp
     580         8918 :       IF (ABS(ABS(cos_gamma) - 1.0_dp) < eps) cos_gamma = SIGN(1.0_dp, cos_gamma)
     581         8918 :       sin_gamma = SIN(cell_angle(3)); IF (ABS(sin_gamma) < eps) sin_gamma = 0.0_dp
     582         8918 :       IF (ABS(ABS(sin_gamma) - 1.0_dp) < eps) sin_gamma = SIGN(1.0_dp, sin_gamma)
     583         8918 :       cos_beta = COS(cell_angle(2)); IF (ABS(cos_beta) < eps) cos_beta = 0.0_dp
     584         8918 :       IF (ABS(ABS(cos_beta) - 1.0_dp) < eps) cos_beta = SIGN(1.0_dp, cos_beta)
     585         8918 :       cos_alpha = COS(cell_angle(1)); IF (ABS(cos_alpha) < eps) cos_alpha = 0.0_dp
     586         8918 :       IF (ABS(ABS(cos_alpha) - 1.0_dp) < eps) cos_alpha = SIGN(1.0_dp, cos_alpha)
     587              : 
     588        35672 :       cell%hmat(:, 1) = [1.0_dp, 0.0_dp, 0.0_dp]
     589        35672 :       cell%hmat(:, 2) = [cos_gamma, sin_gamma, 0.0_dp]
     590        35672 :       cell%hmat(:, 3) = [cos_beta, (cos_alpha - cos_gamma*cos_beta)/sin_gamma, 0.0_dp]
     591         8918 :       cell%hmat(3, 3) = SQRT(1.0_dp - cell%hmat(1, 3)**2 - cell%hmat(2, 3)**2)
     592              : 
     593        35672 :       cell%hmat(:, 1) = cell%hmat(:, 1)*cell_length(1)
     594        35672 :       cell%hmat(:, 2) = cell%hmat(:, 2)*cell_length(2)
     595        35672 :       cell%hmat(:, 3) = cell%hmat(:, 3)*cell_length(3)
     596              : 
     597         8918 :       IF (do_init_cell) THEN
     598           28 :          IF (PRESENT(periodic)) THEN
     599           28 :             CALL init_cell(cell=cell, periodic=periodic)
     600              :          ELSE
     601            0 :             CALL init_cell(cell=cell)
     602              :          END IF
     603              :       END IF
     604              : 
     605         8918 :    END SUBROUTINE set_cell_param
     606              : 
     607              : ! **************************************************************************************************
     608              : !> \brief   Setup of the multiple unit_cell
     609              : !> \param cell ...
     610              : !> \param multiple_unit_cell ...
     611              : !> \date    05.2009
     612              : !> \author  Teodoro Laino [tlaino]
     613              : !> \version 1.0
     614              : ! **************************************************************************************************
     615          300 :    SUBROUTINE set_multiple_unit_cell(cell, multiple_unit_cell)
     616              : 
     617              :       TYPE(cell_type), POINTER                           :: cell
     618              :       INTEGER, DIMENSION(:), POINTER                     :: multiple_unit_cell
     619              : 
     620          300 :       CPASSERT(ASSOCIATED(cell))
     621              : 
     622              :       ! Abort, if one of the value is set to zero
     623         1200 :       IF (ANY(multiple_unit_cell <= 0)) &
     624              :          CALL cp_abort(__LOCATION__, &
     625              :                        "CELL%MULTIPLE_UNIT_CELL accepts only integer values larger than 0! "// &
     626            0 :                        "A value of 0 or negative is meaningless!")
     627              : 
     628              :       ! Scale abc according to user request
     629         1200 :       cell%hmat(:, 1) = cell%hmat(:, 1)*multiple_unit_cell(1)
     630         1200 :       cell%hmat(:, 2) = cell%hmat(:, 2)*multiple_unit_cell(2)
     631         1200 :       cell%hmat(:, 3) = cell%hmat(:, 3)*multiple_unit_cell(3)
     632              : 
     633          300 :    END SUBROUTINE set_multiple_unit_cell
     634              : 
     635              : ! **************************************************************************************************
     636              : !> \brief  Reads cell information from CIF file
     637              : !> \param cif_file_name ...
     638              : !> \param cell ...
     639              : !> \param para_env ...
     640              : !> \date   12.2008
     641              : !> \par    Format Information implemented:
     642              : !>            _cell_length_a
     643              : !>            _cell_length_b
     644              : !>            _cell_length_c
     645              : !>            _cell_angle_alpha
     646              : !>            _cell_angle_beta
     647              : !>            _cell_angle_gamma
     648              : !>
     649              : !> \author Teodoro Laino [tlaino]
     650              : !>         moved from topology_cif (1/2019 JHU)
     651              : ! **************************************************************************************************
     652           48 :    SUBROUTINE read_cell_cif(cif_file_name, cell, para_env)
     653              : 
     654              :       CHARACTER(len=*)                                   :: cif_file_name
     655              :       TYPE(cell_type), POINTER                           :: cell
     656              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     657              : 
     658              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'read_cell_cif'
     659              : 
     660              :       INTEGER                                            :: handle
     661              :       INTEGER, DIMENSION(3)                              :: periodic
     662              :       LOGICAL                                            :: found
     663              :       REAL(KIND=dp), DIMENSION(3)                        :: cell_angles, cell_lengths
     664              :       TYPE(cp_parser_type)                               :: parser
     665              : 
     666           24 :       CALL timeset(routineN, handle)
     667              : 
     668              :       CALL parser_create(parser, cif_file_name, &
     669           24 :                          para_env=para_env, apply_preprocessing=.FALSE.)
     670              : 
     671              :       ! Parsing cell infos
     672           96 :       periodic = 1
     673              :       ! Check for   _cell_length_a
     674              :       CALL parser_search_string(parser, "_cell_length_a", ignore_case=.FALSE., found=found, &
     675           24 :                                 begin_line=.FALSE., search_from_begin_of_file=.TRUE.)
     676           24 :       IF (.NOT. found) &
     677            0 :          CPABORT("The field (_cell_length_a) was not found in CIF file! ")
     678           24 :       CALL cif_get_real(parser, cell_lengths(1))
     679           24 :       cell_lengths(1) = cp_unit_to_cp2k(cell_lengths(1), "angstrom")
     680              : 
     681              :       ! Check for   _cell_length_b
     682              :       CALL parser_search_string(parser, "_cell_length_b", ignore_case=.FALSE., found=found, &
     683           24 :                                 begin_line=.FALSE., search_from_begin_of_file=.TRUE.)
     684           24 :       IF (.NOT. found) &
     685            0 :          CPABORT("The field (_cell_length_b) was not found in CIF file! ")
     686           24 :       CALL cif_get_real(parser, cell_lengths(2))
     687           24 :       cell_lengths(2) = cp_unit_to_cp2k(cell_lengths(2), "angstrom")
     688              : 
     689              :       ! Check for   _cell_length_c
     690              :       CALL parser_search_string(parser, "_cell_length_c", ignore_case=.FALSE., found=found, &
     691           24 :                                 begin_line=.FALSE., search_from_begin_of_file=.TRUE.)
     692           24 :       IF (.NOT. found) &
     693            0 :          CPABORT("The field (_cell_length_c) was not found in CIF file! ")
     694           24 :       CALL cif_get_real(parser, cell_lengths(3))
     695           24 :       cell_lengths(3) = cp_unit_to_cp2k(cell_lengths(3), "angstrom")
     696              : 
     697              :       ! Check for   _cell_angle_alpha
     698              :       CALL parser_search_string(parser, "_cell_angle_alpha", ignore_case=.FALSE., found=found, &
     699           24 :                                 begin_line=.FALSE., search_from_begin_of_file=.TRUE.)
     700           24 :       IF (.NOT. found) &
     701            0 :          CPABORT("The field (_cell_angle_alpha) was not found in CIF file! ")
     702           24 :       CALL cif_get_real(parser, cell_angles(1))
     703           24 :       cell_angles(1) = cp_unit_to_cp2k(cell_angles(1), "deg")
     704              : 
     705              :       ! Check for   _cell_angle_beta
     706              :       CALL parser_search_string(parser, "_cell_angle_beta", ignore_case=.FALSE., found=found, &
     707           24 :                                 begin_line=.FALSE., search_from_begin_of_file=.TRUE.)
     708           24 :       IF (.NOT. found) &
     709            0 :          CPABORT("The field (_cell_angle_beta) was not found in CIF file! ")
     710           24 :       CALL cif_get_real(parser, cell_angles(2))
     711           24 :       cell_angles(2) = cp_unit_to_cp2k(cell_angles(2), "deg")
     712              : 
     713              :       ! Check for   _cell_angle_gamma
     714              :       CALL parser_search_string(parser, "_cell_angle_gamma", ignore_case=.FALSE., found=found, &
     715           24 :                                 begin_line=.FALSE., search_from_begin_of_file=.TRUE.)
     716           24 :       IF (.NOT. found) &
     717            0 :          CPABORT("The field (_cell_angle_gamma) was not found in CIF file! ")
     718           24 :       CALL cif_get_real(parser, cell_angles(3))
     719           24 :       cell_angles(3) = cp_unit_to_cp2k(cell_angles(3), "deg")
     720              : 
     721              :       ! Create cell
     722              :       CALL set_cell_param(cell, cell_lengths, cell_angles, periodic=periodic, &
     723           24 :                           do_init_cell=.TRUE.)
     724              : 
     725           24 :       CALL parser_release(parser)
     726              : 
     727           24 :       CALL timestop(handle)
     728              : 
     729           72 :    END SUBROUTINE read_cell_cif
     730              : 
     731              : ! **************************************************************************************************
     732              : !> \brief  Reads REAL from the CIF file.. This wrapper is needed in order to
     733              : !>         treat properly the accuracy specified in the CIF file, i.e. 3.45(6)
     734              : !> \param parser ...
     735              : !> \param r ...
     736              : !> \date   12.2008
     737              : !> \author Teodoro Laino [tlaino]
     738              : ! **************************************************************************************************
     739          144 :    SUBROUTINE cif_get_real(parser, r)
     740              : 
     741              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     742              :       REAL(KIND=dp), INTENT(OUT)                         :: r
     743              : 
     744              :       CHARACTER(LEN=default_string_length)               :: s_tag
     745              :       INTEGER                                            :: iln
     746              : 
     747          144 :       CALL parser_get_object(parser, s_tag)
     748          144 :       iln = LEN_TRIM(s_tag)
     749          144 :       IF (INDEX(s_tag, "(") /= 0) iln = INDEX(s_tag, "(") - 1
     750          144 :       READ (s_tag(1:iln), *) r
     751              : 
     752          144 :    END SUBROUTINE cif_get_real
     753              : 
     754              : ! **************************************************************************************************
     755              : !> \brief  Reads cell information from comment line of extended xyz file
     756              : !> \param extxyz_file_name ...
     757              : !> \param cell ...
     758              : !> \param para_env ...
     759              : !> \date   03.2026
     760              : !> \par    Extended xyz format has comment on the second line in the form as
     761              : !>               Lattice="Ax Ay Az Bx By Bz Cx Cy Cz"
     762              : !>         where Ax, Ay, Az are three Cartesian components of cell vector A,
     763              : !>         Bx, By, Bz are components of B, Cx, Cy, Cz are components of C,
     764              : !>         all in the unit of angstrom.
     765              : ! **************************************************************************************************
     766            4 :    SUBROUTINE read_cell_extxyz(extxyz_file_name, cell, para_env)
     767              : 
     768              :       CHARACTER(len=*)                                   :: extxyz_file_name
     769              :       TYPE(cell_type), POINTER                           :: cell
     770              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     771              : 
     772              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'read_cell_extxyz'
     773              : 
     774              :       INTEGER                                            :: handle, i, id1, id2, j
     775              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     776              :       TYPE(cp_parser_type)                               :: parser
     777              : 
     778            2 :       CALL timeset(routineN, handle)
     779              : 
     780              :       CALL parser_create(parser, extxyz_file_name, &
     781            2 :                          para_env=para_env, apply_preprocessing=.FALSE.)
     782            2 :       CALL parser_get_next_line(parser, 2)
     783            2 :       CALL uppercase(parser%input_line)
     784            2 :       id1 = INDEX(parser%input_line, "LATTICE=")
     785            2 :       IF (id1 > 0) THEN
     786            2 :          id2 = INDEX(parser%input_line(id1 + 9:), '"')
     787            2 :          READ (parser%input_line(id1 + 9:id1 + id2 + 7), *) hmat(:, 1), hmat(:, 2), hmat(:, 3)
     788            8 :          DO i = 1, 3
     789           26 :             DO j = 1, 3
     790           24 :                cell%hmat(j, i) = cp_unit_to_cp2k(hmat(j, i), "angstrom")
     791              :             END DO
     792              :          END DO
     793              : 
     794              :       ELSE
     795              :          CALL cp_abort(__LOCATION__, &
     796              :                        "The field (lattice=) was not found on comment line "// &
     797              :                        "of XYZ file, so cell information cannot be set via "// &
     798            0 :                        "extended XYZ specification! ")
     799              :       END IF
     800              : 
     801            2 :       CALL parser_release(parser)
     802              : 
     803            2 :       CALL timestop(handle)
     804              : 
     805            6 :    END SUBROUTINE read_cell_extxyz
     806              : 
     807              : ! **************************************************************************************************
     808              : !> \brief  Reads cell information from CRYST1 record of PDB file
     809              : !> \param pdb_file_name ...
     810              : !> \param cell ...
     811              : !> \param para_env ...
     812              : !> \date   03.2026
     813              : !> \par    CRYST1 record may contain space group and Z value at the end,
     814              : !>         but here only the first entries are read:
     815              : !>         COLUMNS       DATA  TYPE    FIELD          DEFINITION
     816              : !>         -------------------------------------------------------------
     817              : !>          1 -  6       Record name   "CRYST1"
     818              : !>          7 - 15       Real(9.3)     a              a (Angstroms).
     819              : !>         16 - 24       Real(9.3)     b              b (Angstroms).
     820              : !>         25 - 33       Real(9.3)     c              c (Angstroms).
     821              : !>         34 - 40       Real(7.2)     alpha          alpha (degrees).
     822              : !>         41 - 47       Real(7.2)     beta           beta (degrees).
     823              : !>         48 - 54       Real(7.2)     gamma          gamma (degrees).
     824              : ! **************************************************************************************************
     825            4 :    SUBROUTINE read_cell_pdb(pdb_file_name, cell, para_env)
     826              : 
     827              :       CHARACTER(len=*)                                   :: pdb_file_name
     828              :       TYPE(cell_type), POINTER                           :: cell
     829              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     830              : 
     831              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'read_cell_pdb'
     832              : 
     833              :       CHARACTER(LEN=default_string_length)               :: cryst
     834              :       INTEGER                                            :: handle, i
     835              :       INTEGER, DIMENSION(3)                              :: periodic
     836              :       LOGICAL                                            :: found
     837              :       REAL(KIND=dp), DIMENSION(3)                        :: cell_angles, cell_lengths
     838              :       TYPE(cp_parser_type)                               :: parser
     839              : 
     840            2 :       CALL timeset(routineN, handle)
     841              : 
     842              :       CALL parser_create(parser, pdb_file_name, &
     843            2 :                          para_env=para_env, apply_preprocessing=.FALSE.)
     844              : 
     845              :       CALL parser_search_string(parser, "CRYST1", ignore_case=.FALSE., found=found, &
     846            2 :                                 begin_line=.TRUE., search_from_begin_of_file=.TRUE.)
     847            2 :       IF (.NOT. found) &
     848            0 :          CPABORT("The field (CRYST1) was not found in PDB file! ")
     849              : 
     850            8 :       periodic = 1
     851            2 :       READ (parser%input_line, *) cryst, cell_lengths(:), cell_angles(:)
     852            8 :       DO i = 1, 3
     853            6 :          cell_lengths(i) = cp_unit_to_cp2k(cell_lengths(i), "angstrom")
     854            8 :          cell_angles(i) = cp_unit_to_cp2k(cell_angles(i), "deg")
     855              :       END DO
     856              :       CALL set_cell_param(cell, cell_lengths, cell_angles, periodic=periodic, &
     857            2 :                           do_init_cell=.TRUE.)
     858              : 
     859            2 :       CALL parser_release(parser)
     860              : 
     861            2 :       CALL timestop(handle)
     862              : 
     863            6 :    END SUBROUTINE read_cell_pdb
     864              : 
     865              : ! **************************************************************************************************
     866              : !> \brief  Reads cell information from cp2k file
     867              : !> \param cp2k_file_name ...
     868              : !> \param cell ...
     869              : !> \param para_env ...
     870              : !> \date   03.2026
     871              : !> \par    Isolated from former read_cell_from_external_file
     872              : ! **************************************************************************************************
     873            4 :    SUBROUTINE read_cell_cp2k(cp2k_file_name, cell, para_env)
     874              : 
     875              :       CHARACTER(len=*)                                   :: cp2k_file_name
     876              :       TYPE(cell_type), POINTER                           :: cell
     877              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     878              : 
     879              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'read_cell_cp2k'
     880              : 
     881              :       INTEGER                                            :: handle, i, idum, j
     882              :       LOGICAL                                            :: my_end
     883              :       REAL(KIND=dp)                                      :: xdum
     884              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     885              :       TYPE(cp_parser_type)                               :: parser
     886              : 
     887            2 :       CALL timeset(routineN, handle)
     888              : 
     889              :       CALL parser_create(parser, cp2k_file_name, &
     890            2 :                          para_env=para_env, apply_preprocessing=.FALSE.)
     891              : 
     892            2 :       CALL parser_get_next_line(parser, 1)
     893            2 :       my_end = .FALSE.
     894           24 :       DO WHILE (.NOT. my_end)
     895           22 :          READ (parser%input_line, *) idum, xdum, hmat(:, 1), hmat(:, 2), hmat(:, 3)
     896           24 :          CALL parser_get_next_line(parser, 1, at_end=my_end)
     897              :       END DO
     898            8 :       DO i = 1, 3
     899           26 :          DO j = 1, 3
     900           24 :             cell%hmat(j, i) = cp_unit_to_cp2k(hmat(j, i), "angstrom")
     901              :          END DO
     902              :       END DO
     903              : 
     904            2 :       CALL parser_release(parser)
     905              : 
     906            2 :       CALL timestop(handle)
     907              : 
     908            6 :    END SUBROUTINE read_cell_cp2k
     909              : 
     910              : ! **************************************************************************************************
     911              : !> \brief  Reads cell information from xsc file
     912              : !> \param xsc_file_name ...
     913              : !> \param cell ...
     914              : !> \param para_env ...
     915              : !> \date   03.2026
     916              : !> \par    Isolated from former read_cell_from_external_file
     917              : ! **************************************************************************************************
     918            0 :    SUBROUTINE read_cell_xsc(xsc_file_name, cell, para_env)
     919              : 
     920              :       CHARACTER(len=*)                                   :: xsc_file_name
     921              :       TYPE(cell_type), POINTER                           :: cell
     922              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     923              : 
     924              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'read_cell_xsc'
     925              : 
     926              :       INTEGER                                            :: handle, i, idum, j
     927              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat
     928              :       TYPE(cp_parser_type)                               :: parser
     929              : 
     930            0 :       CALL timeset(routineN, handle)
     931              : 
     932              :       CALL parser_create(parser, xsc_file_name, &
     933            0 :                          para_env=para_env, apply_preprocessing=.FALSE.)
     934              : 
     935            0 :       CALL parser_get_next_line(parser, 1)
     936            0 :       READ (parser%input_line, *) idum, hmat(:, 1), hmat(:, 2), hmat(:, 3)
     937            0 :       DO i = 1, 3
     938            0 :          DO j = 1, 3
     939            0 :             cell%hmat(j, i) = cp_unit_to_cp2k(hmat(j, i), "angstrom")
     940              :          END DO
     941              :       END DO
     942              : 
     943            0 :       CALL parser_release(parser)
     944              : 
     945            0 :       CALL timestop(handle)
     946              : 
     947            0 :    END SUBROUTINE read_cell_xsc
     948              : 
     949              : ! **************************************************************************************************
     950              : !> \brief   Reset cell section by matrix in cell-type pointer
     951              : !> \param cell ...
     952              : !> \param cell_section ...
     953              : !> \date    03.2026
     954              : !> \par     Alternative keywords for cell settings will be unset
     955              : !>          except MULTIPLE_UNIT_CELL, PERIODIC and SYMMETRY.
     956              : ! **************************************************************************************************
     957        20597 :    SUBROUTINE reset_cell_section_by_cell_mat(cell, cell_section)
     958              : 
     959              :       TYPE(cell_type), POINTER                           :: cell
     960              :       TYPE(section_vals_type), POINTER                   :: cell_section
     961              : 
     962        20597 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cell_par
     963              : 
     964        20597 :       CALL section_vals_val_unset(cell_section, "CELL_FILE_NAME")
     965        20597 :       CALL section_vals_val_unset(cell_section, "CELL_FILE_FORMAT")
     966        20597 :       CALL section_vals_val_unset(cell_section, "ABC")
     967        20597 :       CALL section_vals_val_unset(cell_section, "ALPHA_BETA_GAMMA")
     968        20597 :       CALL section_vals_val_unset(cell_section, "A")
     969        20597 :       CALL section_vals_val_unset(cell_section, "B")
     970        20597 :       CALL section_vals_val_unset(cell_section, "C")
     971        20597 :       ALLOCATE (cell_par(3))
     972       164776 :       cell_par = cell%hmat(:, 1)
     973        20597 :       CALL section_vals_val_set(cell_section, "A", r_vals_ptr=cell_par)
     974        20597 :       ALLOCATE (cell_par(3))
     975       164776 :       cell_par = cell%hmat(:, 2)
     976        20597 :       CALL section_vals_val_set(cell_section, "B", r_vals_ptr=cell_par)
     977        20597 :       ALLOCATE (cell_par(3))
     978       164776 :       cell_par = cell%hmat(:, 3)
     979        20597 :       CALL section_vals_val_set(cell_section, "C", r_vals_ptr=cell_par)
     980              : 
     981        20597 :    END SUBROUTINE reset_cell_section_by_cell_mat
     982              : 
     983              : ! **************************************************************************************************
     984              : !> \brief   Write the cell parameters to the output unit.
     985              : !> \param cell ...
     986              : !> \param subsys_section ...
     987              : !> \param tag ...
     988              : !> \date    02.06.2000
     989              : !> \par     History
     990              : !>    - 11.2008 Teodoro Laino [tlaino] - rewrite and enabling user driven units
     991              : !> \author  Matthias Krack
     992              : !> \version 1.0
     993              : ! **************************************************************************************************
     994        37507 :    SUBROUTINE write_cell(cell, subsys_section, tag)
     995              : 
     996              :       TYPE(cell_type), POINTER                           :: cell
     997              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     998              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: tag
     999              : 
    1000              :       CHARACTER(LEN=default_string_length)               :: label, unit_str
    1001              :       INTEGER                                            :: output_unit
    1002              :       TYPE(cp_logger_type), POINTER                      :: logger
    1003              : 
    1004        37507 :       NULLIFY (logger)
    1005        37507 :       logger => cp_get_default_logger()
    1006        37507 :       IF (PRESENT(tag)) THEN
    1007         9994 :          label = TRIM(tag)//"|"
    1008              :       ELSE
    1009        27513 :          label = TRIM(cell%tag)//"|"
    1010              :       END IF
    1011              : 
    1012        37507 :       output_unit = cp_print_key_unit_nr(logger, subsys_section, "PRINT%CELL", extension=".Log")
    1013        37507 :       CALL section_vals_val_get(subsys_section, "PRINT%CELL%UNIT", c_val=unit_str)
    1014        37507 :       CALL write_cell_low(cell, unit_str, output_unit, label)
    1015        37507 :       CALL cp_print_key_finished_output(output_unit, logger, subsys_section, "PRINT%CELL")
    1016              : 
    1017        37507 :    END SUBROUTINE write_cell
    1018              : 
    1019              : ! **************************************************************************************************
    1020              : !> \brief  Write the cell parameters to the output unit
    1021              : !> \param cell ...
    1022              : !> \param unit_str ...
    1023              : !> \param output_unit ...
    1024              : !> \param label ...
    1025              : !> \date  17.05.2023
    1026              : !> \par   History
    1027              : !>        - Extracted from write_cell (17.05.2023, MK)
    1028              : !> \version 1.0
    1029              : ! **************************************************************************************************
    1030        37507 :    SUBROUTINE write_cell_low(cell, unit_str, output_unit, label)
    1031              : 
    1032              :       TYPE(cell_type), POINTER                           :: cell
    1033              :       CHARACTER(LEN=*), INTENT(IN)                       :: unit_str
    1034              :       INTEGER, INTENT(IN)                                :: output_unit
    1035              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: label
    1036              : 
    1037              :       CHARACTER(LEN=12)                                  :: tag
    1038              :       CHARACTER(LEN=3)                                   :: string
    1039              :       CHARACTER(LEN=default_string_length)               :: my_label
    1040              :       REAL(KIND=dp)                                      :: alpha, beta, gamma, val
    1041              :       REAL(KIND=dp), DIMENSION(3)                        :: abc
    1042              :       TYPE(enumeration_type), POINTER                    :: enum
    1043              :       TYPE(keyword_type), POINTER                        :: keyword
    1044              :       TYPE(section_type), POINTER                        :: section
    1045              : 
    1046        37507 :       NULLIFY (enum)
    1047        37507 :       NULLIFY (keyword)
    1048        37507 :       NULLIFY (section)
    1049              : 
    1050        49047 :       IF (output_unit > 0) THEN
    1051        11540 :          CALL get_cell(cell=cell, abc=abc, alpha=alpha, beta=beta, gamma=gamma, tag=tag)
    1052        11540 :          IF (PRESENT(label)) THEN
    1053        11540 :             my_label = label
    1054              :          ELSE
    1055            0 :             my_label = TRIM(tag)//"|"
    1056              :          END IF
    1057        11540 :          val = cp_unit_from_cp2k(cell%deth, TRIM(unit_str)//"^3")
    1058              :          WRITE (UNIT=output_unit, FMT="(/,T2,A,T61,F20.6)") &
    1059        11540 :             TRIM(my_label)//" Volume ["//TRIM(unit_str)//"^3]:", val
    1060        11540 :          val = cp_unit_from_cp2k(1.0_dp, TRIM(unit_str))
    1061              :          WRITE (UNIT=output_unit, FMT="(T2,A,T30,3F10.3,3X,A6,F12.6)") &
    1062        46160 :             TRIM(my_label)//" Vector a ["//TRIM(unit_str)//"]:", cell%hmat(:, 1)*val, &
    1063        11540 :             "|a| = ", abc(1)*val, &
    1064        46160 :             TRIM(my_label)//" Vector b ["//TRIM(unit_str)//"]:", cell%hmat(:, 2)*val, &
    1065        11540 :             "|b| = ", abc(2)*val, &
    1066        46160 :             TRIM(my_label)//" Vector c ["//TRIM(unit_str)//"]:", cell%hmat(:, 3)*val, &
    1067        23080 :             "|c| = ", abc(3)*val
    1068              :          WRITE (UNIT=output_unit, FMT="(T2,A,T69,F12.6)") &
    1069        11540 :             TRIM(my_label)//" Angle (b,c), alpha [degree]: ", alpha, &
    1070        11540 :             TRIM(my_label)//" Angle (a,c), beta  [degree]: ", beta, &
    1071        23080 :             TRIM(my_label)//" Angle (a,b), gamma [degree]: ", gamma
    1072        11540 :          IF (cell%symmetry_id /= cell_sym_none) THEN
    1073         1464 :             CALL create_cell_section(section)
    1074         1464 :             keyword => section_get_keyword(section, "SYMMETRY")
    1075         1464 :             CALL keyword_get(keyword, enum=enum)
    1076              :             WRITE (UNIT=output_unit, FMT="(T2,A,T61,A20)") &
    1077         1464 :                TRIM(my_label)//" Requested initial symmetry: ", &
    1078         2928 :                ADJUSTR(TRIM(enum_i2c(enum, cell%symmetry_id)))
    1079         1464 :             CALL section_release(section)
    1080              :          END IF
    1081        11540 :          IF (cell%orthorhombic) THEN
    1082              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
    1083         8179 :                TRIM(my_label)//" Numerically orthorhombic: ", "YES"
    1084              :          ELSE
    1085              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
    1086         3361 :                TRIM(my_label)//" Numerically orthorhombic: ", " NO"
    1087              :          END IF
    1088        46160 :          IF (SUM(cell%perd(1:3)) == 0) THEN
    1089              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
    1090         2469 :                TRIM(my_label)//" Periodicity", "NONE"
    1091              :          ELSE
    1092         9071 :             string = ""
    1093         9071 :             IF (cell%perd(1) == 1) string = TRIM(string)//"X"
    1094         9071 :             IF (cell%perd(2) == 1) string = TRIM(string)//"Y"
    1095         9071 :             IF (cell%perd(3) == 1) string = TRIM(string)//"Z"
    1096              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
    1097         9071 :                TRIM(my_label)//" Periodicity", ADJUSTR(string)
    1098              :          END IF
    1099              :       END IF
    1100              : 
    1101        37507 :    END SUBROUTINE write_cell_low
    1102              : 
    1103              : END MODULE cell_methods
        

Generated by: LCOV version 2.0-1