LCOV - code coverage report
Current view: top level - src/motion - gopt_f_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:7641cd9) Lines: 98.2 % 392 385
Test Date: 2026-05-25 07:16:39 Functions: 100.0 % 15 15

            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              : !>      none
      13              : ! **************************************************************************************************
      14              : MODULE gopt_f_methods
      15              : 
      16              :    USE atomic_kind_list_types, ONLY: atomic_kind_list_type
      17              :    USE atomic_kind_types, ONLY: atomic_kind_type, &
      18              :                                 get_atomic_kind_set
      19              :    USE cell_methods, ONLY: cell_create, &
      20              :                            init_cell
      21              :    USE cell_types, ONLY: cell_copy, &
      22              :                          cell_release, &
      23              :                          cell_type, &
      24              :                          real_to_scaled, &
      25              :                          scaled_to_real
      26              :    USE cp_log_handling, ONLY: cp_to_string
      27              :    USE cp_subsys_types, ONLY: cp_subsys_get, &
      28              :                               cp_subsys_set, &
      29              :                               cp_subsys_type, &
      30              :                               pack_subsys_particles
      31              :    USE cp_units, ONLY: cp_unit_from_cp2k
      32              :    USE dimer_types, ONLY: dimer_env_type
      33              :    USE dimer_utils, ONLY: update_dimer_vec
      34              :    USE distribution_1d_types, ONLY: distribution_1d_type
      35              :    USE force_env_types, ONLY: force_env_get, &
      36              :                               force_env_get_natom, &
      37              :                               force_env_get_nparticle, &
      38              :                               force_env_type, &
      39              :                               use_qmmm, &
      40              :                               use_qmmmx
      41              :    USE gopt_f_types, ONLY: gopt_f_type
      42              :    USE gopt_param_types, ONLY: gopt_param_type
      43              :    USE input_constants, ONLY: default_cell_method_id, &
      44              :                               default_minimization_method_id, &
      45              :                               default_shellcore_method_id, &
      46              :                               default_ts_method_id, &
      47              :                               fix_none, &
      48              :                               fix_x, &
      49              :                               fix_xy, &
      50              :                               fix_xz, &
      51              :                               fix_y, &
      52              :                               fix_yz, &
      53              :                               fix_z
      54              :    USE input_cp2k_restarts, ONLY: write_restart
      55              :    USE input_section_types, ONLY: section_vals_type, &
      56              :                                   section_vals_val_get
      57              :    USE kinds, ONLY: default_string_length, &
      58              :                     dp, &
      59              :                     int_8
      60              :    USE machine, ONLY: m_flush
      61              :    USE md_energies, ONLY: sample_memory
      62              :    USE message_passing, ONLY: mp_para_env_type
      63              :    USE motion_utils, ONLY: write_simulation_cell, &
      64              :                            write_stress_tensor_to_file, &
      65              :                            write_trajectory
      66              :    USE particle_list_types, ONLY: particle_list_type
      67              :    USE particle_methods, ONLY: write_final_structure, &
      68              :                                write_structure_data
      69              :    USE particle_types, ONLY: particle_type
      70              :    USE qmmm_util, ONLY: apply_qmmm_translate
      71              :    USE qmmmx_util, ONLY: apply_qmmmx_translate
      72              :    USE virial_methods, ONLY: virial_evaluate
      73              :    USE virial_types, ONLY: virial_type
      74              : #include "../base/base_uses.f90"
      75              : 
      76              :    IMPLICIT NONE
      77              :    PRIVATE
      78              : 
      79              :    #:include "gopt_f77_methods.fypp"
      80              : 
      81              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      82              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = "gopt_f_methods"
      83              : 
      84              :    PUBLIC :: gopt_f_create_x0, &
      85              :              print_geo_opt_header, print_geo_opt_nc, &
      86              :              gopt_f_io_init, gopt_f_io, gopt_f_io_finalize, gopt_f_ii, &
      87              :              apply_cell_change
      88              : 
      89              : CONTAINS
      90              : 
      91              : ! **************************************************************************************************
      92              : !> \brief returns the value of the parameters for the actual configuration
      93              : !> \param gopt_env the geometry optimization environment you want the info about
      94              : !>      x0: the parameter vector (is allocated by this routine)
      95              : !> \param x0 ...
      96              : !> \par History
      97              : !>      - Cell optimization revised (06.11.2012,MK)
      98              : ! **************************************************************************************************
      99         1071 :    SUBROUTINE gopt_f_create_x0(gopt_env, x0)
     100              : 
     101              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     102              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x0
     103              : 
     104              :       INTEGER                                            :: i, idg, j, nparticle
     105              :       TYPE(cell_type), POINTER                           :: cell
     106              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     107              : 
     108         1071 :       NULLIFY (cell)
     109         1071 :       NULLIFY (subsys)
     110              : 
     111         1940 :       SELECT CASE (gopt_env%type_id)
     112              :       CASE (default_minimization_method_id, default_ts_method_id)
     113          869 :          CALL force_env_get(gopt_env%force_env, subsys=subsys)
     114              :          ! before starting we handle the case of translating coordinates (QM/MM)
     115          869 :          IF (gopt_env%force_env%in_use == use_qmmm) &
     116           36 :             CALL apply_qmmm_translate(gopt_env%force_env%qmmm_env)
     117          869 :          IF (gopt_env%force_env%in_use == use_qmmmx) &
     118            0 :             CALL apply_qmmmx_translate(gopt_env%force_env%qmmmx_env)
     119          869 :          nparticle = force_env_get_nparticle(gopt_env%force_env)
     120         2607 :          ALLOCATE (x0(3*nparticle))
     121          869 :          CALL pack_subsys_particles(subsys=subsys, r=x0)
     122              :       CASE (default_cell_method_id)
     123          202 :          CALL force_env_get(gopt_env%force_env, subsys=subsys, cell=cell)
     124              :          ! Store reference cell
     125         5252 :          gopt_env%h_ref = cell%hmat
     126              :          ! before starting we handle the case of translating coordinates (QM/MM)
     127          202 :          IF (gopt_env%force_env%in_use == use_qmmm) &
     128            0 :             CALL apply_qmmm_translate(gopt_env%force_env%qmmm_env)
     129          202 :          IF (gopt_env%force_env%in_use == use_qmmmx) &
     130            0 :             CALL apply_qmmmx_translate(gopt_env%force_env%qmmmx_env)
     131          202 :          nparticle = force_env_get_nparticle(gopt_env%force_env)
     132          606 :          ALLOCATE (x0(3*nparticle + 6))
     133          202 :          CALL pack_subsys_particles(subsys=subsys, r=x0)
     134          202 :          idg = 3*nparticle
     135          808 :          DO i = 1, 3
     136         2020 :             DO j = 1, i
     137         1212 :                idg = idg + 1
     138         1818 :                x0(idg) = cell%hmat(j, i)
     139              :             END DO
     140              :          END DO
     141              :       CASE DEFAULT
     142         1071 :          CPABORT("Invalid or not yet implemented type of optimization")
     143              :       END SELECT
     144              : 
     145         1071 :    END SUBROUTINE gopt_f_create_x0
     146              : 
     147              : ! **************************************************************************************************
     148              : !> \brief Prints iteration step of the optimization procedure on screen
     149              : !> \param its ...
     150              : !> \param output_unit ...
     151              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     152              : ! **************************************************************************************************
     153         8952 :    SUBROUTINE gopt_f_ii(its, output_unit)
     154              : 
     155              :       INTEGER, INTENT(IN)                                :: its, output_unit
     156              : 
     157         8952 :       IF (output_unit > 0) THEN
     158         4514 :          WRITE (UNIT=output_unit, FMT="(/,T2,26('-'))")
     159         4514 :          WRITE (UNIT=output_unit, FMT="(T2,A,I6)") "OPTIMIZATION STEP: ", its
     160         4514 :          WRITE (UNIT=output_unit, FMT="(T2,26('-'))")
     161         4514 :          CALL m_flush(output_unit)
     162              :       END IF
     163              : 
     164         8952 :    END SUBROUTINE gopt_f_ii
     165              : 
     166              : ! **************************************************************************************************
     167              : !> \brief Handles the Output during an optimization run
     168              : !> \param gopt_env ...
     169              : !> \param output_unit ...
     170              : !> \param opt_energy ...
     171              : !> \param wildcard ...
     172              : !> \param its ...
     173              : !> \param used_time ...
     174              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     175              : ! **************************************************************************************************
     176         1133 :    SUBROUTINE gopt_f_io_init(gopt_env, output_unit, opt_energy, wildcard, its, used_time)
     177              : 
     178              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     179              :       INTEGER, INTENT(IN)                                :: output_unit
     180              :       REAL(KIND=dp)                                      :: opt_energy
     181              :       CHARACTER(LEN=5)                                   :: wildcard
     182              :       INTEGER, INTENT(IN)                                :: its
     183              :       REAL(KIND=dp)                                      :: used_time
     184              : 
     185              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     186              :       CHARACTER(LEN=default_string_length)               :: energy_unit, stress_unit
     187              :       REAL(KIND=dp)                                      :: pres_int
     188              :       INTEGER(KIND=int_8)                                :: max_memory
     189              :       LOGICAL                                            :: print_memory
     190              : 
     191         1133 :       NULLIFY (para_env)
     192         1133 :       CALL section_vals_val_get(gopt_env%motion_section, "PRINT%MEMORY_INFO", l_val=print_memory)
     193         1133 :       max_memory = 0
     194         1133 :       IF (print_memory) THEN
     195         1133 :          CALL force_env_get(gopt_env%force_env, para_env=para_env)
     196         1133 :          max_memory = sample_memory(para_env)
     197              :       END IF
     198              : 
     199              :       CALL section_vals_val_get(gopt_env%force_env%force_env_section, &
     200              :                                 "PRINT%PROGRAM_RUN_INFO%ENERGY_UNIT", &
     201         1133 :                                 c_val=energy_unit)
     202              :       CALL section_vals_val_get(gopt_env%force_env%force_env_section, &
     203              :                                 "PRINT%STRESS_TENSOR%STRESS_UNIT", &
     204         1133 :                                 c_val=stress_unit)
     205              : 
     206         2088 :       SELECT CASE (gopt_env%type_id)
     207              :       CASE (default_ts_method_id, default_minimization_method_id)
     208              :          ! Geometry Optimization (Minimization and Transition State Search)
     209          955 :          IF (.NOT. gopt_env%dimer_rotation) THEN
     210              :             CALL write_cycle_infos(output_unit, &
     211              :                                    it=its, &
     212              :                                    etot=opt_energy, &
     213              :                                    wildcard=wildcard, &
     214              :                                    used_time=used_time, &
     215              :                                    max_memory=max_memory, &
     216              :                                    energy_unit=energy_unit, &
     217          823 :                                    stress_unit=stress_unit)
     218              :          ELSE
     219              :             CALL write_rot_cycle_infos(output_unit, &
     220              :                                        it=its, &
     221              :                                        etot=opt_energy, &
     222              :                                        dimer_env=gopt_env%dimer_env, &
     223              :                                        wildcard=wildcard, &
     224              :                                        used_time=used_time, &
     225          132 :                                        max_memory=max_memory)
     226              :          END IF
     227              :       CASE (default_cell_method_id)
     228              :          ! Cell Optimization
     229          158 :          pres_int = gopt_env%cell_env%pres_int
     230              :          CALL write_cycle_infos(output_unit, &
     231              :                                 it=its, &
     232              :                                 etot=opt_energy, &
     233              :                                 pres_int=pres_int, &
     234              :                                 wildcard=wildcard, &
     235              :                                 used_time=used_time, &
     236              :                                 max_memory=max_memory, &
     237              :                                 energy_unit=energy_unit, &
     238          158 :                                 stress_unit=stress_unit)
     239              :       CASE (default_shellcore_method_id)
     240              :          CALL write_cycle_infos(output_unit, &
     241              :                                 it=its, &
     242              :                                 etot=opt_energy, &
     243              :                                 wildcard=wildcard, &
     244              :                                 used_time=used_time, &
     245              :                                 max_memory=max_memory, &
     246              :                                 energy_unit=energy_unit, &
     247         1133 :                                 stress_unit=stress_unit)
     248              :       END SELECT
     249              : 
     250         1133 :    END SUBROUTINE gopt_f_io_init
     251              : 
     252              : ! **************************************************************************************************
     253              : !> \brief Handles the Output during an optimization run
     254              : !> \param gopt_env ...
     255              : !> \param force_env ...
     256              : !> \param root_section ...
     257              : !> \param its ...
     258              : !> \param opt_energy ...
     259              : !> \param output_unit ...
     260              : !> \param eold ...
     261              : !> \param emin ...
     262              : !> \param wildcard ...
     263              : !> \param gopt_param ...
     264              : !> \param ndf ...
     265              : !> \param dx ...
     266              : !> \param xi ...
     267              : !> \param conv ...
     268              : !> \param pred ...
     269              : !> \param rat ...
     270              : !> \param step ...
     271              : !> \param rad ...
     272              : !> \param used_time ...
     273              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     274              : ! **************************************************************************************************
     275        17900 :    SUBROUTINE gopt_f_io(gopt_env, force_env, root_section, its, opt_energy, &
     276         8950 :                         output_unit, eold, emin, wildcard, gopt_param, ndf, dx, xi, conv, pred, rat, &
     277              :                         step, rad, used_time)
     278              : 
     279              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     280              :       TYPE(force_env_type), POINTER                      :: force_env
     281              :       TYPE(section_vals_type), POINTER                   :: root_section
     282              :       INTEGER, INTENT(IN)                                :: its
     283              :       REAL(KIND=dp), INTENT(IN)                          :: opt_energy
     284              :       INTEGER, INTENT(IN)                                :: output_unit
     285              :       REAL(KIND=dp)                                      :: eold, emin
     286              :       CHARACTER(LEN=5)                                   :: wildcard
     287              :       TYPE(gopt_param_type), POINTER                     :: gopt_param
     288              :       INTEGER, INTENT(IN), OPTIONAL                      :: ndf
     289              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: dx
     290              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: xi
     291              :       LOGICAL, OPTIONAL                                  :: conv
     292              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: pred, rat, step, rad
     293              :       REAL(KIND=dp)                                      :: used_time
     294              : 
     295              :       CHARACTER(LEN=default_string_length)               :: energy_unit, stress_unit
     296              :       INTEGER(KIND=int_8)                                :: max_memory
     297              :       LOGICAL                                            :: print_memory
     298              :       REAL(KIND=dp)                                      :: pres_diff, pres_diff_constr, pres_int, &
     299              :                                                             pres_tol
     300              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     301              : 
     302         8950 :       NULLIFY (para_env)
     303         8950 :       CALL section_vals_val_get(gopt_env%motion_section, "PRINT%MEMORY_INFO", l_val=print_memory)
     304         8950 :       max_memory = 0
     305         8950 :       IF (print_memory) THEN
     306         8950 :          CALL force_env_get(force_env, para_env=para_env)
     307         8950 :          max_memory = sample_memory(para_env)
     308              :       END IF
     309              : 
     310              :       CALL section_vals_val_get(gopt_env%force_env%force_env_section, &
     311              :                                 "PRINT%PROGRAM_RUN_INFO%ENERGY_UNIT", &
     312         8950 :                                 c_val=energy_unit)
     313              :       CALL section_vals_val_get(gopt_env%force_env%force_env_section, &
     314              :                                 "PRINT%STRESS_TENSOR%STRESS_UNIT", &
     315         8950 :                                 c_val=stress_unit)
     316              : 
     317        13872 :       SELECT CASE (gopt_env%type_id)
     318              :       CASE (default_ts_method_id, default_minimization_method_id)
     319              :          ! Geometry Optimization (Minimization and Transition State Search)
     320         4922 :          IF (.NOT. gopt_env%dimer_rotation) THEN
     321              :             CALL geo_opt_io(force_env=force_env, root_section=root_section, &
     322         4196 :                             motion_section=gopt_env%motion_section, its=its, opt_energy=opt_energy)
     323              :             CALL write_cycle_infos(output_unit, &
     324              :                                    it=its, &
     325              :                                    etot=opt_energy, &
     326              :                                    ediff=(opt_energy - eold), &
     327              :                                    pred=pred, &
     328              :                                    rat=rat, &
     329              :                                    step=step, &
     330              :                                    rad=rad, &
     331              :                                    emin=emin, &
     332              :                                    wildcard=wildcard, &
     333              :                                    used_time=used_time, &
     334              :                                    max_memory=max_memory, &
     335              :                                    energy_unit=energy_unit, &
     336         4196 :                                    stress_unit=stress_unit)
     337              :             ! Possibly check convergence
     338         4196 :             IF (PRESENT(conv)) THEN
     339         4196 :                CPASSERT(PRESENT(ndf))
     340         4196 :                CPASSERT(PRESENT(dx))
     341         4196 :                CPASSERT(PRESENT(xi))
     342         4196 :                CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit)
     343              :             END IF
     344              :          ELSE
     345          726 :             CALL update_dimer_vec(gopt_env%dimer_env, gopt_env%motion_section)
     346          726 :             CALL write_restart(force_env=force_env, root_section=root_section)
     347              :             CALL write_rot_cycle_infos(output_unit, its, opt_energy, opt_energy - eold, emin, gopt_env%dimer_env, &
     348          726 :                                        wildcard=wildcard, used_time=used_time, max_memory=max_memory)
     349              :             ! Possibly check convergence
     350          726 :             IF (PRESENT(conv)) THEN
     351          726 :                CPASSERT(ASSOCIATED(gopt_env%dimer_env))
     352          726 :                CALL check_rot_conv(gopt_env%dimer_env, output_unit, conv)
     353              :             END IF
     354              :          END IF
     355              :       CASE (default_cell_method_id)
     356              :          ! Cell Optimization
     357         3858 :          pres_diff = gopt_env%cell_env%pres_int - gopt_env%cell_env%pres_ext
     358         3858 :          pres_int = gopt_env%cell_env%pres_int
     359         3858 :          pres_tol = gopt_env%cell_env%pres_tol
     360              :          CALL geo_opt_io(force_env=force_env, root_section=root_section, &
     361         3858 :                          motion_section=gopt_env%motion_section, its=its, opt_energy=opt_energy)
     362              :          CALL write_cycle_infos(output_unit, &
     363              :                                 it=its, &
     364              :                                 etot=opt_energy, &
     365              :                                 ediff=(opt_energy - eold), &
     366              :                                 pred=pred, &
     367              :                                 rat=rat, &
     368              :                                 step=step, &
     369              :                                 rad=rad, &
     370              :                                 emin=emin, &
     371              :                                 pres_int=pres_int, &
     372              :                                 wildcard=wildcard, &
     373              :                                 used_time=used_time, &
     374              :                                 max_memory=max_memory, &
     375              :                                 energy_unit=energy_unit, &
     376         3858 :                                 stress_unit=stress_unit)
     377              :          ! Possibly check convergence
     378         3858 :          IF (PRESENT(conv)) THEN
     379         3858 :             CPASSERT(PRESENT(ndf))
     380         3858 :             CPASSERT(PRESENT(dx))
     381         3858 :             CPASSERT(PRESENT(xi))
     382         3858 :             IF (gopt_env%cell_env%constraint_id == fix_none) THEN
     383              :                CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit, &
     384         3840 :                                   pres_diff, pres_tol)
     385              :             ELSE
     386           18 :                pres_diff_constr = gopt_env%cell_env%pres_constr - gopt_env%cell_env%pres_ext
     387              :                CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit, &
     388           18 :                                   pres_diff, pres_tol, pres_diff_constr)
     389              :             END IF
     390              :          END IF
     391              :       CASE (default_shellcore_method_id)
     392              :          CALL write_cycle_infos(output_unit, &
     393              :                                 it=its, &
     394              :                                 etot=opt_energy, &
     395              :                                 ediff=(opt_energy - eold), &
     396              :                                 pred=pred, &
     397              :                                 rat=rat, &
     398              :                                 step=step, &
     399              :                                 rad=rad, &
     400              :                                 emin=emin, &
     401              :                                 wildcard=wildcard, &
     402              :                                 used_time=used_time, &
     403              :                                 max_memory=max_memory, &
     404              :                                 energy_unit=energy_unit, &
     405          170 :                                 stress_unit=stress_unit)
     406              :          ! Possibly check convergence
     407         9120 :          IF (PRESENT(conv)) THEN
     408          170 :             CPASSERT(PRESENT(ndf))
     409          170 :             CPASSERT(PRESENT(dx))
     410          170 :             CPASSERT(PRESENT(xi))
     411          170 :             CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit)
     412              :          END IF
     413              :       END SELECT
     414              : 
     415         8950 :    END SUBROUTINE gopt_f_io
     416              : 
     417              : ! **************************************************************************************************
     418              : !> \brief Handles the Output at the end of an optimization run
     419              : !> \param gopt_env ...
     420              : !> \param force_env ...
     421              : !> \param x0 ...
     422              : !> \param conv ...
     423              : !> \param its ...
     424              : !> \param root_section ...
     425              : !> \param para_env ...
     426              : !> \param master ...
     427              : !> \param output_unit ...
     428              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     429              : ! **************************************************************************************************
     430         1223 :    RECURSIVE SUBROUTINE gopt_f_io_finalize(gopt_env, force_env, x0, conv, its, root_section, &
     431              :                                            para_env, master, output_unit)
     432              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     433              :       TYPE(force_env_type), POINTER                      :: force_env
     434              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x0
     435              :       LOGICAL                                            :: conv
     436              :       INTEGER                                            :: its
     437              :       TYPE(section_vals_type), POINTER                   :: root_section
     438              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     439              :       INTEGER, INTENT(IN)                                :: master, output_unit
     440              : 
     441         1223 :       IF (gopt_env%eval_opt_geo) THEN
     442         1203 :          IF (.NOT. gopt_env%dimer_rotation) THEN
     443              :             CALL write_final_info(output_unit, conv, its, gopt_env, x0, master, &
     444         1071 :                                   para_env, force_env, gopt_env%motion_section, root_section)
     445              :          ELSE
     446          132 :             CALL update_dimer_vec(gopt_env%dimer_env, gopt_env%motion_section)
     447          132 :             CALL write_restart(force_env=force_env, root_section=root_section)
     448              :          END IF
     449              :       END IF
     450              : 
     451         1223 :    END SUBROUTINE gopt_f_io_finalize
     452              : 
     453              : ! **************************************************************************************************
     454              : !> \brief ...
     455              : !> \param output_unit ...
     456              : !> \param it ...
     457              : !> \param etot ...
     458              : !> \param ediff ...
     459              : !> \param pred ...
     460              : !> \param rat ...
     461              : !> \param step ...
     462              : !> \param rad ...
     463              : !> \param emin ...
     464              : !> \param pres_int ...
     465              : !> \param wildcard ...
     466              : !> \param used_time ...
     467              : ! **************************************************************************************************
     468         9225 :    SUBROUTINE write_cycle_infos(output_unit, it, etot, ediff, pred, rat, step, rad, emin, &
     469              :                                 pres_int, wildcard, used_time, max_memory, energy_unit, stress_unit)
     470              : 
     471              :       INTEGER, INTENT(IN)                                :: output_unit, it
     472              :       REAL(KIND=dp), INTENT(IN)                          :: etot
     473              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: ediff, pred, rat, step, rad, emin, &
     474              :                                                             pres_int
     475              :       CHARACTER(LEN=5), INTENT(IN)                       :: wildcard
     476              :       REAL(KIND=dp), INTENT(IN)                          :: used_time
     477              :       INTEGER(KIND=int_8), INTENT(IN)                    :: max_memory
     478              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: energy_unit, stress_unit
     479              : 
     480              :       CHARACTER(LEN=5)                                   :: tag
     481              : 
     482         9225 :       IF (output_unit > 0) THEN
     483         4668 :          tag = "OPT| "
     484         4668 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") tag//REPEAT("*", 74)
     485              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,I25)") &
     486         4668 :             tag//"Step number", it
     487              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,A25)") &
     488         4668 :             tag//"Optimization method", wildcard
     489              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     490         4668 :             tag//"Total energy ["//TRIM(ADJUSTL(energy_unit))//"]", &
     491         9336 :             cp_unit_from_cp2k(etot, TRIM(energy_unit))
     492         4668 :          IF (PRESENT(pres_int)) THEN
     493              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     494         2008 :                tag//"Internal pressure ["//TRIM(ADJUSTL(stress_unit))//"]", &
     495         4016 :                cp_unit_from_cp2k(pres_int, TRIM(stress_unit))
     496              :          END IF
     497         4668 :          IF (PRESENT(ediff)) THEN
     498              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     499         4150 :                tag//"Effective energy change ["//TRIM(ADJUSTL(energy_unit))//"]", &
     500         8300 :                cp_unit_from_cp2k(ediff, TRIM(energy_unit))
     501              :          END IF
     502         4668 :          IF (PRESENT(pred)) THEN
     503              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     504         2081 :                tag//"Predicted energy change ["//TRIM(ADJUSTL(energy_unit))//"]", &
     505         4162 :                cp_unit_from_cp2k(pred, TRIM(energy_unit))
     506              :          END IF
     507         4668 :          IF (PRESENT(rat)) THEN
     508              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     509         2081 :                tag//"Scaling factor", rat
     510              :          END IF
     511         4668 :          IF (PRESENT(step)) THEN
     512              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     513         2081 :                tag//"Step size", step
     514              :          END IF
     515         4668 :          IF (PRESENT(rad)) THEN
     516              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     517         2081 :                tag//"Trust radius", rad
     518              :          END IF
     519         4668 :          IF (PRESENT(emin)) THEN
     520         4150 :             IF (etot < emin) THEN
     521              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     522         3779 :                   tag//"Decrease in energy", " YES"
     523              :             ELSE
     524              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     525          371 :                   tag//"Decrease in energy", "  NO"
     526              :             END IF
     527              :          END IF
     528              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.3)") &
     529         4668 :             tag//"Used time [s]", used_time
     530         4668 :          IF (it == 0) THEN
     531          512 :             WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     532          512 :             IF (max_memory /= 0) THEN
     533              :                WRITE (UNIT=output_unit, FMT="(T2,A,T60,1X,I20)") &
     534          512 :                   tag//"Estimated peak process memory [MiB]", &
     535         1024 :                   (max_memory + (1024*1024) - 1)/(1024*1024)
     536              :             END IF
     537              :          END IF
     538              :       END IF
     539              : 
     540         9225 :    END SUBROUTINE write_cycle_infos
     541              : 
     542              : ! **************************************************************************************************
     543              : !> \brief ...
     544              : !> \param output_unit ...
     545              : !> \param it ...
     546              : !> \param etot ...
     547              : !> \param ediff ...
     548              : !> \param emin ...
     549              : !> \param dimer_env ...
     550              : !> \param used_time ...
     551              : !> \param wildcard ...
     552              : !> \date  01.2008
     553              : !> \author Luca Bellucci and Teodoro Laino - created [tlaino]
     554              : ! **************************************************************************************************
     555          858 :    SUBROUTINE write_rot_cycle_infos(output_unit, it, etot, ediff, emin, dimer_env, used_time, &
     556              :                                     wildcard, max_memory)
     557              : 
     558              :       INTEGER, INTENT(IN)                                :: output_unit, it
     559              :       REAL(KIND=dp), INTENT(IN)                          :: etot
     560              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: ediff, emin
     561              :       TYPE(dimer_env_type), POINTER                      :: dimer_env
     562              :       REAL(KIND=dp), INTENT(IN)                          :: used_time
     563              :       CHARACTER(LEN=5), INTENT(IN)                       :: wildcard
     564              :       INTEGER(KIND=int_8), INTENT(IN)                    :: max_memory
     565              : 
     566              :       CHARACTER(LEN=5)                                   :: tag
     567              : 
     568          858 :       IF (output_unit > 0) THEN
     569          429 :          tag = "OPT| "
     570          429 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") tag//REPEAT("*", 74)
     571              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,I25)") &
     572          429 :             tag//"Rotational step number", it
     573              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,A25)") &
     574          429 :             tag//"Optimization method", wildcard
     575              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     576          429 :             tag//"Local curvature", dimer_env%rot%curvature, &
     577          858 :             tag//"Total rotational force", etot
     578          429 :          IF (PRESENT(ediff)) THEN
     579              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     580          363 :                tag//"Rotational force change", ediff
     581              :          END IF
     582          429 :          IF (PRESENT(emin)) THEN
     583          363 :             IF (etot < emin) THEN
     584              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     585          157 :                   tag//"Decrease in rotational force", " YES"
     586              :             ELSE
     587              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     588          206 :                   tag//"Decrease in rotational force", "  NO"
     589              :             END IF
     590              :          END IF
     591              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.3)") &
     592          429 :             tag//"Used time [s]", used_time
     593          429 :          IF (it == 0) THEN
     594           66 :             WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     595           66 :             IF (max_memory /= 0) THEN
     596              :                WRITE (UNIT=output_unit, FMT="(T2,A,T60,1X,I20)") &
     597           66 :                   tag//"Estimated peak process memory [MiB]", &
     598          132 :                   (max_memory + (1024*1024) - 1)/(1024*1024)
     599              :             END IF
     600              :          END IF
     601              :       END IF
     602              : 
     603          858 :    END SUBROUTINE write_rot_cycle_infos
     604              : 
     605              : ! **************************************************************************************************
     606              : !> \brief ...
     607              : !> \param ndf ...
     608              : !> \param dr ...
     609              : !> \param g ...
     610              : !> \param output_unit ...
     611              : !> \param conv ...
     612              : !> \param gopt_param ...
     613              : !> \param max_memory ...
     614              : !> \param pres_diff ...
     615              : !> \param pres_tol ...
     616              : !> \param pres_diff_constr ...
     617              : ! **************************************************************************************************
     618         8224 :    SUBROUTINE check_converg(ndf, dr, g, output_unit, conv, gopt_param, max_memory, stress_unit, &
     619              :                             pres_diff, pres_tol, pres_diff_constr)
     620              : 
     621              :       INTEGER, INTENT(IN)                                :: ndf
     622              :       REAL(KIND=dp), INTENT(IN)                          :: dr(ndf), g(ndf)
     623              :       INTEGER, INTENT(IN)                                :: output_unit
     624              :       LOGICAL, INTENT(OUT)                               :: conv
     625              :       TYPE(gopt_param_type), POINTER                     :: gopt_param
     626              :       INTEGER(KIND=int_8), INTENT(IN)                    :: max_memory
     627              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: stress_unit
     628              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: pres_diff, pres_tol, pres_diff_constr
     629              : 
     630              :       CHARACTER(LEN=5)                                   :: tag
     631              :       INTEGER                                            :: indf
     632              :       LOGICAL                                            :: conv_dx, conv_g, conv_p, conv_rdx, &
     633              :                                                             conv_rg
     634              :       REAL(KIND=dp)                                      :: dumm, dxcon, gcon, maxdum(4), rmsgcon, &
     635              :                                                             rmsxcon
     636              : 
     637         8224 :       dxcon = gopt_param%max_dr
     638         8224 :       gcon = gopt_param%max_force
     639         8224 :       rmsgcon = gopt_param%rms_force
     640         8224 :       rmsxcon = gopt_param%rms_dr
     641              : 
     642         8224 :       conv = .FALSE.
     643         8224 :       conv_dx = .TRUE.
     644         8224 :       conv_rdx = .TRUE.
     645         8224 :       conv_g = .TRUE.
     646         8224 :       conv_rg = .TRUE.
     647         8224 :       conv_p = .TRUE.
     648              : 
     649         8224 :       dumm = 0.0_dp
     650      2381425 :       DO indf = 1, ndf
     651      2373201 :          IF (indf == 1) maxdum(1) = ABS(dr(indf))
     652      2373201 :          dumm = dumm + dr(indf)**2
     653      2373201 :          IF (ABS(dr(indf)) > dxcon) conv_dx = .FALSE.
     654      2381425 :          IF (ABS(dr(indf)) > maxdum(1)) maxdum(1) = ABS(dr(indf))
     655              :       END DO
     656              :       ! SQRT(dumm/ndf) > rmsxcon
     657         8224 :       IF (dumm > (rmsxcon*rmsxcon*ndf)) conv_rdx = .FALSE.
     658         8224 :       maxdum(2) = SQRT(dumm/ndf)
     659              : 
     660         8224 :       dumm = 0.0_dp
     661      2381425 :       DO indf = 1, ndf
     662      2373201 :          IF (indf == 1) maxdum(3) = ABS(g(indf))
     663      2373201 :          dumm = dumm + g(indf)**2
     664      2373201 :          IF (ABS(g(indf)) > gcon) conv_g = .FALSE.
     665      2381425 :          IF (ABS(g(indf)) > maxdum(3)) maxdum(3) = ABS(g(indf))
     666              :       END DO
     667              :       ! SQRT(dumm/ndf) > rmsgcon
     668         8224 :       IF (dumm > (rmsgcon*rmsgcon*ndf)) conv_rg = .FALSE.
     669         8224 :       maxdum(4) = SQRT(dumm/ndf)
     670              : 
     671         8224 :       IF (PRESENT(pres_diff_constr) .AND. PRESENT(pres_tol)) THEN
     672           18 :          conv_p = ABS(pres_diff_constr) < ABS(pres_tol)
     673         8206 :       ELSEIF (PRESENT(pres_diff) .AND. PRESENT(pres_tol)) THEN
     674         3840 :          conv_p = ABS(pres_diff) < ABS(pres_tol)
     675              :       END IF
     676              : 
     677         8224 :       IF (output_unit > 0) THEN
     678              : 
     679         4150 :          tag = "OPT| "
     680              : 
     681         4150 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     682              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     683         4150 :             tag//"Maximum step size", maxdum(1), &
     684         8300 :             tag//"Convergence limit for maximum step size", dxcon
     685         4150 :          IF (conv_dx) THEN
     686              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     687          582 :                tag//"Maximum step size is converged", " YES"
     688              :          ELSE
     689              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     690         3568 :                tag//"Maximum step size is converged", "  NO"
     691              :          END IF
     692              : 
     693         4150 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     694              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     695         4150 :             tag//"RMS step size", maxdum(2), &
     696         8300 :             tag//"Convergence limit for RMS step size", rmsxcon
     697         4150 :          IF (conv_rdx) THEN
     698              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     699          784 :                tag//"RMS step size is converged", " YES"
     700              :          ELSE
     701              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     702         3366 :                tag//"RMS step size is converged", "  NO"
     703              :          END IF
     704              : 
     705         4150 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     706              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     707         4150 :             tag//"Maximum gradient", maxdum(3), &
     708         8300 :             tag//"Convergence limit for maximum gradient", gcon
     709         4150 :          IF (conv_g) THEN
     710              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     711          556 :                tag//"Maximum gradient is converged", " YES"
     712              :          ELSE
     713              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     714         3594 :                tag//"Maximum gradient is converged", "  NO"
     715              :          END IF
     716              : 
     717         4150 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     718              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     719         4150 :             tag//"RMS gradient", maxdum(4), &
     720         8300 :             tag//"Convergence limit for RMS gradient", rmsgcon
     721         4150 :          IF (conv_rg) THEN
     722              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     723          757 :                tag//"RMS gradient is converged", " YES"
     724              :          ELSE
     725              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     726         3393 :                tag//"RMS gradient is converged", "  NO"
     727              :          END IF
     728              : 
     729         4150 :          IF (PRESENT(pres_diff) .AND. PRESENT(pres_tol)) THEN
     730         1929 :             WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     731         1929 :             IF (PRESENT(pres_diff_constr)) THEN
     732              :                WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     733              :                   tag//"Pressure deviation without constraint ["// &
     734            9 :                   TRIM(ADJUSTL(stress_unit))//"]", &
     735           18 :                   cp_unit_from_cp2k(pres_diff, TRIM(stress_unit))
     736              :                WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     737              :                   tag//"Pressure deviation with constraint ["// &
     738            9 :                   TRIM(ADJUSTL(stress_unit))//"]", &
     739           18 :                   cp_unit_from_cp2k(pres_diff_constr, TRIM(stress_unit))
     740              :             ELSE
     741              :                WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     742         1920 :                   tag//"Pressure deviation ["//TRIM(ADJUSTL(stress_unit))//"]", &
     743         3840 :                   cp_unit_from_cp2k(pres_diff, TRIM(stress_unit))
     744              :             END IF
     745              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     746         1929 :                tag//"Pressure tolerance ["//TRIM(ADJUSTL(stress_unit))//"]", &
     747         3858 :                cp_unit_from_cp2k(pres_tol, TRIM(stress_unit))
     748         1929 :             IF (conv_p) THEN
     749              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     750          290 :                   tag//"Pressure is converged", " YES"
     751              :             ELSE
     752              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     753         1639 :                   tag//"Pressure is converged", "  NO"
     754              :             END IF
     755              :          END IF
     756              : 
     757         4150 :          WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     758              : 
     759         4150 :          IF (max_memory /= 0) THEN
     760              :             WRITE (UNIT=output_unit, FMT="(T2,A,T60,1X,I20)") &
     761         4150 :                tag//"Estimated peak process memory after this step [MiB]", &
     762         8300 :                (max_memory + (1024*1024) - 1)/(1024*1024)
     763              :          END IF
     764              : 
     765              :       END IF
     766              : 
     767         8224 :       IF (conv_dx .AND. conv_rdx .AND. conv_g .AND. conv_rg .AND. conv_p) conv = .TRUE.
     768              : 
     769         8224 :       IF ((conv) .AND. (output_unit > 0)) THEN
     770          204 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
     771              :          WRITE (UNIT=output_unit, FMT="(T2,A,T25,A,T78,A)") &
     772          204 :             "***", "GEOMETRY OPTIMIZATION COMPLETED", "***"
     773          204 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
     774              :       END IF
     775              : 
     776         8224 :    END SUBROUTINE check_converg
     777              : 
     778              : ! **************************************************************************************************
     779              : !> \brief ...
     780              : !> \param dimer_env ...
     781              : !> \param output_unit ...
     782              : !> \param conv ...
     783              : !> \date  01.2008
     784              : !> \author Luca Bellucci and Teodoro Laino - created [tlaino]
     785              : ! **************************************************************************************************
     786          726 :    SUBROUTINE check_rot_conv(dimer_env, output_unit, conv)
     787              : 
     788              :       TYPE(dimer_env_type), POINTER                      :: dimer_env
     789              :       INTEGER, INTENT(IN)                                :: output_unit
     790              :       LOGICAL, INTENT(OUT)                               :: conv
     791              : 
     792              :       CHARACTER(LEN=5)                                   :: tag
     793              : 
     794          726 :       conv = (ABS(dimer_env%rot%angle2) < dimer_env%rot%angle_tol)
     795              : 
     796          726 :       IF (output_unit > 0) THEN
     797          363 :          tag = "OPT| "
     798          363 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     799              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     800          363 :             tag//"Predicted angle step size", dimer_env%rot%angle1, &
     801          363 :             tag//"Effective angle step size", dimer_env%rot%angle2, &
     802          726 :             tag//"Convergence limit for angle step size", dimer_env%rot%angle_tol
     803          363 :          IF (conv) THEN
     804              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     805           55 :                tag//"Angle step size is converged", " YES"
     806              :          ELSE
     807              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     808          308 :                tag//"Angle step size is converged", "  NO"
     809              :          END IF
     810          363 :          WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     811              :       END IF
     812              : 
     813          726 :       IF ((conv) .AND. (output_unit > 0)) THEN
     814           55 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
     815              :          WRITE (UNIT=output_unit, FMT="(T2,A,T25,A,T78,A)") &
     816           55 :             "***", "ROTATION OPTIMIZATION COMPLETED", "***"
     817           55 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
     818              :       END IF
     819              : 
     820          726 :    END SUBROUTINE check_rot_conv
     821              : 
     822              : ! **************************************************************************************************
     823              : !> \brief ...
     824              : !> \param output_unit ...
     825              : !> \param conv ...
     826              : !> \param it ...
     827              : !> \param gopt_env ...
     828              : !> \param x0 ...
     829              : !> \param master ...
     830              : !> \param para_env ...
     831              : !> \param force_env ...
     832              : !> \param motion_section ...
     833              : !> \param root_section ...
     834              : !> \date  11.2007
     835              : !> \author Teodoro Laino [tlaino] - University of Zurich
     836              : ! **************************************************************************************************
     837         1071 :    RECURSIVE SUBROUTINE write_final_info(output_unit, conv, it, gopt_env, x0, master, para_env, force_env, &
     838              :                                          motion_section, root_section)
     839              :       INTEGER, INTENT(IN)                                :: output_unit
     840              :       LOGICAL, INTENT(IN)                                :: conv
     841              :       INTEGER, INTENT(INOUT)                             :: it
     842              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     843              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x0
     844              :       INTEGER, INTENT(IN)                                :: master
     845              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     846              :       TYPE(force_env_type), POINTER                      :: force_env
     847              :       TYPE(section_vals_type), POINTER                   :: motion_section, root_section
     848              : 
     849              :       CHARACTER(LEN=4)                                   :: constraint_label
     850              :       LOGICAL                                            :: keep_angles, keep_symmetry, &
     851              :                                                             keep_volume
     852              :       REAL(KIND=dp)                                      :: etot
     853              :       TYPE(cell_type), POINTER                           :: cell
     854              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     855              :       TYPE(particle_list_type), POINTER                  :: particles
     856         1071 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     857              : 
     858         1071 :       CALL force_env_get(force_env, cell=cell, subsys=subsys)
     859         1071 :       CALL cp_subsys_get(subsys=subsys, particles=particles)
     860         1071 :       particle_set => particles%els
     861              : 
     862              :       ! Passing gopt_f_type pointer gopt_env to particle_methods where
     863              :       ! write_final_structure is defined causes a circular dependency, so it
     864              :       ! is necessary to get some flags by preprocessing...
     865         1071 :       keep_angles = .TRUE.
     866         1071 :       keep_symmetry = .TRUE.
     867         1071 :       keep_volume = .TRUE.
     868         1071 :       constraint_label = "NONE"
     869         1071 :       IF (gopt_env%type_id == default_cell_method_id) THEN
     870          202 :          keep_angles = gopt_env%cell_env%keep_angles
     871          202 :          keep_symmetry = gopt_env%cell_env%keep_symmetry
     872          202 :          keep_volume = gopt_env%cell_env%keep_volume
     873          202 :          SELECT CASE (gopt_env%cell_env%constraint_id)
     874              :          CASE (fix_x)
     875            0 :             constraint_label = "   X"
     876              :          CASE (fix_y)
     877            0 :             constraint_label = "   Y"
     878              :          CASE (fix_z)
     879            2 :             constraint_label = "   Z"
     880              :          CASE (fix_xy)
     881            2 :             constraint_label = "  XY"
     882              :          CASE (fix_xz)
     883            0 :             constraint_label = "  XZ"
     884              :          CASE (fix_yz)
     885            0 :             constraint_label = "  YZ"
     886              :          CASE (fix_none)
     887          202 :             constraint_label = "NONE"
     888              :          END SELECT
     889              :       END IF
     890              :       CALL write_final_structure(particle_set, cell, motion_section, conv, &
     891              :                                  keep_angles, keep_symmetry, keep_volume, &
     892         1071 :                                  gopt_env%label, constraint_label)
     893              : 
     894         1071 :       IF (conv) THEN
     895          356 :          it = it + 1
     896          356 :          CALL write_structure_data(particle_set, cell, motion_section)
     897          356 :          CALL write_restart(force_env=force_env, root_section=root_section)
     898              : 
     899          356 :          IF (output_unit > 0) &
     900          195 :             WRITE (UNIT=output_unit, FMT="(/,T20,' Reevaluating energy at the minimum')")
     901              : 
     902              :          CALL cp_eval_at(gopt_env, x0, f=etot, master=master, final_evaluation=.TRUE., &
     903          356 :                          para_env=para_env)
     904          356 :          CALL write_geo_traj(force_env, root_section, it, etot)
     905              :       END IF
     906              : 
     907         1071 :    END SUBROUTINE write_final_info
     908              : 
     909              : ! **************************************************************************************************
     910              : !> \brief  Specific driver for dumping trajectory during a GEO_OPT
     911              : !> \param force_env ...
     912              : !> \param root_section ...
     913              : !> \param it ...
     914              : !> \param etot ...
     915              : !> \date   11.2007
     916              : !> \par    History
     917              : !>         09.2010: Output of core and shell positions and forces (MK)
     918              : !> \author Teodoro Laino [tlaino] - University of Zurich
     919              : ! **************************************************************************************************
     920        16820 :    SUBROUTINE write_geo_traj(force_env, root_section, it, etot)
     921              : 
     922              :       TYPE(force_env_type), POINTER                      :: force_env
     923              :       TYPE(section_vals_type), POINTER                   :: root_section
     924              :       INTEGER, INTENT(IN)                                :: it
     925              :       REAL(KIND=dp), INTENT(IN)                          :: etot
     926              : 
     927              :       LOGICAL                                            :: shell_adiabatic, shell_present
     928              :       TYPE(atomic_kind_list_type), POINTER               :: atomic_kinds
     929         8410 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     930              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     931              :       TYPE(particle_list_type), POINTER                  :: core_particles, shell_particles
     932              : 
     933         8410 :       NULLIFY (atomic_kinds)
     934         8410 :       NULLIFY (atomic_kind_set)
     935         8410 :       NULLIFY (core_particles)
     936         8410 :       NULLIFY (shell_particles)
     937         8410 :       NULLIFY (subsys)
     938              : 
     939         8410 :       CALL write_trajectory(force_env, root_section, it, 0.0_dp, 0.0_dp, etot)
     940              :       ! Print Force
     941         8410 :       CALL write_trajectory(force_env, root_section, it, 0.0_dp, 0.0_dp, etot, "FORCES", middle_name="frc")
     942         8410 :       CALL force_env_get(force_env, subsys=subsys)
     943         8410 :       CALL cp_subsys_get(subsys, atomic_kinds=atomic_kinds)
     944         8410 :       atomic_kind_set => atomic_kinds%els
     945              :       CALL get_atomic_kind_set(atomic_kind_set, &
     946              :                                shell_present=shell_present, &
     947         8410 :                                shell_adiabatic=shell_adiabatic)
     948         8410 :       IF (shell_present) THEN
     949              :          CALL cp_subsys_get(subsys, &
     950              :                             core_particles=core_particles, &
     951         3406 :                             shell_particles=shell_particles)
     952              :          CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
     953              :                                etot=etot, pk_name="SHELL_TRAJECTORY", middle_name="shpos", &
     954         3406 :                                particles=shell_particles)
     955         3406 :          IF (shell_adiabatic) THEN
     956              :             CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
     957              :                                   etot=etot, pk_name="SHELL_FORCES", middle_name="shfrc", &
     958         3406 :                                   particles=shell_particles)
     959              :             CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
     960              :                                   etot=etot, pk_name="CORE_TRAJECTORY", middle_name="copos", &
     961         3406 :                                   particles=core_particles)
     962              :             CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
     963              :                                   etot=etot, pk_name="CORE_FORCES", middle_name="cofrc", &
     964         3406 :                                   particles=core_particles)
     965              :          END IF
     966              :       END IF
     967              : 
     968         8410 :    END SUBROUTINE write_geo_traj
     969              : 
     970              : ! **************************************************************************************************
     971              : !> \brief ...
     972              : !> \param gopt_env ...
     973              : !> \param output_unit ...
     974              : !> \param label ...
     975              : !> \date  01.2008
     976              : !> \author Teodoro Laino [tlaino] - University of Zurich
     977              : ! **************************************************************************************************
     978         1223 :    SUBROUTINE print_geo_opt_header(gopt_env, output_unit, label)
     979              : 
     980              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     981              :       INTEGER, INTENT(IN)                                :: output_unit
     982              :       CHARACTER(LEN=*), INTENT(IN)                       :: label
     983              : 
     984              :       CHARACTER(LEN=default_string_length)               :: my_format, my_label
     985              :       INTEGER                                            :: ix
     986              : 
     987         1223 :       IF (output_unit > 0) THEN
     988          629 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
     989          629 :          IF (gopt_env%dimer_rotation) THEN
     990           66 :             my_label = "OPTIMIZING DIMER ROTATION"
     991              :          ELSE
     992          563 :             my_label = "STARTING "//gopt_env%tag(1:8)//" OPTIMIZATION"
     993              :          END IF
     994              : 
     995          629 :          ix = (80 - 7 - LEN_TRIM(my_label))/2
     996          629 :          ix = ix + 5
     997          629 :          my_format = "(T2,A,T"//cp_to_string(ix)//",A,T78,A)"
     998          629 :          WRITE (UNIT=output_unit, FMT=TRIM(my_format)) "***", TRIM(my_label), "***"
     999              : 
    1000          629 :          ix = (80 - 7 - LEN_TRIM(label))/2
    1001          629 :          ix = ix + 5
    1002          629 :          my_format = "(T2,A,T"//cp_to_string(ix)//",A,T78,A)"
    1003          629 :          WRITE (UNIT=output_unit, FMT=TRIM(my_format)) "***", TRIM(label), "***"
    1004              : 
    1005          629 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
    1006          629 :          CALL m_flush(output_unit)
    1007              :       END IF
    1008         1223 :    END SUBROUTINE print_geo_opt_header
    1009              : 
    1010              : ! **************************************************************************************************
    1011              : !> \brief ...
    1012              : !> \param gopt_env ...
    1013              : !> \param output_unit ...
    1014              : !> \date  01.2008
    1015              : !> \author Teodoro Laino [tlaino] - University of Zurich
    1016              : ! **************************************************************************************************
    1017          725 :    SUBROUTINE print_geo_opt_nc(gopt_env, output_unit)
    1018              : 
    1019              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
    1020              :       INTEGER, INTENT(IN)                                :: output_unit
    1021              : 
    1022          725 :       IF (output_unit > 0) THEN
    1023              :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
    1024          363 :             "*** MAXIMUM NUMBER OF OPTIMIZATION STEPS REACHED ***"
    1025          363 :          IF (.NOT. gopt_env%dimer_rotation) THEN
    1026              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1027          352 :                "***        EXITING GEOMETRY OPTIMIZATION         ***"
    1028              :          ELSE
    1029              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1030           11 :                "***        EXITING ROTATION OPTIMIZATION         ***"
    1031              :          END IF
    1032          363 :          CALL m_flush(output_unit)
    1033              :       END IF
    1034              : 
    1035          725 :    END SUBROUTINE print_geo_opt_nc
    1036              : 
    1037              : ! **************************************************************************************************
    1038              : !> \brief   Prints information during GEO_OPT common to all optimizers
    1039              : !> \param force_env ...
    1040              : !> \param root_section ...
    1041              : !> \param motion_section ...
    1042              : !> \param its ...
    1043              : !> \param opt_energy ...
    1044              : !> \date    02.2008
    1045              : !> \author  Teodoro Laino [tlaino] - University of Zurich
    1046              : !> \version 1.0
    1047              : ! **************************************************************************************************
    1048         8054 :    SUBROUTINE geo_opt_io(force_env, root_section, motion_section, its, opt_energy)
    1049              : 
    1050              :       TYPE(force_env_type), POINTER                      :: force_env
    1051              :       TYPE(section_vals_type), POINTER                   :: root_section, motion_section
    1052              :       INTEGER, INTENT(IN)                                :: its
    1053              :       REAL(KIND=dp), INTENT(IN)                          :: opt_energy
    1054              : 
    1055              :       TYPE(atomic_kind_list_type), POINTER               :: atomic_kinds
    1056         8054 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1057              :       TYPE(cell_type), POINTER                           :: cell
    1058              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1059              :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1060              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1061              :       TYPE(particle_list_type), POINTER                  :: particles
    1062         8054 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1063              :       TYPE(virial_type), POINTER                         :: virial
    1064              : 
    1065         8054 :       NULLIFY (para_env, atomic_kind_set, subsys, particle_set, &
    1066         8054 :                local_particles, atomic_kinds, particles)
    1067              : 
    1068              :       ! Write Restart File
    1069         8054 :       CALL write_restart(force_env=force_env, root_section=root_section)
    1070              : 
    1071              :       ! Write Trajectory
    1072         8054 :       CALL write_geo_traj(force_env, root_section, its, opt_energy)
    1073              : 
    1074              :       ! Write the stress Tensor
    1075              :       CALL force_env_get(force_env, cell=cell, para_env=para_env, &
    1076         8054 :                          subsys=subsys)
    1077              :       CALL cp_subsys_get(subsys=subsys, atomic_kinds=atomic_kinds, local_particles=local_particles, &
    1078         8054 :                          particles=particles, virial=virial)
    1079         8054 :       atomic_kind_set => atomic_kinds%els
    1080         8054 :       particle_set => particles%els
    1081              :       CALL virial_evaluate(atomic_kind_set, particle_set, local_particles, &
    1082         8054 :                            virial, para_env)
    1083         8054 :       CALL write_stress_tensor_to_file(virial, cell, motion_section, its, 0.0_dp)
    1084              : 
    1085              :       ! Write the cell
    1086         8054 :       CALL write_simulation_cell(cell, motion_section, its, 0.0_dp)
    1087              : 
    1088         8054 :    END SUBROUTINE geo_opt_io
    1089              : 
    1090              : ! **************************************************************************************************
    1091              : !> \brief   Apply coordinate transformations after cell (shape) change
    1092              : !> \param gopt_env ...
    1093              : !> \param cell ...
    1094              : !> \param x ...
    1095              : !> \param update_forces ...
    1096              : !> \date    05.11.2012 (revised version of unbiase_coordinates moved here, MK)
    1097              : !> \author  Matthias Krack
    1098              : !> \version 1.0
    1099              : ! **************************************************************************************************
    1100        12990 :    SUBROUTINE apply_cell_change(gopt_env, cell, x, update_forces)
    1101              : 
    1102              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
    1103              :       TYPE(cell_type), POINTER                           :: cell
    1104              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x
    1105              :       LOGICAL, INTENT(IN)                                :: update_forces
    1106              : 
    1107              :       INTEGER                                            :: i, iatom, idg, j, natom, nparticle, &
    1108              :                                                             shell_index
    1109              :       REAL(KIND=dp)                                      :: fc, fs, mass
    1110              :       REAL(KIND=dp), DIMENSION(3)                        :: s
    1111              :       TYPE(cell_type), POINTER                           :: cell_ref
    1112              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1113              :       TYPE(particle_list_type), POINTER                  :: core_particles, particles, &
    1114              :                                                             shell_particles
    1115              : 
    1116        12990 :       NULLIFY (cell_ref)
    1117        12990 :       NULLIFY (core_particles)
    1118        12990 :       NULLIFY (particles)
    1119        12990 :       NULLIFY (shell_particles)
    1120        12990 :       NULLIFY (subsys)
    1121              : 
    1122        12990 :       natom = force_env_get_natom(gopt_env%force_env)
    1123        12990 :       nparticle = force_env_get_nparticle(gopt_env%force_env)
    1124              :       CALL force_env_get(gopt_env%force_env, &
    1125        12990 :                          subsys=subsys)
    1126              :       CALL cp_subsys_get(subsys=subsys, &
    1127              :                          core_particles=core_particles, &
    1128              :                          particles=particles, &
    1129        12990 :                          shell_particles=shell_particles)
    1130              : 
    1131              :       ! Retrieve the reference cell
    1132        12990 :       CALL cell_create(cell_ref)
    1133        12990 :       CALL cell_copy(cell, cell_ref, tag="CELL_OPT_REF")
    1134              : 
    1135              :       ! Load the updated cell information
    1136        12990 :       idg = 3*nparticle
    1137        12990 :       CALL init_cell(cell_ref, hmat=gopt_env%h_ref)
    1138        12990 :       CPASSERT((SIZE(x) == idg + 6))
    1139              : 
    1140        12990 :       IF (update_forces) THEN
    1141              : 
    1142              :          ! Transform particle forces back to reference cell
    1143              :          idg = 1
    1144       298478 :          DO iatom = 1, natom
    1145       293416 :             CALL real_to_scaled(s, x(idg:idg + 2), cell)
    1146       293416 :             CALL scaled_to_real(x(idg:idg + 2), s, cell_ref)
    1147       298478 :             idg = idg + 3
    1148              :          END DO
    1149              : 
    1150              :       ELSE
    1151              : 
    1152              :          ! Update cell
    1153        31712 :          DO i = 1, 3
    1154        79280 :             DO j = 1, i
    1155        47568 :                idg = idg + 1
    1156        71352 :                cell%hmat(j, i) = x(idg)
    1157              :             END DO
    1158              :          END DO
    1159         7928 :          CALL init_cell(cell)
    1160         7928 :          CALL cp_subsys_set(subsys, cell=cell)
    1161              : 
    1162              :          ! Retrieve particle coordinates for the current cell
    1163         7928 :          idg = 1
    1164       548522 :          DO iatom = 1, natom
    1165       540594 :             CALL real_to_scaled(s, x(idg:idg + 2), cell_ref)
    1166       540594 :             shell_index = particles%els(iatom)%shell_index
    1167       540594 :             IF (shell_index == 0) THEN
    1168       222258 :                CALL scaled_to_real(particles%els(iatom)%r, s, cell)
    1169              :             ELSE
    1170       318336 :                CALL scaled_to_real(core_particles%els(shell_index)%r, s, cell)
    1171       318336 :                i = 3*(natom + shell_index - 1) + 1
    1172       318336 :                CALL real_to_scaled(s, x(i:i + 2), cell_ref)
    1173       318336 :                CALL scaled_to_real(shell_particles%els(shell_index)%r, s, cell)
    1174              :                ! Update atomic position due to core and shell motion
    1175       318336 :                mass = particles%els(iatom)%atomic_kind%mass
    1176       318336 :                fc = core_particles%els(shell_index)%atomic_kind%shell%mass_core/mass
    1177       318336 :                fs = shell_particles%els(shell_index)%atomic_kind%shell%mass_shell/mass
    1178              :                particles%els(iatom)%r(1:3) = fc*core_particles%els(shell_index)%r(1:3) + &
    1179      2546688 :                                              fs*shell_particles%els(shell_index)%r(1:3)
    1180              :             END IF
    1181       548522 :             idg = idg + 3
    1182              :          END DO
    1183              :       END IF
    1184              : 
    1185        12990 :       CALL cell_release(cell_ref)
    1186              : 
    1187        12990 :    END SUBROUTINE apply_cell_change
    1188              : 
    1189              : END MODULE gopt_f_methods
        

Generated by: LCOV version 2.0-1