LCOV - code coverage report
Current view: top level - src/motion - cell_opt_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cccd2f3) Lines: 92.9 % 198 184
Test Date: 2026-05-06 07:07:47 Functions: 100.0 % 6 6

            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 a functional that calculates the energy and its derivatives
      10              : !>      for the geometry optimizer
      11              : !> \par History
      12              : !>      03.2008 - Teodoro Laino [tlaino] - University of Zurich - Cell Optimization
      13              : ! **************************************************************************************************
      14              : MODULE cell_opt_utils
      15              :    USE cell_types,                      ONLY: &
      16              :         cell_sym_cubic, cell_sym_hexagonal_gamma_120, cell_sym_hexagonal_gamma_60, &
      17              :         cell_sym_monoclinic, cell_sym_monoclinic_gamma_ab, cell_sym_orthorhombic, &
      18              :         cell_sym_rhombohedral, cell_sym_tetragonal_ab, cell_sym_tetragonal_ac, &
      19              :         cell_sym_tetragonal_bc, cell_sym_triclinic, cell_type
      20              :    USE cp_files,                        ONLY: close_file,&
      21              :                                               open_file
      22              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      23              :                                               cp_logger_create,&
      24              :                                               cp_logger_get_default_unit_nr,&
      25              :                                               cp_logger_release,&
      26              :                                               cp_logger_set,&
      27              :                                               cp_logger_type,&
      28              :                                               cp_to_string
      29              :    USE input_constants,                 ONLY: fix_none,&
      30              :                                               fix_x,&
      31              :                                               fix_xy,&
      32              :                                               fix_xz,&
      33              :                                               fix_y,&
      34              :                                               fix_yz,&
      35              :                                               fix_z
      36              :    USE input_cp2k_global,               ONLY: create_global_section
      37              :    USE input_enumeration_types,         ONLY: enum_i2c,&
      38              :                                               enumeration_type
      39              :    USE input_keyword_types,             ONLY: keyword_get,&
      40              :                                               keyword_type
      41              :    USE input_section_types,             ONLY: section_get_keyword,&
      42              :                                               section_release,&
      43              :                                               section_type,&
      44              :                                               section_vals_type,&
      45              :                                               section_vals_val_get,&
      46              :                                               section_vals_val_set
      47              :    USE kinds,                           ONLY: default_path_length,&
      48              :                                               default_string_length,&
      49              :                                               dp
      50              :    USE mathconstants,                   ONLY: sqrt3
      51              :    USE mathlib,                         ONLY: angle,&
      52              :                                               det_3x3
      53              :    USE message_passing,                 ONLY: mp_para_env_type
      54              : #include "../base/base_uses.f90"
      55              : 
      56              :    IMPLICIT NONE
      57              :    PRIVATE
      58              : 
      59              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      60              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cell_opt_utils'
      61              : 
      62              :    PUBLIC :: get_dg_dh, gopt_new_logger_create, &
      63              :              gopt_new_logger_release, read_external_press_tensor, &
      64              :              apply_cell_constraints, rescale_new_cell_volume
      65              : 
      66              : CONTAINS
      67              : 
      68              : ! **************************************************************************************************
      69              : !> \brief creates a new logger used for cell optimization algorithm
      70              : !> \param new_logger ...
      71              : !> \param root_section ...
      72              : !> \param para_env ...
      73              : !> \param project_name ...
      74              : !> \param id_run ...
      75              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
      76              : ! **************************************************************************************************
      77          930 :    SUBROUTINE gopt_new_logger_create(new_logger, root_section, para_env, project_name, &
      78              :                                      id_run)
      79              :       TYPE(cp_logger_type), POINTER                      :: new_logger
      80              :       TYPE(section_vals_type), POINTER                   :: root_section
      81              :       TYPE(mp_para_env_type), POINTER                    :: para_env
      82              :       CHARACTER(len=default_string_length), INTENT(OUT)  :: project_name
      83              :       INTEGER, INTENT(IN)                                :: id_run
      84              : 
      85              :       CHARACTER(len=default_path_length)                 :: c_val, input_file_path, output_file_path
      86              :       CHARACTER(len=default_string_length)               :: label
      87              :       INTEGER                                            :: i, lp, unit_nr
      88              :       TYPE(cp_logger_type), POINTER                      :: logger
      89              :       TYPE(enumeration_type), POINTER                    :: enum
      90              :       TYPE(keyword_type), POINTER                        :: keyword
      91              :       TYPE(section_type), POINTER                        :: section
      92              : 
      93          930 :       NULLIFY (new_logger, logger, enum, keyword, section)
      94          930 :       logger => cp_get_default_logger()
      95              : 
      96          930 :       CALL create_global_section(section)
      97          930 :       keyword => section_get_keyword(section, "RUN_TYPE")
      98          930 :       CALL keyword_get(keyword, enum=enum)
      99          930 :       label = TRIM(enum_i2c(enum, id_run))
     100          930 :       CALL section_release(section)
     101              : 
     102              :       ! Redirecting output of the sub_calculation to a different file
     103          930 :       CALL section_vals_val_get(root_section, "GLOBAL%PROJECT_NAME", c_val=project_name)
     104          930 :       input_file_path = TRIM(project_name)
     105          930 :       lp = LEN_TRIM(input_file_path)
     106          930 :       i = logger%iter_info%iteration(logger%iter_info%n_rlevel)
     107          930 :       input_file_path(lp + 1:LEN(input_file_path)) = "-"//TRIM(label)//"-"//ADJUSTL(cp_to_string(i))
     108          930 :       lp = LEN_TRIM(input_file_path)
     109          930 :       CALL section_vals_val_set(root_section, "GLOBAL%PROJECT_NAME", c_val=input_file_path(1:lp))
     110          930 :       CALL section_vals_val_set(root_section, "GLOBAL%RUN_TYPE", i_val=id_run)
     111              : 
     112              :       ! Redirecting output into a new file
     113          930 :       output_file_path = input_file_path(1:lp)//".out"
     114          930 :       IF (para_env%is_source()) THEN
     115              :          CALL open_file(file_name=output_file_path, file_status="UNKNOWN", &
     116          465 :                         file_action="WRITE", file_position="APPEND", unit_number=unit_nr)
     117              :       ELSE
     118          465 :          unit_nr = -1
     119              :       END IF
     120              :       CALL cp_logger_create(new_logger, para_env=para_env, default_global_unit_nr=unit_nr, &
     121          930 :                             close_global_unit_on_dealloc=.FALSE.)
     122          930 :       CALL section_vals_val_get(root_section, "GLOBAL%PROJECT", c_val=c_val)
     123          930 :       IF (c_val /= "") THEN
     124          930 :          CALL cp_logger_set(new_logger, local_filename=TRIM(c_val)//"_localLog")
     125              :       END IF
     126          930 :       new_logger%iter_info%project_name = TRIM(c_val)
     127              :       CALL section_vals_val_get(root_section, "GLOBAL%PRINT_LEVEL", &
     128          930 :                                 i_val=new_logger%iter_info%print_level)
     129              : 
     130          930 :    END SUBROUTINE gopt_new_logger_create
     131              : 
     132              : ! **************************************************************************************************
     133              : !> \brief releases a new logger used for cell optimization algorithm
     134              : !> \param new_logger ...
     135              : !> \param root_section ...
     136              : !> \param para_env ...
     137              : !> \param project_name ...
     138              : !> \param id_run ...
     139              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     140              : ! **************************************************************************************************
     141          930 :    SUBROUTINE gopt_new_logger_release(new_logger, root_section, para_env, project_name, id_run)
     142              :       TYPE(cp_logger_type), POINTER                      :: new_logger
     143              :       TYPE(section_vals_type), POINTER                   :: root_section
     144              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     145              :       CHARACTER(len=default_string_length), INTENT(IN)   :: project_name
     146              :       INTEGER, INTENT(IN)                                :: id_run
     147              : 
     148              :       INTEGER                                            :: unit_nr
     149              : 
     150          930 :       IF (para_env%is_source()) THEN
     151          465 :          unit_nr = cp_logger_get_default_unit_nr(new_logger)
     152          465 :          CALL close_file(unit_number=unit_nr)
     153              :       END IF
     154          930 :       CALL cp_logger_release(new_logger)
     155          930 :       CALL section_vals_val_set(root_section, "GLOBAL%RUN_TYPE", i_val=id_run)
     156          930 :       CALL section_vals_val_set(root_section, "GLOBAL%PROJECT_NAME", c_val=project_name)
     157              : 
     158          930 :    END SUBROUTINE gopt_new_logger_release
     159              : 
     160              : ! **************************************************************************************************
     161              : !> \brief Reads the external pressure tensor
     162              : !> \param geo_section ...
     163              : !> \param cell ...
     164              : !> \param pres_ext ...
     165              : !> \param mtrx ...
     166              : !> \param rot ...
     167              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     168              : ! **************************************************************************************************
     169          224 :    SUBROUTINE read_external_press_tensor(geo_section, cell, pres_ext, mtrx, rot)
     170              :       TYPE(section_vals_type), POINTER                   :: geo_section
     171              :       TYPE(cell_type), POINTER                           :: cell
     172              :       REAL(KIND=dp), INTENT(OUT)                         :: pres_ext
     173              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: mtrx
     174              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: rot
     175              : 
     176              :       INTEGER                                            :: i, ind, j
     177              :       LOGICAL                                            :: check
     178              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: pres_ext_tens
     179          224 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: pvals
     180              : 
     181          224 :       NULLIFY (pvals)
     182          224 :       mtrx = 0.0_dp
     183          224 :       pres_ext_tens = 0.0_dp
     184          224 :       pres_ext = 0.0_dp
     185          224 :       CALL section_vals_val_get(geo_section, "EXTERNAL_PRESSURE", r_vals=pvals)
     186          224 :       check = (SIZE(pvals) == 1) .OR. (SIZE(pvals) == 9)
     187          224 :       IF (.NOT. check) &
     188            0 :          CPABORT("EXTERNAL_PRESSURE can have 1 or 9 components only!")
     189              : 
     190          224 :       IF (SIZE(pvals) == 9) THEN
     191              :          ind = 0
     192          448 :          DO i = 1, 3
     193         1456 :             DO j = 1, 3
     194         1008 :                ind = ind + 1
     195         1344 :                pres_ext_tens(j, i) = pvals(ind)
     196              :             END DO
     197              :          END DO
     198              :          ! Also the pressure tensor must be oriented in the same canonical directions
     199              :          ! of the simulation cell
     200         4480 :          pres_ext_tens = MATMUL(TRANSPOSE(rot), pres_ext_tens)
     201          448 :          DO i = 1, 3
     202          448 :             pres_ext = pres_ext + pres_ext_tens(i, i)
     203              :          END DO
     204          112 :          pres_ext = pres_ext/3.0_dp
     205          448 :          DO i = 1, 3
     206          448 :             pres_ext_tens(i, i) = pres_ext_tens(i, i) - pres_ext
     207              :          END DO
     208              :       ELSE
     209          112 :          pres_ext = pvals(1)
     210              :       END IF
     211              : 
     212         2912 :       IF (ANY(pres_ext_tens > 1.0E-5_dp)) THEN
     213            0 :          mtrx = cell%deth*MATMUL(cell%h_inv, MATMUL(pres_ext_tens, TRANSPOSE(cell%h_inv)))
     214              :       END IF
     215              : 
     216          224 :    END SUBROUTINE read_external_press_tensor
     217              : 
     218              : ! **************************************************************************************************
     219              : !> \brief Computes the derivatives for the cell
     220              : !> \param gradient ...
     221              : !> \param av_ptens ...
     222              : !> \param pres_ext ...
     223              : !> \param cell ...
     224              : !> \param mtrx ...
     225              : !> \param keep_angles ...
     226              : !> \param keep_symmetry ...
     227              : !> \param pres_int ...
     228              : !> \param pres_constr ...
     229              : !> \param constraint_id ...
     230              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     231              : ! **************************************************************************************************
     232         5648 :    SUBROUTINE get_dg_dh(gradient, av_ptens, pres_ext, cell, mtrx, keep_angles, &
     233              :                         keep_symmetry, pres_int, pres_constr, constraint_id)
     234              : 
     235              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: gradient
     236              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: av_ptens
     237              :       REAL(KIND=dp), INTENT(IN)                          :: pres_ext
     238              :       TYPE(cell_type), POINTER                           :: cell
     239              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: mtrx
     240              :       LOGICAL, INTENT(IN), OPTIONAL                      :: keep_angles, keep_symmetry
     241              :       REAL(KIND=dp), INTENT(OUT)                         :: pres_int, pres_constr
     242              :       INTEGER, INTENT(IN), OPTIONAL                      :: constraint_id
     243              : 
     244              :       INTEGER                                            :: i, my_constraint_id
     245              :       LOGICAL                                            :: my_keep_angles, my_keep_symmetry
     246              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: correction, pten_hinv_old, ptens
     247              : 
     248         5648 :       my_keep_angles = .FALSE.
     249         5648 :       IF (PRESENT(keep_angles)) my_keep_angles = keep_angles
     250         5648 :       my_keep_symmetry = .FALSE.
     251         5648 :       IF (PRESENT(keep_symmetry)) my_keep_symmetry = keep_symmetry
     252        39536 :       gradient = 0.0_dp
     253         5648 :       IF (PRESENT(constraint_id)) THEN
     254         5648 :          my_constraint_id = constraint_id
     255              :       ELSE
     256            0 :          my_constraint_id = fix_none
     257              :       END IF
     258              : 
     259        39536 :       gradient = 0.0_dp
     260              : 
     261         5648 :       ptens = av_ptens
     262              : 
     263              :       ! Evaluating the internal pressure
     264         5648 :       pres_int = 0.0_dp
     265        22592 :       DO i = 1, 3
     266        22592 :          pres_int = pres_int + ptens(i, i)
     267              :       END DO
     268         5648 :       pres_int = pres_int/3.0_dp
     269              : 
     270            0 :       SELECT CASE (my_constraint_id)
     271              :       CASE (fix_x)
     272            0 :          pres_constr = ptens(2, 2) + ptens(3, 3)
     273              :       CASE (fix_y)
     274            0 :          pres_constr = ptens(1, 1) + ptens(3, 3)
     275              :       CASE (fix_z)
     276            6 :          pres_constr = ptens(1, 1) + ptens(2, 2)
     277              :       CASE (fix_xy)
     278            6 :          pres_constr = ptens(3, 3)
     279              :       CASE (fix_xz)
     280            0 :          pres_constr = ptens(2, 2)
     281              :       CASE (fix_yz)
     282            0 :          pres_constr = ptens(1, 1)
     283              :       CASE (fix_none)
     284         5648 :          pres_constr = ptens(1, 1) + ptens(2, 2) + ptens(3, 3)
     285              :       END SELECT
     286         5648 :       pres_constr = pres_constr/3.0_dp
     287              : 
     288         5648 :       ptens(1, 1) = av_ptens(1, 1) - pres_ext
     289         5648 :       ptens(2, 2) = av_ptens(2, 2) - pres_ext
     290         5648 :       ptens(3, 3) = av_ptens(3, 3) - pres_ext
     291              : 
     292       293696 :       pten_hinv_old = cell%deth*MATMUL(cell%h_inv, ptens)
     293       225920 :       correction = MATMUL(mtrx, cell%hmat)
     294              : 
     295         5648 :       gradient(1) = pten_hinv_old(1, 1) - correction(1, 1)
     296         5648 :       gradient(2) = pten_hinv_old(2, 1) - correction(2, 1)
     297         5648 :       gradient(3) = pten_hinv_old(2, 2) - correction(2, 2)
     298         5648 :       gradient(4) = pten_hinv_old(3, 1) - correction(3, 1)
     299         5648 :       gradient(5) = pten_hinv_old(3, 2) - correction(3, 2)
     300         5648 :       gradient(6) = pten_hinv_old(3, 3) - correction(3, 3)
     301              : 
     302         5648 :       CALL apply_cell_constraints(gradient, cell, my_keep_angles, my_keep_symmetry, my_constraint_id)
     303              : 
     304        39536 :       gradient = -gradient
     305              : 
     306         5648 :    END SUBROUTINE get_dg_dh
     307              : 
     308              : ! **************************************************************************************************
     309              : !> \brief Apply cell constraints
     310              : !> \param gradient ...
     311              : !> \param cell ...
     312              : !> \param keep_angles ...
     313              : !> \param keep_symmetry ...
     314              : !> \param constraint_id ...
     315              : !> \author Matthias Krack (October 26, 2017, MK)
     316              : ! **************************************************************************************************
     317         5648 :    SUBROUTINE apply_cell_constraints(gradient, cell, keep_angles, keep_symmetry, constraint_id)
     318              : 
     319              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: gradient
     320              :       TYPE(cell_type), POINTER                           :: cell
     321              :       LOGICAL, INTENT(IN)                                :: keep_angles, keep_symmetry
     322              :       INTEGER, INTENT(IN)                                :: constraint_id
     323              : 
     324              :       REAL(KIND=dp)                                      :: a, a_length, ab_length, b_length, cosa, &
     325              :                                                             cosah, cosg, deriv_gamma, g, gamma, &
     326              :                                                             norm, norm_b, norm_c, sina, sinah, sing
     327              : 
     328         5648 :       IF (keep_angles) THEN
     329              :          ! If we want to keep the angles constant we have to project out the
     330              :          ! components of the cell angles
     331         2720 :          norm_b = DOT_PRODUCT(cell%hmat(:, 2), cell%hmat(:, 2))
     332         2040 :          norm = DOT_PRODUCT(cell%hmat(1:2, 2), gradient(2:3))
     333         3400 :          gradient(2:3) = cell%hmat(1:2, 2)/norm_b*norm
     334         2720 :          norm_c = DOT_PRODUCT(cell%hmat(:, 3), cell%hmat(:, 3))
     335         2720 :          norm = DOT_PRODUCT(cell%hmat(1:3, 3), gradient(4:6))
     336         4760 :          gradient(4:6) = cell%hmat(1:3, 3)/norm_c*norm
     337              :          ! Retain an exact orthorhombic cell
     338              :          ! (off-diagonal elements must remain zero identically to keep QS fast)
     339          680 :          IF (cell%orthorhombic) THEN
     340           98 :             gradient(2) = 0.0_dp
     341           98 :             gradient(4) = 0.0_dp
     342           98 :             gradient(5) = 0.0_dp
     343              :          END IF
     344              :       END IF
     345              : 
     346         5648 :       IF (keep_symmetry) THEN
     347         3080 :          SELECT CASE (cell%symmetry_id)
     348              :          CASE (cell_sym_cubic, &
     349              :                cell_sym_tetragonal_ab, &
     350              :                cell_sym_tetragonal_ac, &
     351              :                cell_sym_tetragonal_bc, &
     352              :                cell_sym_orthorhombic)
     353          100 :             SELECT CASE (cell%symmetry_id)
     354              :             CASE (cell_sym_cubic)
     355          100 :                g = (gradient(1) + gradient(3) + gradient(6))/3.0_dp
     356          100 :                gradient(1) = g
     357          100 :                gradient(3) = g
     358          100 :                gradient(6) = g
     359              :             CASE (cell_sym_tetragonal_ab, &
     360              :                   cell_sym_tetragonal_ac, &
     361              :                   cell_sym_tetragonal_bc)
     362          564 :                SELECT CASE (cell%symmetry_id)
     363              :                CASE (cell_sym_tetragonal_ab)
     364          186 :                   g = 0.5_dp*(gradient(1) + gradient(3))
     365          186 :                   gradient(1) = g
     366          186 :                   gradient(3) = g
     367              :                CASE (cell_sym_tetragonal_ac)
     368           89 :                   g = 0.5_dp*(gradient(1) + gradient(6))
     369           89 :                   gradient(1) = g
     370           89 :                   gradient(6) = g
     371              :                CASE (cell_sym_tetragonal_bc)
     372           86 :                   g = 0.5_dp*(gradient(3) + gradient(6))
     373           86 :                   gradient(3) = g
     374          361 :                   gradient(6) = g
     375              :                END SELECT
     376              :             CASE (cell_sym_orthorhombic)
     377              :                ! Nothing else to do
     378              :             END SELECT
     379          564 :             gradient(2) = 0.0_dp
     380          564 :             gradient(4) = 0.0_dp
     381          564 :             gradient(5) = 0.0_dp
     382              :          CASE (cell_sym_hexagonal_gamma_60)
     383          236 :             g = 0.5_dp*(gradient(1) + 0.5_dp*(gradient(2) + sqrt3*gradient(3)))
     384          236 :             gradient(1) = g
     385          236 :             gradient(2) = 0.5_dp*g
     386          236 :             gradient(3) = sqrt3*gradient(2)
     387          236 :             gradient(4) = 0.0_dp
     388          236 :             gradient(5) = 0.0_dp
     389              :          CASE (cell_sym_hexagonal_gamma_120)
     390          118 :             g = 0.5_dp*(gradient(1) - 0.5_dp*(gradient(2) - sqrt3*gradient(3)))
     391          118 :             gradient(1) = g
     392          118 :             gradient(2) = -0.5_dp*g
     393          118 :             gradient(3) = -sqrt3*gradient(2)
     394          118 :             gradient(4) = 0.0_dp
     395          118 :             gradient(5) = 0.0_dp
     396              :          CASE (cell_sym_rhombohedral)
     397              :             a = (angle(cell%hmat(:, 3), cell%hmat(:, 2)) + &
     398              :                  angle(cell%hmat(:, 1), cell%hmat(:, 3)) + &
     399           93 :                  angle(cell%hmat(:, 1), cell%hmat(:, 2)))/3.0_dp
     400           93 :             cosa = COS(a)
     401           93 :             sina = SIN(a)
     402           93 :             cosah = COS(0.5_dp*a)
     403           93 :             sinah = SIN(0.5_dp*a)
     404           93 :             norm = cosa/cosah
     405           93 :             norm_c = SQRT(1.0_dp - norm*norm)
     406              :             g = (gradient(1) + gradient(2)*cosa + gradient(3)*sina + &
     407           93 :                  gradient(4)*cosah*norm + gradient(5)*sinah*norm + gradient(6)*norm_c)/3.0_dp
     408           93 :             gradient(1) = g
     409           93 :             gradient(2) = g*cosa
     410           93 :             gradient(3) = g*sina
     411           93 :             gradient(4) = g*cosah*norm
     412           93 :             gradient(5) = g*sinah*norm
     413           93 :             gradient(6) = g*norm_c
     414              :          CASE (cell_sym_monoclinic)
     415         1177 :             gradient(2) = 0.0_dp
     416         1177 :             gradient(5) = 0.0_dp
     417              :          CASE (cell_sym_monoclinic_gamma_ab)
     418              :             ! Cell symmetry with a = b, alpha = beta = 90 degree and gammma not equal 90 degree
     419              :             a_length = SQRT(cell%hmat(1, 1)*cell%hmat(1, 1) + &
     420              :                             cell%hmat(2, 1)*cell%hmat(2, 1) + &
     421          106 :                             cell%hmat(3, 1)*cell%hmat(3, 1))
     422              :             b_length = SQRT(cell%hmat(1, 2)*cell%hmat(1, 2) + &
     423              :                             cell%hmat(2, 2)*cell%hmat(2, 2) + &
     424          106 :                             cell%hmat(3, 2)*cell%hmat(3, 2))
     425          106 :             ab_length = 0.5_dp*(a_length + b_length)
     426          106 :             gamma = angle(cell%hmat(:, 1), cell%hmat(:, 2))
     427          106 :             cosg = COS(gamma)
     428          106 :             sing = SIN(gamma)
     429              :             ! Here, g is the average derivative of the cell vector length ab_length, and deriv_gamma is the derivative of the angle gamma
     430          106 :             g = 0.5_dp*(gradient(1) + cosg*gradient(2) + sing*gradient(3))
     431          106 :             deriv_gamma = (gradient(3)*cosg - gradient(2)*sing)/b_length
     432          106 :             gradient(1) = g
     433          106 :             gradient(2) = g*cosg - ab_length*sing*deriv_gamma
     434          106 :             gradient(3) = g*sing + ab_length*cosg*deriv_gamma
     435          106 :             gradient(4) = 0.0_dp
     436         2516 :             gradient(5) = 0.0_dp
     437              :          CASE (cell_sym_triclinic)
     438              :             ! Nothing to do
     439              :          END SELECT
     440              :       END IF
     441              : 
     442         5648 :       SELECT CASE (constraint_id)
     443              :       CASE (fix_x)
     444            0 :          gradient(1:2) = 0.0_dp
     445            0 :          gradient(4) = 0.0_dp
     446              :       CASE (fix_y)
     447            0 :          gradient(2:3) = 0.0_dp
     448            0 :          gradient(5) = 0.0_dp
     449              :       CASE (fix_z)
     450           24 :          gradient(4:6) = 0.0_dp
     451              :       CASE (fix_xy)
     452           36 :          gradient(1:5) = 0.0_dp
     453              :       CASE (fix_xz)
     454            0 :          gradient(1:2) = 0.0_dp
     455            0 :          gradient(4:6) = 0.0_dp
     456              :       CASE (fix_yz)
     457         5648 :          gradient(2:6) = 0.0_dp
     458              :       CASE (fix_none)
     459              :          ! Nothing to do
     460              :       END SELECT
     461              : 
     462         5648 :    END SUBROUTINE apply_cell_constraints
     463              : 
     464              : ! **************************************************************************************************
     465              : !> \brief Rescale x(idg+1:idg+6) according to vol
     466              : !> \param vol ...
     467              : !> \param x ...
     468              : !> \param idg ...
     469              : ! **************************************************************************************************
     470         2278 :    SUBROUTINE rescale_new_cell_volume(vol, x, idg)
     471              : 
     472              :       REAL(KIND=dp), INTENT(IN)                          :: vol
     473              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x
     474              :       INTEGER, INTENT(IN)                                :: idg
     475              : 
     476              :       INTEGER                                            :: i, j, my_idg
     477              :       REAL(KIND=dp)                                      :: ratio
     478              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat_tmp
     479              : 
     480         2278 :       CPASSERT((SIZE(x) == idg + 6))
     481         2278 :       my_idg = idg
     482              : 
     483         2278 :       hmat_tmp(:, :) = 0.0_dp
     484         9112 :       DO i = 1, 3
     485        22780 :          DO j = 1, i
     486        13668 :             my_idg = my_idg + 1
     487        20502 :             hmat_tmp(j, i) = x(my_idg)
     488              :          END DO
     489              :       END DO
     490              : 
     491         2278 :       ratio = vol/ABS(det_3x3(hmat_tmp))
     492         2278 :       ratio = ratio**(1.0_dp/3.0_dp) ! no need to use EXP(LOG(ratio)/3) for cube root
     493              : 
     494         2278 :       my_idg = idg
     495         9112 :       DO i = 1, 3
     496        22780 :          DO j = 1, i
     497        13668 :             my_idg = my_idg + 1
     498        20502 :             x(my_idg) = x(my_idg)*ratio
     499              :          END DO
     500              :       END DO
     501              : 
     502         2278 :    END SUBROUTINE rescale_new_cell_volume
     503              : 
     504              : END MODULE cell_opt_utils
        

Generated by: LCOV version 2.0-1