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

Generated by: LCOV version 2.0-1