LCOV - code coverage report
Current view: top level - src/motion - gopt_f_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 98.4 % 491 483
Test Date: 2026-09-24 01:27:39 Functions: 100.0 % 17 17

            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 bibliography,                    ONLY: Henkelman1999,&
      20              :                                               cite_reference
      21              :    USE cell_methods,                    ONLY: cell_create,&
      22              :                                               init_cell,&
      23              :                                               write_cell
      24              :    USE cell_opt_utils,                  ONLY: get_dg_dh,&
      25              :                                               rescale_new_cell_volume
      26              :    USE cell_types,                      ONLY: cell_copy,&
      27              :                                               cell_release,&
      28              :                                               cell_type,&
      29              :                                               real_to_scaled,&
      30              :                                               scaled_to_real
      31              :    USE cp_log_handling,                 ONLY: cp_to_string
      32              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      33              :                                               cp_subsys_set,&
      34              :                                               cp_subsys_type,&
      35              :                                               pack_subsys_particles,&
      36              :                                               unpack_subsys_particles
      37              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      38              :    USE dimer_methods,                   ONLY: cp_eval_at_ts
      39              :    USE dimer_types,                     ONLY: dimer_env_type
      40              :    USE dimer_utils,                     ONLY: update_dimer_vec
      41              :    USE distribution_1d_types,           ONLY: distribution_1d_type
      42              :    USE force_env_methods,               ONLY: force_env_calc_energy_force
      43              :    USE force_env_types,                 ONLY: force_env_get,&
      44              :                                               force_env_get_natom,&
      45              :                                               force_env_get_nparticle,&
      46              :                                               force_env_type,&
      47              :                                               use_qmmm,&
      48              :                                               use_qmmmx
      49              :    USE gopt_f_types,                    ONLY: gopt_f_type
      50              :    USE gopt_param_types,                ONLY: gopt_param_type
      51              :    USE input_constants,                 ONLY: &
      52              :         default_cell_method_id, default_minimization_method_id, default_shellcore_method_id, &
      53              :         default_ts_method_id, fix_none, fix_x, fix_xy, fix_xz, fix_y, fix_yz, 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 space_groups,                    ONLY: spgr_apply_rotations_force,&
      73              :                                               spgr_apply_rotations_stress,&
      74              :                                               spgr_project_cell_metric,&
      75              :                                               spgr_write_stress_tensor
      76              :    USE space_groups_types,              ONLY: spgr_type
      77              :    USE virial_methods,                  ONLY: virial_evaluate,&
      78              :                                               virial_update
      79              :    USE virial_types,                    ONLY: virial_type
      80              : #include "../base/base_uses.f90"
      81              : 
      82              :    IMPLICIT NONE
      83              :    PRIVATE
      84              : 
      85              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      86              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gopt_f_methods'
      87              : 
      88              :    PUBLIC :: cp_eval_at, &
      89              :              gopt_f_create_x0, &
      90              :              print_geo_opt_header, print_geo_opt_nc, &
      91              :              gopt_f_io_init, gopt_f_io, gopt_f_io_finalize, gopt_f_ii, &
      92              :              apply_cell_change
      93              : 
      94              : CONTAINS
      95              : 
      96              : ! **************************************************************************************************
      97              : !> \brief returns the value of the parameters for the actual configuration
      98              : !> \param gopt_env the geometry optimization environment you want the info about
      99              : !>      x0: the parameter vector (is allocated by this routine)
     100              : !> \param x0 ...
     101              : !> \par History
     102              : !>      - Cell optimization revised (06.11.2012,MK)
     103              : ! **************************************************************************************************
     104         1105 :    SUBROUTINE gopt_f_create_x0(gopt_env, x0)
     105              : 
     106              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     107              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x0
     108              : 
     109              :       INTEGER                                            :: i, idg, j, nparticle
     110              :       TYPE(cell_type), POINTER                           :: cell
     111              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     112              : 
     113         1105 :       NULLIFY (cell)
     114         1105 :       NULLIFY (subsys)
     115              : 
     116         1994 :       SELECT CASE (gopt_env%type_id)
     117              :       CASE (default_minimization_method_id, default_ts_method_id)
     118          889 :          CALL force_env_get(gopt_env%force_env, subsys=subsys)
     119              :          ! before starting we handle the case of translating coordinates (QM/MM)
     120          889 :          IF (gopt_env%force_env%in_use == use_qmmm) THEN
     121           36 :             CALL apply_qmmm_translate(gopt_env%force_env%qmmm_env)
     122              :          END IF
     123          889 :          IF (gopt_env%force_env%in_use == use_qmmmx) THEN
     124            0 :             CALL apply_qmmmx_translate(gopt_env%force_env%qmmmx_env)
     125              :          END IF
     126          889 :          nparticle = force_env_get_nparticle(gopt_env%force_env)
     127         2667 :          ALLOCATE (x0(3*nparticle))
     128          889 :          CALL pack_subsys_particles(subsys=subsys, r=x0)
     129              :       CASE (default_cell_method_id)
     130          216 :          CALL force_env_get(gopt_env%force_env, subsys=subsys, cell=cell)
     131              :          ! Store reference cell
     132         5616 :          gopt_env%h_ref = cell%hmat
     133              :          ! before starting we handle the case of translating coordinates (QM/MM)
     134          216 :          IF (gopt_env%force_env%in_use == use_qmmm) THEN
     135            0 :             CALL apply_qmmm_translate(gopt_env%force_env%qmmm_env)
     136              :          END IF
     137          216 :          IF (gopt_env%force_env%in_use == use_qmmmx) THEN
     138            0 :             CALL apply_qmmmx_translate(gopt_env%force_env%qmmmx_env)
     139              :          END IF
     140          216 :          nparticle = force_env_get_nparticle(gopt_env%force_env)
     141          648 :          ALLOCATE (x0(3*nparticle + 6))
     142          216 :          CALL pack_subsys_particles(subsys=subsys, r=x0)
     143          216 :          idg = 3*nparticle
     144          864 :          DO i = 1, 3
     145         2160 :             DO j = 1, i
     146         1296 :                idg = idg + 1
     147         1944 :                x0(idg) = gopt_env%cell_env%opt_cell%hmat(j, i)
     148              :             END DO
     149              :          END DO
     150              :       CASE DEFAULT
     151         1105 :          CPABORT("Invalid or not yet implemented type of optimization")
     152              :       END SELECT
     153              : 
     154         1105 :    END SUBROUTINE gopt_f_create_x0
     155              : 
     156              : ! **************************************************************************************************
     157              : !> \brief evaluete the potential energy and its gradients using an array
     158              : !>      with same dimension as the particle_set
     159              : !> \param gopt_env the geometry optimization environment
     160              : !> \param x the position where the function should be evaluated
     161              : !> \param f the function value
     162              : !> \param gradient the value of its gradient
     163              : !> \param master ...
     164              : !> \param final_evaluation ...
     165              : !> \param para_env ...
     166              : !> \par History
     167              : !>       CELL OPTIMIZATION:  Teodoro Laino [tlaino] - University of Zurich - 03.2008
     168              : !>       07.2020 Pierre Cazade [pcazade] Space Group Symmetry
     169              : !> \author Teodoro Laino [tlaino] - University of Zurich - 01.2008
     170              : ! **************************************************************************************************
     171        16765 :    SUBROUTINE cp_eval_at(gopt_env, x, f, gradient, master, &
     172              :                          final_evaluation, para_env)
     173              : 
     174              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     175              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x
     176              :       REAL(KIND=dp), INTENT(OUT), OPTIONAL               :: f
     177              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: gradient
     178              :       INTEGER, INTENT(IN)                                :: master
     179              :       LOGICAL, INTENT(IN), OPTIONAL                      :: final_evaluation
     180              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     181              : 
     182              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cp_eval_at'
     183              : 
     184              :       INTEGER                                            :: handle, idg, idir, ip, nparticle, nsize, &
     185              :                                                             shell_index
     186              :       REAL(KIND=dp)                                      :: f_ts
     187              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: av_ptens, av_ptens_opt
     188        16765 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cell_gradient, gradient_ts
     189              :       TYPE(cell_type), POINTER                           :: cell
     190              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     191              :       TYPE(particle_list_type), POINTER                  :: core_particles, particles, &
     192              :                                                             shell_particles
     193              :       TYPE(spgr_type), POINTER                           :: spgr
     194              :       TYPE(virial_type), POINTER                         :: virial
     195              : 
     196              :       MARK_USED(final_evaluation)
     197              : 
     198        16765 :       NULLIFY (cell)
     199        16765 :       NULLIFY (core_particles)
     200        16765 :       NULLIFY (gradient_ts)
     201        16765 :       NULLIFY (particles)
     202        16765 :       NULLIFY (shell_particles)
     203        16765 :       NULLIFY (subsys)
     204        16765 :       NULLIFY (virial)
     205        16765 :       NULLIFY (spgr)
     206              : 
     207        16765 :       CALL timeset(routineN, handle)
     208              : 
     209        16765 :       CALL force_env_get(gopt_env%force_env, subsys=subsys, cell=cell)
     210              :       CALL cp_subsys_get(subsys, &
     211              :                          core_particles=core_particles, &
     212              :                          particles=particles, &
     213              :                          shell_particles=shell_particles, &
     214        16765 :                          virial=virial)
     215              : 
     216        16765 :       spgr => gopt_env%spgr
     217              : 
     218        25176 :       SELECT CASE (gopt_env%type_id)
     219              :       CASE (default_minimization_method_id, default_ts_method_id)
     220         8411 :          CALL unpack_subsys_particles(subsys=subsys, r=x)
     221         8411 :          CALL write_structure_data(particles%els, cell, gopt_env%motion_section)
     222        15034 :          SELECT CASE (gopt_env%type_id)
     223              :          CASE (default_minimization_method_id)
     224              :             ! Geometry Minimization
     225              :             CALL force_env_calc_energy_force(gopt_env%force_env, &
     226              :                                              calc_force=PRESENT(gradient), &
     227         6623 :                                              require_consistent_energy_force=gopt_env%require_consistent_energy_force)
     228              :             ! Possibly take the potential energy
     229         6623 :             IF (PRESENT(f)) THEN
     230         6623 :                CALL force_env_get(gopt_env%force_env, potential_energy=f)
     231              :             END IF
     232              :             ! Possibly take the gradients
     233         6623 :             IF (PRESENT(gradient)) THEN
     234         6085 :                IF (master == para_env%mepos) THEN ! we are on the master
     235         5933 :                   CALL pack_subsys_particles(subsys=subsys, f=gradient, fscale=-1.0_dp)
     236         5933 :                   IF (spgr%keep_space_group) THEN
     237            8 :                      CALL spgr_apply_rotations_force(spgr, gradient)
     238            8 :                      CALL unpack_subsys_particles(subsys=subsys, f=gradient, fscale=-1.0_dp)
     239              :                   END IF
     240              :                END IF
     241              :             END IF
     242              :          CASE (default_ts_method_id)
     243              :             ! Transition State Optimization
     244         5364 :             ALLOCATE (gradient_ts(particles%n_els*3))
     245              :             ! Real calculation of energy and forces for transition state optimization:
     246              :             ! When doing dimer methods forces have to be always computed since the function
     247              :             ! to minimize is not the energy but the effective force
     248         1788 :             CALL cp_eval_at_ts(gopt_env, x, f_ts, gradient_ts, calc_force=.TRUE.)
     249         1788 :             CALL cite_reference(Henkelman1999)
     250              :             ! Possibly take the potential energy
     251         1788 :             IF (PRESENT(f)) f = f_ts
     252              :             ! Possibly take the gradients
     253         1788 :             IF (PRESENT(gradient)) THEN
     254          844 :                IF (master == para_env%mepos) THEN ! we are on the master
     255          844 :                   CPASSERT(ASSOCIATED(gradient))
     256        29420 :                   gradient = gradient_ts
     257              :                END IF
     258              :             END IF
     259        10199 :             DEALLOCATE (gradient_ts)
     260              :          END SELECT
     261              :          ! This call is necessary for QM/MM if a Translation is applied
     262              :          ! this makes the geometry optimizer consistent
     263         8411 :          CALL unpack_subsys_particles(subsys=subsys, r=x)
     264              :       CASE (default_cell_method_id)
     265              :          ! Check for VIRIAL
     266         8034 :          IF (.NOT. virial%pv_availability) THEN
     267              :             CALL cp_abort(__LOCATION__, &
     268              :                           "For the CELL_OPT task, the FORCE_EVAL/STRESS_TENSOR "// &
     269              :                           "keyword MUST be defined in the input file for the "// &
     270            0 :                           "evaluation of the stress tensor, but none is found!")
     271              :          END IF
     272         8034 :          IF (gopt_env%cell_env%keep_volume) THEN
     273         2284 :             nparticle = force_env_get_nparticle(gopt_env%force_env)
     274         2284 :             idg = 3*nparticle
     275         2284 :             CALL rescale_new_cell_volume(cell%deth, x, idg)
     276              :          END IF
     277              : 
     278         8034 :          CALL apply_cell_change(gopt_env, cell, x, update_forces=.FALSE.)
     279              :          ! Possibly output the new cell used for the next calculation
     280         8034 :          CALL write_cell(cell, gopt_env%geo_section)
     281              :          ! Compute the pressure tensor
     282         8034 :          BLOCK
     283              :             TYPE(virial_type) :: virial_avg
     284              :             CALL force_env_calc_energy_force(gopt_env%force_env, &
     285              :                                              calc_force=PRESENT(gradient), &
     286         8034 :                                              require_consistent_energy_force=gopt_env%require_consistent_energy_force)
     287              :             ! Possibly take the potential energy
     288         8034 :             virial_avg = virial
     289         8034 :             CALL virial_update(virial_avg, subsys, para_env)
     290         8034 :             IF (PRESENT(f)) THEN
     291         8034 :                CALL force_env_get(gopt_env%force_env, potential_energy=f)
     292              :             END IF
     293              :             ! Possibly take the gradients
     294      1992432 :             IF (PRESENT(gradient)) THEN
     295         6724 :                CPASSERT(ANY(virial_avg%pv_total /= 0))
     296              :                ! Convert the average ptens
     297        87412 :                av_ptens(:, :) = virial_avg%pv_total(:, :)/cell%deth
     298         6724 :                IF (master == para_env%mepos) THEN ! we are on the master
     299         5176 :                   CPASSERT(ASSOCIATED(gradient))
     300         5176 :                   nparticle = force_env_get_nparticle(gopt_env%force_env)
     301         5176 :                   nsize = 3*nparticle
     302         5176 :                   CPASSERT((SIZE(gradient) == nsize + 6))
     303         5176 :                   CALL pack_subsys_particles(subsys=subsys, f=gradient(1:nsize), fscale=-1.0_dp)
     304         5176 :                   CALL apply_cell_change(gopt_env, cell, gradient, update_forces=.TRUE.)
     305         5176 :                   IF (spgr%keep_space_group) THEN
     306          556 :                      CALL spgr_apply_rotations_force(spgr, gradient)
     307          556 :                      CALL spgr_apply_rotations_stress(spgr, cell, av_ptens)
     308          556 :                      CALL spgr_write_stress_tensor(av_ptens, spgr)
     309              :                   END IF
     310         5176 :                   cell_gradient => gradient(nsize + 1:nsize + 6)
     311        36232 :                   cell_gradient = 0.0_dp
     312              :                   av_ptens_opt = MATMUL(gopt_env%cell_env%input_to_opt, &
     313       408904 :                                         MATMUL(av_ptens, gopt_env%cell_env%opt_to_input))
     314              :                   CALL get_dg_dh(cell_gradient, av_ptens_opt, gopt_env%cell_env%pres_ext, &
     315              :                                  gopt_env%cell_env%opt_cell, gopt_env%cell_env%mtrx, &
     316              :                                  keep_angles=gopt_env%cell_env%keep_angles, &
     317              :                                  keep_symmetry=gopt_env%cell_env%keep_symmetry, &
     318              :                                  pres_int=gopt_env%cell_env%pres_int, &
     319              :                                  pres_constr=gopt_env%cell_env%pres_constr, &
     320         5176 :                                  constraint_id=gopt_env%cell_env%constraint_id)
     321              :                END IF
     322              :                ! some callers expect pres_int to be available on all ranks. Also, here master is not necessarily a single rank.
     323              :                ! Assume at least master==0
     324         6724 :                CALL para_env%bcast(gopt_env%cell_env%pres_int, 0)
     325         6724 :                IF (gopt_env%cell_env%constraint_id /= fix_none) THEN
     326           24 :                   CALL para_env%bcast(gopt_env%cell_env%pres_constr, 0)
     327              :                END IF
     328              :             END IF
     329              :          END BLOCK
     330              :       CASE (default_shellcore_method_id)
     331              :          idg = 0
     332        31040 :          DO ip = 1, particles%n_els
     333        30720 :             shell_index = particles%els(ip)%shell_index
     334        31040 :             IF (shell_index /= 0) THEN
     335       122880 :                DO idir = 1, 3
     336        92160 :                   idg = 3*(shell_index - 1) + idir
     337       122880 :                   shell_particles%els(shell_index)%r(idir) = core_particles%els(ip)%r(idir) - x(idg)
     338              :                END DO
     339              :             END IF
     340              :          END DO
     341          320 :          CALL write_structure_data(particles%els, cell, gopt_env%motion_section)
     342              : 
     343              :          ! Shell-core optimization
     344              :          CALL force_env_calc_energy_force(gopt_env%force_env, &
     345              :                                           calc_force=PRESENT(gradient), &
     346          320 :                                           require_consistent_energy_force=gopt_env%require_consistent_energy_force)
     347              : 
     348              :          ! Possibly take the potential energy
     349          320 :          IF (PRESENT(f)) THEN
     350          320 :             CALL force_env_get(gopt_env%force_env, potential_energy=f)
     351              :          END IF
     352              : 
     353              :          ! Possibly take the gradients
     354          320 :          IF (PRESENT(gradient)) THEN
     355          320 :             IF (master == para_env%mepos) THEN ! we are on the master
     356          320 :                CPASSERT(ASSOCIATED(gradient))
     357          320 :                idg = 0
     358        31040 :                DO ip = 1, shell_particles%n_els
     359       123200 :                   DO idir = 1, 3
     360        92160 :                      idg = idg + 1
     361       122880 :                      gradient(idg) = -(core_particles%els(ip)%f(idir) - shell_particles%els(ip)%f(idir))
     362              :                   END DO
     363              :                END DO
     364              :             END IF
     365              :          END IF
     366              :       CASE DEFAULT
     367        16765 :          CPABORT("Invalid or not yet implemented type of optimization")
     368              :       END SELECT
     369              : 
     370        16765 :       CALL timestop(handle)
     371              : 
     372        16765 :    END SUBROUTINE cp_eval_at
     373              : 
     374              : ! **************************************************************************************************
     375              : !> \brief Prints iteration step of the optimization procedure on screen
     376              : !> \param its ...
     377              : !> \param output_unit ...
     378              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     379              : ! **************************************************************************************************
     380         9172 :    SUBROUTINE gopt_f_ii(its, output_unit)
     381              : 
     382              :       INTEGER, INTENT(IN)                                :: its, output_unit
     383              : 
     384         9172 :       IF (output_unit > 0) THEN
     385         4746 :          WRITE (UNIT=output_unit, FMT="(/,T2,26('-'))")
     386         4746 :          WRITE (UNIT=output_unit, FMT="(T2,A,I6)") "OPTIMIZATION STEP: ", its
     387         4746 :          WRITE (UNIT=output_unit, FMT="(T2,26('-'))")
     388         4746 :          CALL m_flush(output_unit)
     389              :       END IF
     390              : 
     391         9172 :    END SUBROUTINE gopt_f_ii
     392              : 
     393              : ! **************************************************************************************************
     394              : !> \brief Retrieves the reporting metadata used during an optimization step.
     395              : !> \param gopt_env Optimization environment supplying print configuration and units
     396              : !> \param force_env Force environment used for memory sampling
     397              : !> \param max_memory Sampled memory, or zero if memory reporting is disabled
     398              : !> \param energy_unit Energy reporting unit
     399              : !> \param stress_unit Stress reporting unit
     400              : ! **************************************************************************************************
     401        10333 :    SUBROUTINE get_reporting_metadata(gopt_env, force_env, max_memory, energy_unit, stress_unit)
     402              : 
     403              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     404              :       TYPE(force_env_type), POINTER                      :: force_env
     405              :       INTEGER(KIND=int_8), INTENT(OUT)                   :: max_memory
     406              :       CHARACTER(LEN=default_string_length), INTENT(OUT)  :: energy_unit, stress_unit
     407              : 
     408              :       LOGICAL                                            :: print_memory
     409              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     410              : 
     411        10333 :       NULLIFY (para_env)
     412        10333 :       CALL section_vals_val_get(gopt_env%motion_section, "PRINT%MEMORY_INFO", l_val=print_memory)
     413        10333 :       max_memory = 0
     414        10333 :       IF (print_memory) THEN
     415        10333 :          CALL force_env_get(force_env, para_env=para_env)
     416        10333 :          max_memory = sample_memory(para_env)
     417              :       END IF
     418              : 
     419              :       CALL section_vals_val_get(gopt_env%force_env%force_env_section, &
     420              :                                 "PRINT%PROGRAM_RUN_INFO%ENERGY_UNIT", &
     421        10333 :                                 c_val=energy_unit)
     422              :       CALL section_vals_val_get(gopt_env%force_env%force_env_section, &
     423              :                                 "PRINT%STRESS_TENSOR%STRESS_UNIT", &
     424        10333 :                                 c_val=stress_unit)
     425              : 
     426        10333 :    END SUBROUTINE get_reporting_metadata
     427              : 
     428              : ! **************************************************************************************************
     429              : !> \brief Handles the Output during an optimization run
     430              : !> \param gopt_env ...
     431              : !> \param output_unit ...
     432              : !> \param opt_energy ...
     433              : !> \param wildcard ...
     434              : !> \param its ...
     435              : !> \param used_time ...
     436              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     437              : ! **************************************************************************************************
     438         1163 :    SUBROUTINE gopt_f_io_init(gopt_env, output_unit, opt_energy, wildcard, its, used_time)
     439              : 
     440              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     441              :       INTEGER, INTENT(IN)                                :: output_unit
     442              :       REAL(KIND=dp)                                      :: opt_energy
     443              :       CHARACTER(LEN=5)                                   :: wildcard
     444              :       INTEGER, INTENT(IN)                                :: its
     445              :       REAL(KIND=dp)                                      :: used_time
     446              : 
     447              :       CHARACTER(LEN=default_string_length)               :: energy_unit, stress_unit
     448              :       INTEGER(KIND=int_8)                                :: max_memory
     449              :       REAL(KIND=dp)                                      :: pres_int
     450              : 
     451         1163 :       CALL get_reporting_metadata(gopt_env, gopt_env%force_env, max_memory, energy_unit, stress_unit)
     452              : 
     453         2134 :       SELECT CASE (gopt_env%type_id)
     454              :       CASE (default_ts_method_id, default_minimization_method_id)
     455              :          ! Geometry Optimization (Minimization and Transition State Search)
     456          971 :          IF (.NOT. gopt_env%dimer_rotation) THEN
     457              :             CALL write_cycle_infos(output_unit, &
     458              :                                    it=its, &
     459              :                                    etot=opt_energy, &
     460              :                                    wildcard=wildcard, &
     461              :                                    used_time=used_time, &
     462              :                                    max_memory=max_memory, &
     463              :                                    energy_unit=energy_unit, &
     464          843 :                                    stress_unit=stress_unit)
     465              :          ELSE
     466              :             CALL write_rot_cycle_infos(output_unit, &
     467              :                                        it=its, &
     468              :                                        etot=opt_energy, &
     469              :                                        dimer_env=gopt_env%dimer_env, &
     470              :                                        wildcard=wildcard, &
     471              :                                        used_time=used_time, &
     472          128 :                                        max_memory=max_memory)
     473              :          END IF
     474              :       CASE (default_cell_method_id)
     475              :          ! Cell Optimization
     476          172 :          pres_int = gopt_env%cell_env%pres_int
     477              :          CALL write_cycle_infos(output_unit, &
     478              :                                 it=its, &
     479              :                                 etot=opt_energy, &
     480              :                                 pres_int=pres_int, &
     481              :                                 wildcard=wildcard, &
     482              :                                 used_time=used_time, &
     483              :                                 max_memory=max_memory, &
     484              :                                 energy_unit=energy_unit, &
     485          172 :                                 stress_unit=stress_unit)
     486              :       CASE (default_shellcore_method_id)
     487              :          CALL write_cycle_infos(output_unit, &
     488              :                                 it=its, &
     489              :                                 etot=opt_energy, &
     490              :                                 wildcard=wildcard, &
     491              :                                 used_time=used_time, &
     492              :                                 max_memory=max_memory, &
     493              :                                 energy_unit=energy_unit, &
     494         1163 :                                 stress_unit=stress_unit)
     495              :       END SELECT
     496              : 
     497         1163 :    END SUBROUTINE gopt_f_io_init
     498              : 
     499              : ! **************************************************************************************************
     500              : !> \brief Handles the Output during an optimization run
     501              : !> \param gopt_env ...
     502              : !> \param force_env ...
     503              : !> \param root_section ...
     504              : !> \param its ...
     505              : !> \param opt_energy ...
     506              : !> \param output_unit ...
     507              : !> \param eold ...
     508              : !> \param emin ...
     509              : !> \param wildcard ...
     510              : !> \param gopt_param ...
     511              : !> \param ndf ...
     512              : !> \param dx ...
     513              : !> \param xi ...
     514              : !> \param conv ...
     515              : !> \param pred ...
     516              : !> \param rat ...
     517              : !> \param step ...
     518              : !> \param rad ...
     519              : !> \param used_time ...
     520              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     521              : ! **************************************************************************************************
     522        18340 :    SUBROUTINE gopt_f_io(gopt_env, force_env, root_section, its, opt_energy, &
     523         9170 :                         output_unit, eold, emin, wildcard, gopt_param, ndf, dx, xi, conv, pred, rat, &
     524              :                         step, rad, used_time)
     525              : 
     526              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     527              :       TYPE(force_env_type), POINTER                      :: force_env
     528              :       TYPE(section_vals_type), POINTER                   :: root_section
     529              :       INTEGER, INTENT(IN)                                :: its
     530              :       REAL(KIND=dp), INTENT(IN)                          :: opt_energy
     531              :       INTEGER, INTENT(IN)                                :: output_unit
     532              :       REAL(KIND=dp)                                      :: eold, emin
     533              :       CHARACTER(LEN=5)                                   :: wildcard
     534              :       TYPE(gopt_param_type), POINTER                     :: gopt_param
     535              :       INTEGER, INTENT(IN), OPTIONAL                      :: ndf
     536              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: dx
     537              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: xi
     538              :       LOGICAL, OPTIONAL                                  :: conv
     539              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: pred, rat, step, rad
     540              :       REAL(KIND=dp)                                      :: used_time
     541              : 
     542              :       CHARACTER(LEN=default_string_length)               :: energy_unit, stress_unit
     543              :       INTEGER(KIND=int_8)                                :: max_memory
     544              :       REAL(KIND=dp)                                      :: pres_diff, pres_diff_constr, pres_int, &
     545              :                                                             pres_tol
     546              : 
     547         9170 :       CALL get_reporting_metadata(gopt_env, force_env, max_memory, energy_unit, stress_unit)
     548              : 
     549        14250 :       SELECT CASE (gopt_env%type_id)
     550              :       CASE (default_ts_method_id, default_minimization_method_id)
     551              :          ! Geometry Optimization (Minimization and Transition State Search)
     552         5080 :          IF (.NOT. gopt_env%dimer_rotation) THEN
     553              :             CALL geo_opt_io(force_env=force_env, root_section=root_section, &
     554         4358 :                             motion_section=gopt_env%motion_section, its=its, opt_energy=opt_energy)
     555              :             CALL write_cycle_infos(output_unit, &
     556              :                                    it=its, &
     557              :                                    etot=opt_energy, &
     558              :                                    ediff=(opt_energy - eold), &
     559              :                                    pred=pred, &
     560              :                                    rat=rat, &
     561              :                                    step=step, &
     562              :                                    rad=rad, &
     563              :                                    emin=emin, &
     564              :                                    wildcard=wildcard, &
     565              :                                    used_time=used_time, &
     566              :                                    max_memory=max_memory, &
     567              :                                    energy_unit=energy_unit, &
     568         4358 :                                    stress_unit=stress_unit)
     569              :             ! Possibly check convergence
     570         4358 :             IF (PRESENT(conv)) THEN
     571         4358 :                CPASSERT(PRESENT(ndf))
     572         4358 :                CPASSERT(PRESENT(dx))
     573         4358 :                CPASSERT(PRESENT(xi))
     574         4358 :                CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit)
     575              :             END IF
     576              :          ELSE
     577          722 :             CALL update_dimer_vec(gopt_env%dimer_env, gopt_env%motion_section)
     578          722 :             CALL write_restart(force_env=force_env, root_section=root_section)
     579              :             CALL write_rot_cycle_infos(output_unit, its, opt_energy, opt_energy - eold, emin, gopt_env%dimer_env, &
     580          722 :                                        wildcard=wildcard, used_time=used_time, max_memory=max_memory)
     581              :             ! Possibly check convergence
     582          722 :             IF (PRESENT(conv)) THEN
     583          722 :                CPASSERT(ASSOCIATED(gopt_env%dimer_env))
     584          722 :                CALL check_rot_conv(gopt_env%dimer_env, output_unit, conv)
     585              :             END IF
     586              :          END IF
     587              :       CASE (default_cell_method_id)
     588              :          ! Cell Optimization
     589         3940 :          pres_diff = gopt_env%cell_env%pres_int - gopt_env%cell_env%pres_ext
     590         3940 :          pres_int = gopt_env%cell_env%pres_int
     591         3940 :          pres_tol = gopt_env%cell_env%pres_tol
     592              :          CALL geo_opt_io(force_env=force_env, root_section=root_section, &
     593         3940 :                          motion_section=gopt_env%motion_section, its=its, opt_energy=opt_energy)
     594              :          CALL write_cycle_infos(output_unit, &
     595              :                                 it=its, &
     596              :                                 etot=opt_energy, &
     597              :                                 ediff=(opt_energy - eold), &
     598              :                                 pred=pred, &
     599              :                                 rat=rat, &
     600              :                                 step=step, &
     601              :                                 rad=rad, &
     602              :                                 emin=emin, &
     603              :                                 pres_int=pres_int, &
     604              :                                 wildcard=wildcard, &
     605              :                                 used_time=used_time, &
     606              :                                 max_memory=max_memory, &
     607              :                                 energy_unit=energy_unit, &
     608         3940 :                                 stress_unit=stress_unit)
     609              :          ! Possibly check convergence
     610         3940 :          IF (PRESENT(conv)) THEN
     611         3940 :             CPASSERT(PRESENT(ndf))
     612         3940 :             CPASSERT(PRESENT(dx))
     613         3940 :             CPASSERT(PRESENT(xi))
     614         3940 :             IF (gopt_env%cell_env%constraint_id == fix_none) THEN
     615              :                CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit, &
     616         3922 :                                   pres_diff, pres_tol)
     617              :             ELSE
     618           18 :                pres_diff_constr = gopt_env%cell_env%pres_constr - gopt_env%cell_env%pres_ext
     619              :                CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit, &
     620           18 :                                   pres_diff, pres_tol, pres_diff_constr)
     621              :             END IF
     622              :          END IF
     623              :       CASE (default_shellcore_method_id)
     624              :          CALL write_cycle_infos(output_unit, &
     625              :                                 it=its, &
     626              :                                 etot=opt_energy, &
     627              :                                 ediff=(opt_energy - eold), &
     628              :                                 pred=pred, &
     629              :                                 rat=rat, &
     630              :                                 step=step, &
     631              :                                 rad=rad, &
     632              :                                 emin=emin, &
     633              :                                 wildcard=wildcard, &
     634              :                                 used_time=used_time, &
     635              :                                 max_memory=max_memory, &
     636              :                                 energy_unit=energy_unit, &
     637          150 :                                 stress_unit=stress_unit)
     638              :          ! Possibly check convergence
     639         9320 :          IF (PRESENT(conv)) THEN
     640          150 :             CPASSERT(PRESENT(ndf))
     641          150 :             CPASSERT(PRESENT(dx))
     642          150 :             CPASSERT(PRESENT(xi))
     643          150 :             CALL check_converg(ndf, dx, xi, output_unit, conv, gopt_param, max_memory, stress_unit)
     644              :          END IF
     645              :       END SELECT
     646              : 
     647         9170 :    END SUBROUTINE gopt_f_io
     648              : 
     649              : ! **************************************************************************************************
     650              : !> \brief Handles the Output at the end of an optimization run
     651              : !> \param gopt_env ...
     652              : !> \param force_env ...
     653              : !> \param x0 ...
     654              : !> \param conv ...
     655              : !> \param its ...
     656              : !> \param root_section ...
     657              : !> \param para_env ...
     658              : !> \param master ...
     659              : !> \param output_unit ...
     660              : !> \author Teodoro Laino [tlaino] - University of Zurich - 03.2008
     661              : ! **************************************************************************************************
     662         1253 :    RECURSIVE SUBROUTINE gopt_f_io_finalize(gopt_env, force_env, x0, conv, its, root_section, &
     663              :                                            para_env, master, output_unit)
     664              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
     665              :       TYPE(force_env_type), POINTER                      :: force_env
     666              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x0
     667              :       LOGICAL                                            :: conv
     668              :       INTEGER                                            :: its
     669              :       TYPE(section_vals_type), POINTER                   :: root_section
     670              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     671              :       INTEGER, INTENT(IN)                                :: master, output_unit
     672              : 
     673         1253 :       IF (gopt_env%eval_opt_geo) THEN
     674         1233 :          IF (.NOT. gopt_env%dimer_rotation) THEN
     675              :             CALL write_final_info(output_unit, conv, its, gopt_env, x0, master, &
     676         1105 :                                   para_env, force_env, gopt_env%motion_section, root_section)
     677              :          ELSE
     678          128 :             CALL update_dimer_vec(gopt_env%dimer_env, gopt_env%motion_section)
     679          128 :             CALL write_restart(force_env=force_env, root_section=root_section)
     680              :          END IF
     681              :       END IF
     682              : 
     683         1253 :    END SUBROUTINE gopt_f_io_finalize
     684              : 
     685              : ! **************************************************************************************************
     686              : !> \brief ...
     687              : !> \param output_unit ...
     688              : !> \param it ...
     689              : !> \param etot ...
     690              : !> \param ediff ...
     691              : !> \param pred ...
     692              : !> \param rat ...
     693              : !> \param step ...
     694              : !> \param rad ...
     695              : !> \param emin ...
     696              : !> \param pres_int ...
     697              : !> \param wildcard ...
     698              : !> \param used_time ...
     699              : !> \param max_memory ...
     700              : !> \param energy_unit ...
     701              : !> \param stress_unit ...
     702              : ! **************************************************************************************************
     703         9483 :    SUBROUTINE write_cycle_infos(output_unit, it, etot, ediff, pred, rat, step, rad, emin, &
     704              :                                 pres_int, wildcard, used_time, max_memory, energy_unit, stress_unit)
     705              : 
     706              :       INTEGER, INTENT(IN)                                :: output_unit, it
     707              :       REAL(KIND=dp), INTENT(IN)                          :: etot
     708              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: ediff, pred, rat, step, rad, emin, &
     709              :                                                             pres_int
     710              :       CHARACTER(LEN=5), INTENT(IN)                       :: wildcard
     711              :       REAL(KIND=dp), INTENT(IN)                          :: used_time
     712              :       INTEGER(KIND=int_8), INTENT(IN)                    :: max_memory
     713              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: energy_unit, stress_unit
     714              : 
     715              :       CHARACTER(LEN=5)                                   :: tag
     716              : 
     717         9483 :       IF (output_unit > 0) THEN
     718         4925 :          tag = "OPT| "
     719         4925 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") tag//REPEAT("*", 74)
     720              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,I25)") &
     721         4925 :             tag//"Step number", it
     722              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,A25)") &
     723         4925 :             tag//"Optimization method", wildcard
     724              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     725         4925 :             tag//"Total energy ["//TRIM(ADJUSTL(energy_unit))//"]", &
     726         9850 :             cp_unit_from_cp2k(etot, TRIM(energy_unit))
     727         4925 :          IF (PRESENT(pres_int)) THEN
     728              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     729         2056 :                tag//"Internal pressure ["//TRIM(ADJUSTL(stress_unit))//"]", &
     730         4112 :                cp_unit_from_cp2k(pres_int, TRIM(stress_unit))
     731              :          END IF
     732         4925 :          IF (PRESENT(ediff)) THEN
     733              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     734         4384 :                tag//"Effective energy change ["//TRIM(ADJUSTL(energy_unit))//"]", &
     735         8768 :                cp_unit_from_cp2k(ediff, TRIM(energy_unit))
     736              :          END IF
     737         4925 :          IF (PRESENT(pred)) THEN
     738              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     739         2075 :                tag//"Predicted energy change ["//TRIM(ADJUSTL(energy_unit))//"]", &
     740         4150 :                cp_unit_from_cp2k(pred, TRIM(energy_unit))
     741              :          END IF
     742         4925 :          IF (PRESENT(rat)) THEN
     743              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     744         2331 :                tag//"Scaling factor", rat
     745              :          END IF
     746         4925 :          IF (PRESENT(step)) THEN
     747              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     748         2331 :                tag//"Step size", step
     749              :          END IF
     750         4925 :          IF (PRESENT(rad)) THEN
     751              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     752         2331 :                tag//"Trust radius", rad
     753              :          END IF
     754         4925 :          IF (PRESENT(emin)) THEN
     755         4384 :             IF (etot < emin) THEN
     756              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     757         3977 :                   tag//"Decrease in energy", " YES"
     758              :             ELSE
     759              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     760          407 :                   tag//"Decrease in energy", "  NO"
     761              :             END IF
     762              :          END IF
     763              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.3)") &
     764         4925 :             tag//"Used time [s]", used_time
     765         4925 :          IF (it == 0) THEN
     766          535 :             WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     767          535 :             IF (max_memory /= 0) THEN
     768              :                WRITE (UNIT=output_unit, FMT="(T2,A,T60,1X,I20)") &
     769          535 :                   tag//"Estimated peak process memory [MiB]", &
     770         1070 :                   (max_memory + (1024*1024) - 1)/(1024*1024)
     771              :             END IF
     772              :          END IF
     773              :       END IF
     774              : 
     775         9483 :    END SUBROUTINE write_cycle_infos
     776              : 
     777              : ! **************************************************************************************************
     778              : !> \brief ...
     779              : !> \param output_unit ...
     780              : !> \param it ...
     781              : !> \param etot ...
     782              : !> \param ediff ...
     783              : !> \param emin ...
     784              : !> \param dimer_env ...
     785              : !> \param used_time ...
     786              : !> \param wildcard ...
     787              : !> \param max_memory ...
     788              : !> \date  01.2008
     789              : !> \author Luca Bellucci and Teodoro Laino - created [tlaino]
     790              : ! **************************************************************************************************
     791          850 :    SUBROUTINE write_rot_cycle_infos(output_unit, it, etot, ediff, emin, dimer_env, used_time, &
     792              :                                     wildcard, max_memory)
     793              : 
     794              :       INTEGER, INTENT(IN)                                :: output_unit, it
     795              :       REAL(KIND=dp), INTENT(IN)                          :: etot
     796              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: ediff, emin
     797              :       TYPE(dimer_env_type), POINTER                      :: dimer_env
     798              :       REAL(KIND=dp), INTENT(IN)                          :: used_time
     799              :       CHARACTER(LEN=5), INTENT(IN)                       :: wildcard
     800              :       INTEGER(KIND=int_8), INTENT(IN)                    :: max_memory
     801              : 
     802              :       CHARACTER(LEN=5)                                   :: tag
     803              : 
     804          850 :       IF (output_unit > 0) THEN
     805          425 :          tag = "OPT| "
     806          425 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") tag//REPEAT("*", 74)
     807              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,I25)") &
     808          425 :             tag//"Rotational step number", it
     809              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,A25)") &
     810          425 :             tag//"Optimization method", wildcard
     811              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     812          425 :             tag//"Local curvature", dimer_env%rot%curvature, &
     813          850 :             tag//"Total rotational force", etot
     814          425 :          IF (PRESENT(ediff)) THEN
     815              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     816          361 :                tag//"Rotational force change", ediff
     817              :          END IF
     818          425 :          IF (PRESENT(emin)) THEN
     819          361 :             IF (etot < emin) THEN
     820              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     821          155 :                   tag//"Decrease in rotational force", " YES"
     822              :             ELSE
     823              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     824          206 :                   tag//"Decrease in rotational force", "  NO"
     825              :             END IF
     826              :          END IF
     827              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.3)") &
     828          425 :             tag//"Used time [s]", used_time
     829          425 :          IF (it == 0) THEN
     830           64 :             WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     831           64 :             IF (max_memory /= 0) THEN
     832              :                WRITE (UNIT=output_unit, FMT="(T2,A,T60,1X,I20)") &
     833           64 :                   tag//"Estimated peak process memory [MiB]", &
     834          128 :                   (max_memory + (1024*1024) - 1)/(1024*1024)
     835              :             END IF
     836              :          END IF
     837              :       END IF
     838              : 
     839          850 :    END SUBROUTINE write_rot_cycle_infos
     840              : 
     841              : ! **************************************************************************************************
     842              : !> \brief ...
     843              : !> \param ndf ...
     844              : !> \param dr ...
     845              : !> \param g ...
     846              : !> \param output_unit ...
     847              : !> \param conv ...
     848              : !> \param gopt_param ...
     849              : !> \param max_memory ...
     850              : !> \param stress_unit ...
     851              : !> \param pres_diff ...
     852              : !> \param pres_tol ...
     853              : !> \param pres_diff_constr ...
     854              : ! **************************************************************************************************
     855         8448 :    SUBROUTINE check_converg(ndf, dr, g, output_unit, conv, gopt_param, max_memory, stress_unit, &
     856              :                             pres_diff, pres_tol, pres_diff_constr)
     857              : 
     858              :       INTEGER, INTENT(IN)                                :: ndf
     859              :       REAL(KIND=dp), INTENT(IN)                          :: dr(ndf), g(ndf)
     860              :       INTEGER, INTENT(IN)                                :: output_unit
     861              :       LOGICAL, INTENT(OUT)                               :: conv
     862              :       TYPE(gopt_param_type), POINTER                     :: gopt_param
     863              :       INTEGER(KIND=int_8), INTENT(IN)                    :: max_memory
     864              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: stress_unit
     865              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: pres_diff, pres_tol, pres_diff_constr
     866              : 
     867              :       CHARACTER(LEN=5)                                   :: tag
     868              :       INTEGER                                            :: indf
     869              :       LOGICAL                                            :: conv_dx, conv_g, conv_p, conv_rdx, &
     870              :                                                             conv_rg
     871              :       REAL(KIND=dp)                                      :: dumm, dxcon, gcon, maxdum(4), rmsgcon, &
     872              :                                                             rmsxcon
     873              : 
     874         8448 :       dxcon = gopt_param%max_dr
     875         8448 :       gcon = gopt_param%max_force
     876         8448 :       rmsgcon = gopt_param%rms_force
     877         8448 :       rmsxcon = gopt_param%rms_dr
     878              : 
     879         8448 :       conv = .FALSE.
     880         8448 :       conv_dx = .TRUE.
     881         8448 :       conv_rdx = .TRUE.
     882         8448 :       conv_g = .TRUE.
     883         8448 :       conv_rg = .TRUE.
     884         8448 :       conv_p = .TRUE.
     885              : 
     886         8448 :       dumm = 0.0_dp
     887      2446284 :       DO indf = 1, ndf
     888      2437836 :          IF (indf == 1) maxdum(1) = ABS(dr(indf))
     889      2437836 :          dumm = dumm + dr(indf)**2
     890      2437836 :          IF (ABS(dr(indf)) > dxcon) conv_dx = .FALSE.
     891      2446284 :          IF (ABS(dr(indf)) > maxdum(1)) maxdum(1) = ABS(dr(indf))
     892              :       END DO
     893              :       ! SQRT(dumm/ndf) > rmsxcon
     894         8448 :       IF (dumm > (rmsxcon*rmsxcon*ndf)) conv_rdx = .FALSE.
     895         8448 :       maxdum(2) = SQRT(dumm/ndf)
     896              : 
     897         8448 :       dumm = 0.0_dp
     898      2446284 :       DO indf = 1, ndf
     899      2437836 :          IF (indf == 1) maxdum(3) = ABS(g(indf))
     900      2437836 :          dumm = dumm + g(indf)**2
     901      2437836 :          IF (ABS(g(indf)) > gcon) conv_g = .FALSE.
     902      2446284 :          IF (ABS(g(indf)) > maxdum(3)) maxdum(3) = ABS(g(indf))
     903              :       END DO
     904              :       ! SQRT(dumm/ndf) > rmsgcon
     905         8448 :       IF (dumm > (rmsgcon*rmsgcon*ndf)) conv_rg = .FALSE.
     906         8448 :       maxdum(4) = SQRT(dumm/ndf)
     907              : 
     908         8448 :       IF (PRESENT(pres_diff_constr) .AND. PRESENT(pres_tol)) THEN
     909           18 :          conv_p = ABS(pres_diff_constr) < ABS(pres_tol)
     910         8430 :       ELSE IF (PRESENT(pres_diff) .AND. PRESENT(pres_tol)) THEN
     911         3922 :          conv_p = ABS(pres_diff) < ABS(pres_tol)
     912              :       END IF
     913              : 
     914         8448 :       IF (output_unit > 0) THEN
     915              : 
     916         4384 :          tag = "OPT| "
     917              : 
     918         4384 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     919              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     920         4384 :             tag//"Maximum step size", maxdum(1), &
     921         8768 :             tag//"Convergence limit for maximum step size", dxcon
     922         4384 :          IF (conv_dx) THEN
     923              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     924          604 :                tag//"Maximum step size is converged", " YES"
     925              :          ELSE
     926              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     927         3780 :                tag//"Maximum step size is converged", "  NO"
     928              :          END IF
     929              : 
     930         4384 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     931              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     932         4384 :             tag//"RMS step size", maxdum(2), &
     933         8768 :             tag//"Convergence limit for RMS step size", rmsxcon
     934         4384 :          IF (conv_rdx) THEN
     935              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     936          855 :                tag//"RMS step size is converged", " YES"
     937              :          ELSE
     938              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     939         3529 :                tag//"RMS step size is converged", "  NO"
     940              :          END IF
     941              : 
     942         4384 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     943              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     944         4384 :             tag//"Maximum gradient", maxdum(3), &
     945         8768 :             tag//"Convergence limit for maximum gradient", gcon
     946         4384 :          IF (conv_g) THEN
     947              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     948          661 :                tag//"Maximum gradient is converged", " YES"
     949              :          ELSE
     950              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     951         3723 :                tag//"Maximum gradient is converged", "  NO"
     952              :          END IF
     953              : 
     954         4384 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     955              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     956         4384 :             tag//"RMS gradient", maxdum(4), &
     957         8768 :             tag//"Convergence limit for RMS gradient", rmsgcon
     958         4384 :          IF (conv_rg) THEN
     959              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     960          904 :                tag//"RMS gradient is converged", " YES"
     961              :          ELSE
     962              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     963         3480 :                tag//"RMS gradient is converged", "  NO"
     964              :          END IF
     965              : 
     966         4384 :          IF (PRESENT(pres_diff) .AND. PRESENT(pres_tol)) THEN
     967         1970 :             WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
     968         1970 :             IF (PRESENT(pres_diff_constr)) THEN
     969              :                WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     970              :                   tag//"Pressure deviation without constraint ["// &
     971            9 :                   TRIM(ADJUSTL(stress_unit))//"]", &
     972           18 :                   cp_unit_from_cp2k(pres_diff, TRIM(stress_unit))
     973              :                WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     974              :                   tag//"Pressure deviation with constraint ["// &
     975            9 :                   TRIM(ADJUSTL(stress_unit))//"]", &
     976           18 :                   cp_unit_from_cp2k(pres_diff_constr, TRIM(stress_unit))
     977              :             ELSE
     978              :                WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     979         1961 :                   tag//"Pressure deviation ["//TRIM(ADJUSTL(stress_unit))//"]", &
     980         3922 :                   cp_unit_from_cp2k(pres_diff, TRIM(stress_unit))
     981              :             END IF
     982              :             WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
     983         1970 :                tag//"Pressure tolerance ["//TRIM(ADJUSTL(stress_unit))//"]", &
     984         3940 :                cp_unit_from_cp2k(pres_tol, TRIM(stress_unit))
     985         1970 :             IF (conv_p) THEN
     986              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     987          299 :                   tag//"Pressure is converged", " YES"
     988              :             ELSE
     989              :                WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
     990         1671 :                   tag//"Pressure is converged", "  NO"
     991              :             END IF
     992              :          END IF
     993              : 
     994         4384 :          WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
     995              : 
     996         4384 :          IF (max_memory /= 0) THEN
     997              :             WRITE (UNIT=output_unit, FMT="(T2,A,T60,1X,I20)") &
     998         4384 :                tag//"Estimated peak process memory after this step [MiB]", &
     999         8768 :                (max_memory + (1024*1024) - 1)/(1024*1024)
    1000              :          END IF
    1001              : 
    1002              :       END IF
    1003              : 
    1004         8448 :       IF (conv_dx .AND. conv_rdx .AND. conv_g .AND. conv_rg .AND. conv_p) conv = .TRUE.
    1005              : 
    1006         8448 :       IF ((conv) .AND. (output_unit > 0)) THEN
    1007          214 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
    1008              :          WRITE (UNIT=output_unit, FMT="(T2,A,T25,A,T78,A)") &
    1009          214 :             "***", "GEOMETRY OPTIMIZATION COMPLETED", "***"
    1010          214 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
    1011              :       END IF
    1012              : 
    1013         8448 :    END SUBROUTINE check_converg
    1014              : 
    1015              : ! **************************************************************************************************
    1016              : !> \brief ...
    1017              : !> \param dimer_env ...
    1018              : !> \param output_unit ...
    1019              : !> \param conv ...
    1020              : !> \date  01.2008
    1021              : !> \author Luca Bellucci and Teodoro Laino - created [tlaino]
    1022              : ! **************************************************************************************************
    1023          722 :    SUBROUTINE check_rot_conv(dimer_env, output_unit, conv)
    1024              : 
    1025              :       TYPE(dimer_env_type), POINTER                      :: dimer_env
    1026              :       INTEGER, INTENT(IN)                                :: output_unit
    1027              :       LOGICAL, INTENT(OUT)                               :: conv
    1028              : 
    1029              :       CHARACTER(LEN=5)                                   :: tag
    1030              : 
    1031          722 :       conv = (ABS(dimer_env%rot%angle2) < dimer_env%rot%angle_tol)
    1032              : 
    1033          722 :       IF (output_unit > 0) THEN
    1034          361 :          tag = "OPT| "
    1035          361 :          WRITE (UNIT=output_unit, FMT="(T2,A)") TRIM(tag)
    1036              :          WRITE (UNIT=output_unit, FMT="(T2,A,T55,1X,F25.10)") &
    1037          361 :             tag//"Predicted angle step size", dimer_env%rot%angle1, &
    1038          361 :             tag//"Effective angle step size", dimer_env%rot%angle2, &
    1039          722 :             tag//"Convergence limit for angle step size", dimer_env%rot%angle_tol
    1040          361 :          IF (conv) THEN
    1041              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
    1042           59 :                tag//"Angle step size is converged", " YES"
    1043              :          ELSE
    1044              :             WRITE (UNIT=output_unit, FMT="(T2,A,T77,A4)") &
    1045          302 :                tag//"Angle step size is converged", "  NO"
    1046              :          END IF
    1047          361 :          WRITE (UNIT=output_unit, FMT="(T2,A)") tag//REPEAT("*", 74)
    1048              :       END IF
    1049              : 
    1050          722 :       IF ((conv) .AND. (output_unit > 0)) THEN
    1051           59 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
    1052              :          WRITE (UNIT=output_unit, FMT="(T2,A,T25,A,T78,A)") &
    1053           59 :             "***", "ROTATION OPTIMIZATION COMPLETED", "***"
    1054           59 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
    1055              :       END IF
    1056              : 
    1057          722 :    END SUBROUTINE check_rot_conv
    1058              : 
    1059              : ! **************************************************************************************************
    1060              : !> \brief ...
    1061              : !> \param output_unit ...
    1062              : !> \param conv ...
    1063              : !> \param it ...
    1064              : !> \param gopt_env ...
    1065              : !> \param x0 ...
    1066              : !> \param master ...
    1067              : !> \param para_env ...
    1068              : !> \param force_env ...
    1069              : !> \param motion_section ...
    1070              : !> \param root_section ...
    1071              : !> \date  11.2007
    1072              : !> \author Teodoro Laino [tlaino] - University of Zurich
    1073              : ! **************************************************************************************************
    1074         1105 :    RECURSIVE SUBROUTINE write_final_info(output_unit, conv, it, gopt_env, x0, master, para_env, force_env, &
    1075              :                                          motion_section, root_section)
    1076              :       INTEGER, INTENT(IN)                                :: output_unit
    1077              :       LOGICAL, INTENT(IN)                                :: conv
    1078              :       INTEGER, INTENT(INOUT)                             :: it
    1079              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
    1080              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x0
    1081              :       INTEGER, INTENT(IN)                                :: master
    1082              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1083              :       TYPE(force_env_type), POINTER                      :: force_env
    1084              :       TYPE(section_vals_type), POINTER                   :: motion_section, root_section
    1085              : 
    1086              :       CHARACTER(LEN=4)                                   :: constraint_label
    1087              :       LOGICAL                                            :: keep_angles, keep_symmetry, keep_volume
    1088              :       REAL(KIND=dp)                                      :: etot
    1089              :       TYPE(cell_type), POINTER                           :: cell
    1090              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1091              :       TYPE(particle_list_type), POINTER                  :: particles
    1092         1105 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1093              : 
    1094         1105 :       CALL force_env_get(force_env, cell=cell, subsys=subsys)
    1095         1105 :       CALL cp_subsys_get(subsys=subsys, particles=particles)
    1096         1105 :       particle_set => particles%els
    1097              : 
    1098              :       ! Passing gopt_f_type pointer gopt_env to particle_methods where
    1099              :       ! write_final_structure is defined causes a circular dependency, so it
    1100              :       ! is necessary to get some flags by preprocessing...
    1101         1105 :       keep_angles = .TRUE.
    1102         1105 :       keep_symmetry = .TRUE.
    1103         1105 :       keep_volume = .TRUE.
    1104         1105 :       constraint_label = "NONE"
    1105         1105 :       IF (gopt_env%type_id == default_cell_method_id) THEN
    1106          216 :          keep_angles = gopt_env%cell_env%keep_angles
    1107          216 :          keep_symmetry = gopt_env%cell_env%keep_symmetry
    1108          216 :          keep_volume = gopt_env%cell_env%keep_volume
    1109          216 :          SELECT CASE (gopt_env%cell_env%constraint_id)
    1110              :          CASE (fix_x)
    1111            0 :             constraint_label = "   X"
    1112              :          CASE (fix_y)
    1113            0 :             constraint_label = "   Y"
    1114              :          CASE (fix_z)
    1115            2 :             constraint_label = "   Z"
    1116              :          CASE (fix_xy)
    1117            2 :             constraint_label = "  XY"
    1118              :          CASE (fix_xz)
    1119            0 :             constraint_label = "  XZ"
    1120              :          CASE (fix_yz)
    1121            0 :             constraint_label = "  YZ"
    1122              :          CASE (fix_none)
    1123          216 :             constraint_label = "NONE"
    1124              :          END SELECT
    1125              :       END IF
    1126              :       CALL write_final_structure(particle_set, cell, motion_section, conv, &
    1127              :                                  keep_angles, keep_symmetry, keep_volume, &
    1128         1105 :                                  gopt_env%label, constraint_label)
    1129              : 
    1130         1105 :       IF (conv) THEN
    1131          364 :          it = it + 1
    1132          364 :          CALL write_structure_data(particle_set, cell, motion_section)
    1133          364 :          CALL write_restart(force_env=force_env, root_section=root_section)
    1134              : 
    1135          364 :          IF (output_unit > 0) THEN
    1136          205 :             WRITE (UNIT=output_unit, FMT="(/,T20,' Reevaluating energy at the minimum')")
    1137              :          END IF
    1138              : 
    1139              :          CALL cp_eval_at(gopt_env, x0, f=etot, master=master, final_evaluation=.TRUE., &
    1140          364 :                          para_env=para_env)
    1141          364 :          CALL write_geo_traj(force_env, root_section, it, etot)
    1142              :       END IF
    1143              : 
    1144         1105 :    END SUBROUTINE write_final_info
    1145              : 
    1146              : ! **************************************************************************************************
    1147              : !> \brief  Specific driver for dumping trajectory during a GEO_OPT
    1148              : !> \param force_env ...
    1149              : !> \param root_section ...
    1150              : !> \param it ...
    1151              : !> \param etot ...
    1152              : !> \date   11.2007
    1153              : !> \par    History
    1154              : !>         09.2010: Output of core and shell positions and forces (MK)
    1155              : !> \author Teodoro Laino [tlaino] - University of Zurich
    1156              : ! **************************************************************************************************
    1157        17324 :    SUBROUTINE write_geo_traj(force_env, root_section, it, etot)
    1158              : 
    1159              :       TYPE(force_env_type), POINTER                      :: force_env
    1160              :       TYPE(section_vals_type), POINTER                   :: root_section
    1161              :       INTEGER, INTENT(IN)                                :: it
    1162              :       REAL(KIND=dp), INTENT(IN)                          :: etot
    1163              : 
    1164              :       LOGICAL                                            :: shell_adiabatic, shell_present
    1165              :       TYPE(atomic_kind_list_type), POINTER               :: atomic_kinds
    1166         8662 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1167              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1168              :       TYPE(particle_list_type), POINTER                  :: core_particles, shell_particles
    1169              : 
    1170         8662 :       NULLIFY (atomic_kinds)
    1171         8662 :       NULLIFY (atomic_kind_set)
    1172         8662 :       NULLIFY (core_particles)
    1173         8662 :       NULLIFY (shell_particles)
    1174         8662 :       NULLIFY (subsys)
    1175              : 
    1176         8662 :       CALL write_trajectory(force_env, root_section, it, 0.0_dp, 0.0_dp, etot)
    1177              :       ! Print Force
    1178         8662 :       CALL write_trajectory(force_env, root_section, it, 0.0_dp, 0.0_dp, etot, "FORCES", middle_name="frc")
    1179         8662 :       CALL force_env_get(force_env, subsys=subsys)
    1180         8662 :       CALL cp_subsys_get(subsys, atomic_kinds=atomic_kinds)
    1181         8662 :       atomic_kind_set => atomic_kinds%els
    1182              :       CALL get_atomic_kind_set(atomic_kind_set, &
    1183              :                                shell_present=shell_present, &
    1184         8662 :                                shell_adiabatic=shell_adiabatic)
    1185         8662 :       IF (shell_present) THEN
    1186              :          CALL cp_subsys_get(subsys, &
    1187              :                             core_particles=core_particles, &
    1188         3414 :                             shell_particles=shell_particles)
    1189              :          CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
    1190              :                                etot=etot, pk_name="SHELL_TRAJECTORY", middle_name="shpos", &
    1191         3414 :                                particles=shell_particles)
    1192         3414 :          IF (shell_adiabatic) THEN
    1193              :             CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
    1194              :                                   etot=etot, pk_name="SHELL_FORCES", middle_name="shfrc", &
    1195         3414 :                                   particles=shell_particles)
    1196              :             CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
    1197              :                                   etot=etot, pk_name="CORE_TRAJECTORY", middle_name="copos", &
    1198         3414 :                                   particles=core_particles)
    1199              :             CALL write_trajectory(force_env, root_section, it=it, time=0.0_dp, dtime=0.0_dp, &
    1200              :                                   etot=etot, pk_name="CORE_FORCES", middle_name="cofrc", &
    1201         3414 :                                   particles=core_particles)
    1202              :          END IF
    1203              :       END IF
    1204              : 
    1205         8662 :    END SUBROUTINE write_geo_traj
    1206              : 
    1207              : ! **************************************************************************************************
    1208              : !> \brief ...
    1209              : !> \param gopt_env ...
    1210              : !> \param output_unit ...
    1211              : !> \param label ...
    1212              : !> \date  01.2008
    1213              : !> \author Teodoro Laino [tlaino] - University of Zurich
    1214              : ! **************************************************************************************************
    1215         1253 :    SUBROUTINE print_geo_opt_header(gopt_env, output_unit, label)
    1216              : 
    1217              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
    1218              :       INTEGER, INTENT(IN)                                :: output_unit
    1219              :       CHARACTER(LEN=*), INTENT(IN)                       :: label
    1220              : 
    1221              :       CHARACTER(LEN=default_string_length)               :: my_format, my_label
    1222              :       INTEGER                                            :: ix
    1223              : 
    1224         1253 :       IF (output_unit > 0) THEN
    1225          650 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
    1226          650 :          IF (gopt_env%dimer_rotation) THEN
    1227           64 :             my_label = "OPTIMIZING DIMER ROTATION"
    1228              :          ELSE
    1229          586 :             my_label = "STARTING "//gopt_env%tag(1:8)//" OPTIMIZATION"
    1230              :          END IF
    1231              : 
    1232          650 :          ix = (80 - 7 - LEN_TRIM(my_label))/2
    1233          650 :          ix = ix + 5
    1234          650 :          my_format = "(T2,A,T"//cp_to_string(ix)//",A,T78,A)"
    1235          650 :          WRITE (UNIT=output_unit, FMT=TRIM(my_format)) "***", TRIM(my_label), "***"
    1236              : 
    1237          650 :          ix = (80 - 7 - LEN_TRIM(label))/2
    1238          650 :          ix = ix + 5
    1239          650 :          my_format = "(T2,A,T"//cp_to_string(ix)//",A,T78,A)"
    1240          650 :          WRITE (UNIT=output_unit, FMT=TRIM(my_format)) "***", TRIM(label), "***"
    1241              : 
    1242          650 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
    1243          650 :          CALL m_flush(output_unit)
    1244              :       END IF
    1245         1253 :    END SUBROUTINE print_geo_opt_header
    1246              : 
    1247              : ! **************************************************************************************************
    1248              : !> \brief ...
    1249              : !> \param gopt_env ...
    1250              : !> \param output_unit ...
    1251              : !> \date  01.2008
    1252              : !> \author Teodoro Laino [tlaino] - University of Zurich
    1253              : ! **************************************************************************************************
    1254          739 :    SUBROUTINE print_geo_opt_nc(gopt_env, output_unit)
    1255              : 
    1256              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
    1257              :       INTEGER, INTENT(IN)                                :: output_unit
    1258              : 
    1259          739 :       IF (output_unit > 0) THEN
    1260              :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
    1261          370 :             "*** MAXIMUM NUMBER OF OPTIMIZATION STEPS REACHED ***"
    1262          370 :          IF (.NOT. gopt_env%dimer_rotation) THEN
    1263              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1264          365 :                "***        EXITING GEOMETRY OPTIMIZATION         ***"
    1265              :          ELSE
    1266              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1267            5 :                "***        EXITING ROTATION OPTIMIZATION         ***"
    1268              :          END IF
    1269          370 :          CALL m_flush(output_unit)
    1270              :       END IF
    1271              : 
    1272          739 :    END SUBROUTINE print_geo_opt_nc
    1273              : 
    1274              : ! **************************************************************************************************
    1275              : !> \brief   Prints information during GEO_OPT common to all optimizers
    1276              : !> \param force_env ...
    1277              : !> \param root_section ...
    1278              : !> \param motion_section ...
    1279              : !> \param its ...
    1280              : !> \param opt_energy ...
    1281              : !> \date    02.2008
    1282              : !> \author  Teodoro Laino [tlaino] - University of Zurich
    1283              : !> \version 1.0
    1284              : ! **************************************************************************************************
    1285         8298 :    SUBROUTINE geo_opt_io(force_env, root_section, motion_section, its, opt_energy)
    1286              : 
    1287              :       TYPE(force_env_type), POINTER                      :: force_env
    1288              :       TYPE(section_vals_type), POINTER                   :: root_section, motion_section
    1289              :       INTEGER, INTENT(IN)                                :: its
    1290              :       REAL(KIND=dp), INTENT(IN)                          :: opt_energy
    1291              : 
    1292              :       TYPE(atomic_kind_list_type), POINTER               :: atomic_kinds
    1293         8298 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1294              :       TYPE(cell_type), POINTER                           :: cell
    1295              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1296              :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1297              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1298              :       TYPE(particle_list_type), POINTER                  :: particles
    1299         8298 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1300              :       TYPE(virial_type), POINTER                         :: virial
    1301              : 
    1302         8298 :       NULLIFY (para_env, atomic_kind_set, subsys, particle_set, &
    1303         8298 :                local_particles, atomic_kinds, particles)
    1304              : 
    1305              :       ! Write Restart File
    1306         8298 :       CALL write_restart(force_env=force_env, root_section=root_section)
    1307              : 
    1308              :       ! Write Trajectory
    1309         8298 :       CALL write_geo_traj(force_env, root_section, its, opt_energy)
    1310              : 
    1311              :       ! Write the stress Tensor
    1312              :       CALL force_env_get(force_env, cell=cell, para_env=para_env, &
    1313         8298 :                          subsys=subsys)
    1314              :       CALL cp_subsys_get(subsys=subsys, atomic_kinds=atomic_kinds, local_particles=local_particles, &
    1315         8298 :                          particles=particles, virial=virial)
    1316         8298 :       atomic_kind_set => atomic_kinds%els
    1317         8298 :       particle_set => particles%els
    1318              :       CALL virial_evaluate(atomic_kind_set, particle_set, local_particles, &
    1319         8298 :                            virial, para_env)
    1320         8298 :       CALL write_stress_tensor_to_file(virial, cell, motion_section, its, 0.0_dp)
    1321              : 
    1322              :       ! Write the cell
    1323         8298 :       CALL write_simulation_cell(cell, motion_section, its, 0.0_dp)
    1324              : 
    1325         8298 :    END SUBROUTINE geo_opt_io
    1326              : 
    1327              : ! **************************************************************************************************
    1328              : !> \brief   Apply coordinate transformations after cell (shape) change
    1329              : !> \param gopt_env ...
    1330              : !> \param cell ...
    1331              : !> \param x ...
    1332              : !> \param update_forces ...
    1333              : !> \date    05.11.2012 (revised version of unbiase_coordinates moved here, MK)
    1334              : !> \author  Matthias Krack
    1335              : !> \version 1.0
    1336              : ! **************************************************************************************************
    1337        13210 :    SUBROUTINE apply_cell_change(gopt_env, cell, x, update_forces)
    1338              : 
    1339              :       TYPE(gopt_f_type), POINTER                         :: gopt_env
    1340              :       TYPE(cell_type), POINTER                           :: cell
    1341              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: x
    1342              :       LOGICAL, INTENT(IN)                                :: update_forces
    1343              : 
    1344              :       INTEGER                                            :: i, iatom, idg, j, natom, nparticle, &
    1345              :                                                             shell_index
    1346              :       REAL(KIND=dp)                                      :: fc, fs, mass
    1347              :       REAL(KIND=dp), DIMENSION(3)                        :: s
    1348              :       TYPE(cell_type), POINTER                           :: cell_ref
    1349              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1350              :       TYPE(particle_list_type), POINTER                  :: core_particles, particles, &
    1351              :                                                             shell_particles
    1352              : 
    1353        13210 :       NULLIFY (cell_ref)
    1354        13210 :       NULLIFY (core_particles)
    1355        13210 :       NULLIFY (particles)
    1356        13210 :       NULLIFY (shell_particles)
    1357        13210 :       NULLIFY (subsys)
    1358              : 
    1359        13210 :       natom = force_env_get_natom(gopt_env%force_env)
    1360        13210 :       nparticle = force_env_get_nparticle(gopt_env%force_env)
    1361              :       CALL force_env_get(gopt_env%force_env, &
    1362        13210 :                          subsys=subsys)
    1363              :       CALL cp_subsys_get(subsys=subsys, &
    1364              :                          core_particles=core_particles, &
    1365              :                          particles=particles, &
    1366        13210 :                          shell_particles=shell_particles)
    1367              : 
    1368              :       ! Retrieve the reference cell
    1369        13210 :       CALL cell_create(cell_ref)
    1370        13210 :       CALL cell_copy(cell, cell_ref, tag="CELL_OPT_REF")
    1371              : 
    1372              :       ! Load the updated cell information
    1373        13210 :       idg = 3*nparticle
    1374        13210 :       CALL init_cell(cell_ref, hmat=gopt_env%h_ref)
    1375        13210 :       CPASSERT((SIZE(x) == idg + 6))
    1376              : 
    1377        13210 :       IF (update_forces) THEN
    1378              : 
    1379              :          ! Transform particle forces back to reference cell
    1380              :          idg = 1
    1381       295414 :          DO iatom = 1, natom
    1382       290238 :             CALL real_to_scaled(s, x(idg:idg + 2), cell)
    1383       290238 :             CALL scaled_to_real(x(idg:idg + 2), s, cell_ref)
    1384       295414 :             idg = idg + 3
    1385              :          END DO
    1386              : 
    1387              :       ELSE
    1388              : 
    1389              :          ! Update the six independent components in the canonical optimization frame.
    1390       104442 :          gopt_env%cell_env%opt_cell%hmat = 0.0_dp
    1391        32136 :          DO i = 1, 3
    1392        80340 :             DO j = 1, i
    1393        48204 :                idg = idg + 1
    1394        72306 :                gopt_env%cell_env%opt_cell%hmat(j, i) = x(idg)
    1395              :             END DO
    1396              :          END DO
    1397         8034 :          CALL init_cell(gopt_env%cell_env%opt_cell)
    1398         8034 :          IF (gopt_env%spgr%keep_space_group) THEN
    1399          798 :             CALL spgr_project_cell_metric(gopt_env%spgr, gopt_env%cell_env%opt_cell)
    1400              :             ! Keep the optimizer variables synchronized with the projected cell.
    1401          798 :             idg = 3*nparticle
    1402         3192 :             DO i = 1, 3
    1403         7980 :                DO j = 1, i
    1404         4788 :                   idg = idg + 1
    1405         7182 :                   x(idg) = gopt_env%cell_env%opt_cell%hmat(j, i)
    1406              :                END DO
    1407              :             END DO
    1408              :          END IF
    1409              : 
    1410              :          ! Reconstruct the physical cell in the fixed orientation of the input cell.
    1411              :          cell%hmat = MATMUL(gopt_env%cell_env%opt_to_input, &
    1412       626652 :                             gopt_env%cell_env%opt_cell%hmat)
    1413         8034 :          CALL init_cell(cell)
    1414         8034 :          CALL cp_subsys_set(subsys, cell=cell)
    1415              : 
    1416              :          ! Retrieve particle coordinates for the current cell
    1417         8034 :          idg = 1
    1418       541310 :          DO iatom = 1, natom
    1419       533276 :             CALL real_to_scaled(s, x(idg:idg + 2), cell_ref)
    1420       533276 :             shell_index = particles%els(iatom)%shell_index
    1421       533276 :             IF (shell_index == 0) THEN
    1422       213536 :                CALL scaled_to_real(particles%els(iatom)%r, s, cell)
    1423              :             ELSE
    1424       319740 :                CALL scaled_to_real(core_particles%els(shell_index)%r, s, cell)
    1425       319740 :                i = 3*(natom + shell_index - 1) + 1
    1426       319740 :                CALL real_to_scaled(s, x(i:i + 2), cell_ref)
    1427       319740 :                CALL scaled_to_real(shell_particles%els(shell_index)%r, s, cell)
    1428              :                ! Update atomic position due to core and shell motion
    1429       319740 :                mass = particles%els(iatom)%atomic_kind%mass
    1430       319740 :                fc = core_particles%els(shell_index)%atomic_kind%shell%mass_core/mass
    1431       319740 :                fs = shell_particles%els(shell_index)%atomic_kind%shell%mass_shell/mass
    1432              :                particles%els(iatom)%r(1:3) = fc*core_particles%els(shell_index)%r(1:3) + &
    1433      2557920 :                                              fs*shell_particles%els(shell_index)%r(1:3)
    1434              :             END IF
    1435       541310 :             idg = idg + 3
    1436              :          END DO
    1437              :       END IF
    1438              : 
    1439        13210 :       CALL cell_release(cell_ref)
    1440              : 
    1441        13210 :    END SUBROUTINE apply_cell_change
    1442              : 
    1443              : END MODULE gopt_f_methods
        

Generated by: LCOV version 2.0-1