LCOV - code coverage report
Current view: top level - src/motion - cell_opt_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:50c68ef) Lines: 91.5 % 59 54
Test Date: 2026-10-22 00:56:13 Functions: 75.0 % 4 3

            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 Contains type used for a Simulation Cell Optimization
      10              : !> \par History
      11              : !>      none
      12              : !> \author Teodoro Laino - created [tlaino] - 03.2008 - Zurich University
      13              : ! **************************************************************************************************
      14              : MODULE cell_opt_types
      15              : 
      16              :    USE cell_methods,                    ONLY: canonicalize_cell_matrix,&
      17              :                                               cell_create
      18              :    USE cell_opt_utils,                  ONLY: cell_opt_constraint_label,&
      19              :                                               keep_angles_conflict,&
      20              :                                               keep_symmetry_conflict,&
      21              :                                               keep_symmetry_coupled_set,&
      22              :                                               mask_shear,&
      23              :                                               parse_cell_constraint,&
      24              :                                               pres_crit_shear_pinned,&
      25              :                                               read_external_press_tensor
      26              :    USE cell_types,                      ONLY: cell_clone,&
      27              :                                               cell_release,&
      28              :                                               cell_type
      29              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      30              :                                               cp_logger_type
      31              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      32              :                                               cp_print_key_unit_nr
      33              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      34              :    USE force_env_types,                 ONLY: force_env_get,&
      35              :                                               force_env_type
      36              :    USE input_constants,                 ONLY: fix_none
      37              :    USE input_section_types,             ONLY: section_vals_type,&
      38              :                                               section_vals_val_get,&
      39              :                                               section_vals_val_set
      40              :    USE kinds,                           ONLY: default_string_length,&
      41              :                                               dp
      42              :    USE string_utilities,                ONLY: uppercase
      43              : #include "../base/base_uses.f90"
      44              : 
      45              :    IMPLICIT NONE
      46              :    PRIVATE
      47              : 
      48              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cell_opt_types'
      49              : 
      50              :    PUBLIC :: cell_opt_env_type, &
      51              :              cell_opt_env_create, &
      52              :              cell_opt_env_release
      53              : 
      54              : ! **************************************************************************************************
      55              : !> \brief Type containing all informations abour the simulation cell optimization
      56              : !> \par History
      57              : !>      none
      58              : !> \author Teodoro Laino - created [tlaino] - 03.2008 - Zurich University
      59              : ! **************************************************************************************************
      60              :    TYPE cell_opt_env_type
      61              :       ! Simulation cell optimization parameters
      62              :       ! constraint_id is a mask of fixed cell components (comp_* / mask_*):
      63              :       ! a set bit means fixed, 0 (= fix_none) leaves all components relaxable
      64              :       INTEGER                                    :: constraint_id = fix_none
      65              :       LOGICAL                                    :: keep_angles = .FALSE., &
      66              :                                                     keep_symmetry = .FALSE., &
      67              :                                                     keep_volume = .FALSE.
      68              :       REAL(KIND=dp)                              :: pres_ext = 0.0_dp, pres_int = 0.0_dp, pres_tol = 0.0_dp, pres_constr = 0.0_dp
      69              :       REAL(KIND=dp), DIMENSION(3, 3)             :: mtrx = 0.0_dp
      70              :       ! Fixed rotations between the user's Cartesian frame and the canonical
      71              :       ! frame used for the six independent cell optimization variables.
      72              :       REAL(KIND=dp), DIMENSION(3, 3)             :: input_to_opt = 0.0_dp, &
      73              :                                                     opt_to_input = 0.0_dp
      74              :       TYPE(cell_type), POINTER                   :: opt_cell => NULL()
      75              :    END TYPE cell_opt_env_type
      76              : 
      77              : CONTAINS
      78              : 
      79              : ! **************************************************************************************************
      80              : !> \brief ...
      81              : !> \param cell_env ...
      82              : !> \param force_env ...
      83              : !> \param geo_section ...
      84              : !> \par History
      85              : !>      none
      86              : !> \author Teodoro Laino - created [tlaino] - 03.2008 - Zurich University
      87              : ! **************************************************************************************************
      88         8658 :    SUBROUTINE cell_opt_env_create(cell_env, force_env, geo_section)
      89              :       TYPE(cell_opt_env_type), INTENT(OUT)               :: cell_env
      90              :       TYPE(force_env_type), POINTER                      :: force_env
      91              :       TYPE(section_vals_type), POINTER                   :: geo_section
      92              : 
      93              :       CHARACTER(LEN=default_string_length)               :: label
      94              :       CHARACTER(LEN=default_string_length), &
      95          234 :          DIMENSION(:), POINTER                           :: canonical_tokens, constraint_tokens
      96              :       INTEGER                                            :: output_unit
      97              :       LOGICAL                                            :: constraint_explicit
      98              :       TYPE(cell_type), POINTER                           :: cell
      99              :       TYPE(cp_logger_type), POINTER                      :: logger
     100              : 
     101          234 :       NULLIFY (cell_env%opt_cell, cell, canonical_tokens, constraint_tokens)
     102          234 :       CALL force_env_get(force_env, cell=cell)
     103          234 :       CALL cell_create(cell_env%opt_cell)
     104          234 :       CALL cell_clone(cell, cell_env%opt_cell, tag="CELL_OPT_CANONICAL")
     105          234 :       CALL canonicalize_cell_matrix(cell_env%opt_cell)
     106              :       ! Keep the physical cell in the input orientation while the optimizer
     107              :       ! works with the canonical cell and its six non-redundant components.
     108        12168 :       cell_env%input_to_opt = MATMUL(cell_env%opt_cell%hmat, cell%h_inv)
     109        12168 :       cell_env%opt_to_input = MATMUL(cell%hmat, cell_env%opt_cell%h_inv)
     110          234 :       CALL section_vals_val_get(geo_section, "KEEP_VOLUME", l_val=cell_env%keep_volume)
     111          234 :       CALL section_vals_val_get(geo_section, "KEEP_ANGLES", l_val=cell_env%keep_angles)
     112          234 :       CALL section_vals_val_get(geo_section, "KEEP_SYMMETRY", l_val=cell_env%keep_symmetry)
     113          234 :       CALL section_vals_val_get(geo_section, "PRESSURE_TOLERANCE", r_val=cell_env%pres_tol)
     114              :       CALL section_vals_val_get(geo_section, "CONSTRAINT", &
     115          234 :                                 c_vals=constraint_tokens, explicit=constraint_explicit)
     116              :       CALL parse_cell_constraint(constraint_tokens, cell, constraint_explicit, &
     117          234 :                                  cell_env%constraint_id)
     118              :       ! Only for explicitly set values: an unset keyword must stay unparsed so
     119              :       ! the restart echo keeps omitting the line, as it always has.
     120          234 :       IF (constraint_explicit) THEN
     121          102 :          ALLOCATE (canonical_tokens(SIZE(constraint_tokens)))
     122          114 :          canonical_tokens = constraint_tokens
     123           74 :          CALL uppercase(canonical_tokens)
     124           34 :          CALL section_vals_val_set(geo_section, "CONSTRAINT", c_vals_ptr=canonical_tokens)
     125              :       END IF
     126              : 
     127          234 :       CALL cell_opt_validate_constraint(cell_env)
     128              : 
     129              :       ! The masked pressure criterion is structurally off target for this
     130              :       ! combination on a non-orthorhombic cell. The run stays legal: the
     131              :       ! geometry criteria still work, and the pressure criterion may still
     132              :       ! be met when the pinned shear stresses vanish by symmetry. The
     133              :       ! decision lives in pres_crit_shear_pinned, which the unit test
     134              :       ! checks over all 64 masks.
     135          234 :       IF (pres_crit_shear_pinned(cell_env%constraint_id, &
     136              :                                  cell_env%opt_cell%orthorhombic, &
     137              :                                  cell_env%keep_angles)) THEN
     138            4 :          IF (IAND(cell_env%constraint_id, mask_shear) /= 0) THEN
     139              :             CALL cp_warn(__LOCATION__, &
     140              :                          "CELL_OPT: CONSTRAINT ("// &
     141              :                          TRIM(cell_opt_constraint_label(cell_env%constraint_id))// &
     142              :                          ") pins a shear component of a non-orthorhombic cell. "// &
     143              :                          "The masked pressure criterion is met at the constrained minimum "// &
     144              :                          "only if the stresses conjugate to the pinned components vanish "// &
     145              :                          "there, for example when the pinned values are the stress-free "// &
     146              :                          "ones; otherwise it can stay off the external pressure. Check "// &
     147              :                          "the per-step ""Pressure is converged"" line: with L-BFGS the "// &
     148              :                          """run CONVERGED"" banner can appear while it is NO. The "// &
     149            2 :                          "projected-stress criterion planned in #6031 removes this limitation.")
     150              :          ELSE
     151              :             CALL cp_warn(__LOCATION__, &
     152              :                          "CELL_OPT: CONSTRAINT ("// &
     153              :                          TRIM(cell_opt_constraint_label(cell_env%constraint_id))// &
     154              :                          ") fixes a diagonal component while KEEP_ANGLES pins the "// &
     155              :                          "angles of a non-orthorhombic cell. The masked pressure criterion "// &
     156              :                          "is met at the constrained minimum only if the stresses conjugate "// &
     157              :                          "to the pinned components vanish there, for example when the "// &
     158              :                          "pinned values are the stress-free ones; otherwise it can stay "// &
     159              :                          "off the external pressure. Check the per-step ""Pressure is "// &
     160              :                          "converged"" line: with L-BFGS the ""run CONVERGED"" banner can "// &
     161              :                          "appear while it is NO. The projected-stress criterion planned "// &
     162            2 :                          "in #6031 removes this limitation.")
     163              :          END IF
     164              :       END IF
     165              : 
     166              :       ! Get the external pressure
     167              :       CALL read_external_press_tensor(geo_section, cell_env%opt_cell, cell_env%pres_ext, &
     168          234 :                                       cell_env%mtrx, cell_env%input_to_opt)
     169              : 
     170              :       ! Print cell optimisation setup
     171          234 :       NULLIFY (logger)
     172          234 :       logger => cp_get_default_logger()
     173          234 :       output_unit = cp_print_key_unit_nr(logger, geo_section, "PRINT%CELL", extension=".Log")
     174          234 :       IF (output_unit > 0) THEN
     175              :          WRITE (UNIT=output_unit, FMT="(/,T2,A,T61,F20.1)") &
     176          117 :             "CELL_OPT| Pressure tolerance [bar]: ", cp_unit_from_cp2k(cell_env%pres_tol, "bar")
     177          117 :          IF (cell_env%keep_volume) THEN
     178              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
     179            3 :                "CELL_OPT| Keep volume of cell: ", "YES"
     180              :          ELSE
     181              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
     182          114 :                "CELL_OPT| Keep volume of cell: ", " NO"
     183              :          END IF
     184          117 :          IF (cell_env%keep_angles) THEN
     185              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
     186           21 :                "CELL_OPT| Keep angles between the cell vectors: ", "YES"
     187              :          ELSE
     188              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
     189           96 :                "CELL_OPT| Keep angles between the cell vectors: ", " NO"
     190              :          END IF
     191          117 :          IF (cell_env%keep_symmetry) THEN
     192              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
     193           21 :                "CELL_OPT| Keep cell symmetry: ", "YES"
     194              :          ELSE
     195              :             WRITE (UNIT=output_unit, FMT="(T2,A,T78,A3)") &
     196           96 :                "CELL_OPT| Keep cell symmetry: ", " NO"
     197              :          END IF
     198          117 :          label = cell_opt_constraint_label(cell_env%constraint_id)
     199          468 :          IF (COUNT(cell%perd /= 0) == 2 .AND. .NOT. constraint_explicit) THEN
     200            1 :             label = TRIM(label)//" (auto)"
     201              :          END IF
     202              :          WRITE (UNIT=output_unit, FMT="(T2,A,T77,A)") &
     203          117 :             "CELL_OPT| Constraint: ", TRIM(label)
     204              :       END IF
     205          234 :       CALL cp_print_key_finished_output(output_unit, logger, geo_section, "PRINT%CELL")
     206              : 
     207          468 :    END SUBROUTINE cell_opt_env_create
     208              : 
     209              : ! **************************************************************************************************
     210              : !> \brief Abort on constraint combinations that corrupt the KEEP_* projections
     211              : !> \param cell_env ...
     212              : ! **************************************************************************************************
     213          234 :    SUBROUTINE cell_opt_validate_constraint(cell_env)
     214              :       TYPE(cell_opt_env_type), INTENT(IN)                :: cell_env
     215              : 
     216              :       LOGICAL                                            :: bad_constraint
     217              : 
     218              :       ! Reject CONSTRAINT combinations that would silently corrupt the
     219              :       ! KEEP_ANGLES projection or the KEEP_SYMMETRY symmetrization.
     220              :       ! Slot order of apply_cell_constraints: AX, BX, BY, CX, CY, CZ.
     221              :       ! KEEP_ANGLES projects the gradient slots {BX,BY} onto b and {CX,CY,CZ} onto c.
     222              :       ! Gradient slots that a legacy value zeroes:
     223              :       !    x  = {AX,BX,CX}          B partial,  C partial   -> breaks parallelism
     224              :       !    y  = {BX,BY,CY}          B complete, C partial   -> breaks parallelism
     225              :       !    z  = {CX,CY,CZ}          B untouched, C complete -> safe
     226              :       !    xy = {AX..CY}            B complete, C partial   -> breaks parallelism
     227              :       !    xz = {AX,BX,CX,CY,CZ}    B partial,  C complete  -> breaks parallelism
     228              :       !    yz = {BX..CZ}            B complete, C complete  -> safe
     229              :       ! A partial group breaks the parallelism. A complete or untouched group keeps it.
     230          234 :       IF (cell_env%keep_angles) THEN
     231              :          ! The decision lives in keep_angles_conflict, which the unit test
     232              :          ! checks over all 64 masks.
     233           42 :          IF (keep_angles_conflict(cell_env%constraint_id, &
     234              :                                   cell_env%opt_cell%orthorhombic)) THEN
     235              :             CALL cp_abort(__LOCATION__, &
     236              :                           "CELL_OPT: CONSTRAINT ("// &
     237              :                           TRIM(cell_opt_constraint_label(cell_env%constraint_id))// &
     238              :                           ") fixes only part of the b or c cell vector and would "// &
     239            0 :                           "destroy the KEEP_ANGLES projection.")
     240              :          END IF
     241              :       END IF
     242              : 
     243          234 :       IF (cell_env%keep_symmetry .AND. cell_env%constraint_id /= fix_none) THEN
     244              :          ! The decision lives in keep_symmetry_conflict, which the unit test
     245              :          ! checks over all 64 masks for every crystal system.
     246              :          bad_constraint = keep_symmetry_conflict(cell_env%constraint_id, &
     247            0 :                                                  cell_env%opt_cell%symmetry_id)
     248            0 :          IF (bad_constraint) THEN
     249              :             CALL cp_abort(__LOCATION__, &
     250              :                           "CELL_OPT: CONSTRAINT ("// &
     251              :                           TRIM(cell_opt_constraint_label(cell_env%constraint_id))// &
     252              :                           ") fixes only part of the components coupled by "// &
     253              :                           "KEEP_SYMMETRY ("// &
     254              :                           TRIM(cell_opt_constraint_label( &
     255              :                                keep_symmetry_coupled_set(cell_env%opt_cell%symmetry_id)))// &
     256            0 :                           ") and would break the cell symmetry.")
     257              :          END IF
     258              :       END IF
     259              : 
     260          234 :    END SUBROUTINE cell_opt_validate_constraint
     261              : 
     262              : ! **************************************************************************************************
     263              : !> \brief ...
     264              : !> \param cell_env ...
     265              : !> \par History
     266              : !>      none
     267              : !> \author Teodoro Laino - created [tlaino] - 03.2008 - Zurich University
     268              : ! **************************************************************************************************
     269          234 :    SUBROUTINE cell_opt_env_release(cell_env)
     270              :       TYPE(cell_opt_env_type), INTENT(INOUT)             :: cell_env
     271              : 
     272          234 :       CALL cell_release(cell_env%opt_cell)
     273              : 
     274          234 :    END SUBROUTINE cell_opt_env_release
     275              : 
     276            0 : END MODULE cell_opt_types
        

Generated by: LCOV version 2.0-1