LCOV - code coverage report
Current view: top level - src/motion - gopt_f_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:21ef868) Lines: 98.3 % 402 395
Test Date: 2026-08-14 07:04:57 Functions: 100.0 % 15 15

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

Generated by: LCOV version 2.0-1