LCOV - code coverage report
Current view: top level - src - ipi_driver.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:51fc4cd) Lines: 0.0 % 111 0
Test Date: 2026-02-04 06:28:27 Functions: 0.0 % 1 0

            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 Driver mode - To communicate with i-PI Python wrapper
      10              : !> \par History
      11              : !>      none
      12              : !> \author Michele Ceriotti 03.2012
      13              : ! **************************************************************************************************
      14              : MODULE ipi_driver
      15              :    USE ISO_C_BINDING, ONLY: C_CHAR, &
      16              :                             C_DOUBLE, &
      17              :                             C_INT, &
      18              :                             C_LOC, &
      19              :                             C_NULL_CHAR, &
      20              :                             C_PTR
      21              :    USE bibliography, ONLY: Ceriotti2014, &
      22              :                            Kapil2016, &
      23              :                            cite_reference
      24              :    USE cell_methods, ONLY: cell_create, &
      25              :                            init_cell
      26              :    USE cell_types, ONLY: cell_release, &
      27              :                          cell_type
      28              :    USE cp_external_control, ONLY: external_control
      29              :    USE cp_log_handling, ONLY: cp_logger_get_default_io_unit
      30              :    USE cp_subsys_types, ONLY: cp_subsys_get, &
      31              :                               cp_subsys_set, &
      32              :                               cp_subsys_type
      33              :    USE force_env_methods, ONLY: force_env_calc_energy_force
      34              :    USE force_env_types, ONLY: force_env_get, &
      35              :                               force_env_type
      36              :    USE global_types, ONLY: global_environment_type
      37              :    USE input_section_types, ONLY: section_vals_get_subs_vals, &
      38              :                                   section_vals_type, &
      39              :                                   section_vals_val_get
      40              :    USE kinds, ONLY: default_path_length, &
      41              :                     default_string_length, &
      42              :                     dp, &
      43              :                     int_4
      44              :    USE message_passing, ONLY: mp_para_env_type, &
      45              :                               mp_request_type, &
      46              :                               mp_testany
      47              : #ifndef __NO_SOCKETS
      48              :    USE sockets_interface, ONLY: writebuffer, &
      49              :                                 readbuffer, &
      50              :                                 open_connect_socket, &
      51              :                                 uwait
      52              : #endif
      53              :    USE virial_types, ONLY: virial_type
      54              : #include "./base/base_uses.f90"
      55              : 
      56              :    IMPLICIT NONE
      57              : 
      58              :    PRIVATE
      59              : 
      60              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ipi_driver'
      61              : 
      62              :    PUBLIC :: run_driver
      63              : 
      64              : CONTAINS
      65              : 
      66              : ! **************************************************************************************************
      67              : !> \brief ...
      68              : !> \param force_env ...
      69              : !> \param globenv ...
      70              : !> \par History
      71              : !>       12.2013 included in repository
      72              : !> \author Ceriotti
      73              : ! **************************************************************************************************
      74              : 
      75            0 :    SUBROUTINE run_driver(force_env, globenv)
      76              :       TYPE(force_env_type), POINTER            :: force_env
      77              :       TYPE(global_environment_type), POINTER   :: globenv
      78              : 
      79              :       CHARACTER(len=*), PARAMETER :: routineN = 'run_driver'
      80              : 
      81              : #ifdef __NO_SOCKETS
      82              :       INTEGER                                  :: handle
      83              :       CALL timeset(routineN, handle)
      84              :       CPABORT("CP2K was compiled with the __NO_SOCKETS option!")
      85              :       MARK_USED(globenv)
      86              :       MARK_USED(force_env)
      87              : #else
      88              :       INTEGER, PARAMETER                       :: MSGLEN = 12
      89              : 
      90              :       CHARACTER(len=default_path_length)       :: c_hostname, drv_hostname
      91              :       CHARACTER(LEN=default_string_length)     :: header
      92              :       INTEGER                                  :: drv_port, handle, i_drv_unix, &
      93              :                                                   idir, ii, inet, ip, iwait, &
      94              :                                                   nat, output_unit, socket
      95            0 :       TYPE(mp_request_type), DIMENSION(2) ::                                            wait_req
      96            0 :       INTEGER(KIND=int_4), POINTER             :: wait_msg(:)
      97              :       LOGICAL                                  :: drv_unix, fwait, hasdata, &
      98              :                                                   ionode, should_stop
      99              :       REAL(KIND=dp)                            :: cellh(3, 3), cellih(3, 3), &
     100              :                                                   mxmat(9), pot, vir(3, 3)
     101            0 :       REAL(KIND=dp), ALLOCATABLE               :: combuf(:)
     102              :       TYPE(cell_type), POINTER                 :: cpcell
     103              :       TYPE(mp_para_env_type), POINTER          :: para_env
     104              :       TYPE(cp_subsys_type), POINTER            :: subsys
     105              :       TYPE(section_vals_type), POINTER         :: drv_section, motion_section
     106              :       TYPE(virial_type), POINTER               :: virial
     107              :       REAL(KIND=dp)                            :: sleeptime
     108              :       INTEGER, DIMENSION(3)                    :: perd
     109              :       TYPE(cell_type), POINTER                 :: oldcell
     110              : 
     111            0 :       CALL timeset(routineN, handle)
     112              : 
     113            0 :       CALL cite_reference(Ceriotti2014)
     114            0 :       CALL cite_reference(Kapil2016)
     115              : 
     116              : ! server address parsing
     117              : ! buffers and temporaries for communication
     118              : ! access cp2k structures
     119              : 
     120            0 :       CPASSERT(ASSOCIATED(force_env))
     121            0 :       CALL force_env_get(force_env, para_env=para_env)
     122              : 
     123            0 :       hasdata = .FALSE.
     124            0 :       ionode = para_env%is_source()
     125              : 
     126            0 :       output_unit = cp_logger_get_default_io_unit()
     127              : 
     128              :       ! reads driver parameters from input
     129            0 :       motion_section => section_vals_get_subs_vals(force_env%root_section, "MOTION")
     130            0 :       drv_section => section_vals_get_subs_vals(motion_section, "DRIVER")
     131              : 
     132            0 :       CALL section_vals_val_get(drv_section, "HOST", c_val=drv_hostname)
     133            0 :       CALL section_vals_val_get(drv_section, "PORT", i_val=drv_port)
     134            0 :       CALL section_vals_val_get(drv_section, "UNIX", l_val=drv_unix)
     135            0 :       CALL section_vals_val_get(drv_section, "SLEEP_TIME", r_val=sleeptime)
     136            0 :       CPASSERT(sleeptime >= 0)
     137              : 
     138              :       ! opens the socket
     139            0 :       socket = 0
     140            0 :       inet = 1
     141            0 :       i_drv_unix = 1 ! a bit convoluted. socket.c uses a different convention...
     142            0 :       IF (drv_unix) i_drv_unix = 0
     143            0 :       IF (output_unit > 0) THEN
     144            0 :          WRITE (output_unit, *) "@ i-PI DRIVER BEING LOADED"
     145            0 :          WRITE (output_unit, *) "@ INPUT DATA: ", TRIM(drv_hostname), drv_port, drv_unix
     146              :       END IF
     147              : 
     148            0 :       c_hostname = TRIM(drv_hostname)//C_NULL_CHAR
     149            0 :       IF (ionode) CALL open_connect_socket(socket, i_drv_unix, drv_port, c_hostname)
     150              : 
     151              :       NULLIFY (wait_msg)
     152            0 :       ALLOCATE (wait_msg(1))
     153              :       !now we have a socket, so we can initialize the CP2K environments.
     154            0 :       NULLIFY (cpcell)
     155            0 :       CALL cell_create(cpcell)
     156              :       driver_loop: DO
     157              :          ! do communication on master node only...
     158            0 :          header = ""
     159              : 
     160            0 :          CALL para_env%sync()
     161              : 
     162              :          ! non-blocking sync to avoid useless CPU consumption
     163            0 :          IF (ionode) THEN
     164            0 :             CALL readbuffer(socket, header, MSGLEN)
     165            0 :             wait_msg = 0
     166            0 :             DO iwait = 0, para_env%num_pe - 1
     167            0 :                IF (iwait /= para_env%source) THEN
     168            0 :                   CALL para_env%send(msg=wait_msg, dest=iwait, tag=666)
     169              :                END IF
     170              :             END DO
     171              :          ELSE
     172              :             CALL para_env%irecv(msgout=wait_msg, source=para_env%source, &
     173            0 :                                 tag=666, request=wait_req(2))
     174            0 :             CALL mp_testany(wait_req(2:), flag=fwait)
     175            0 :             DO WHILE (.NOT. fwait)
     176            0 :                CALL mp_testany(wait_req(2:), flag=fwait)
     177            0 :                CALL uwait(sleeptime)
     178              :             END DO
     179              :          END IF
     180              : 
     181            0 :          CALL para_env%sync()
     182              : 
     183            0 :          CALL para_env%bcast(header)
     184              : 
     185            0 :          IF (output_unit > 0) WRITE (output_unit, *) " @ DRIVER MODE: Message from server: ", TRIM(header)
     186            0 :          IF (TRIM(header) == "STATUS") THEN
     187              : 
     188            0 :             CALL para_env%sync()
     189            0 :             IF (ionode) THEN ! does not  need init (well, maybe it should, just to check atom numbers and the like... )
     190            0 :                IF (hasdata) THEN
     191            0 :                   CALL writebuffer(socket, "HAVEDATA    ", MSGLEN)
     192              :                ELSE
     193            0 :                   CALL writebuffer(socket, "READY       ", MSGLEN)
     194              :                END IF
     195              :             END IF
     196            0 :             CALL para_env%sync()
     197            0 :          ELSE IF (TRIM(header) == "POSDATA") THEN
     198            0 :             IF (ionode) THEN
     199            0 :                CALL readbuffer(socket, mxmat, 9)
     200            0 :                cellh = RESHAPE(mxmat, [3, 3])
     201            0 :                CALL readbuffer(socket, mxmat, 9)
     202            0 :                cellih = RESHAPE(mxmat, [3, 3])
     203            0 :                CALL readbuffer(socket, nat)
     204            0 :                cellh = TRANSPOSE(cellh)
     205            0 :                cellih = TRANSPOSE(cellih)
     206              :             END IF
     207            0 :             CALL para_env%bcast(cellh)
     208            0 :             CALL para_env%bcast(cellih)
     209            0 :             CALL para_env%bcast(nat)
     210            0 :             IF (.NOT. ALLOCATED(combuf)) ALLOCATE (combuf(3*nat))
     211            0 :             IF (ionode) CALL readbuffer(socket, combuf, nat*3)
     212            0 :             CALL para_env%bcast(combuf)
     213              : 
     214            0 :             CALL force_env_get(force_env, subsys=subsys)
     215            0 :             IF (nat /= subsys%particles%n_els) &
     216            0 :                CPABORT("@DRIVER MODE: Uh-oh! Particle number mismatch between i-PI and cp2k input!")
     217            0 :             ii = 0
     218            0 :             DO ip = 1, subsys%particles%n_els
     219            0 :                DO idir = 1, 3
     220            0 :                   ii = ii + 1
     221            0 :                   subsys%particles%els(ip)%r(idir) = combuf(ii)
     222              :                END DO
     223              :             END DO
     224            0 :             NULLIFY (oldcell)
     225            0 :             CALL cp_subsys_get(subsys, cell=oldcell)
     226            0 :             perd = oldcell%perd
     227              : 
     228            0 :             CALL init_cell(cpcell, hmat=cellh, periodic=perd)
     229            0 :             CALL cp_subsys_set(subsys, cell=cpcell)
     230              : 
     231            0 :             CALL force_env_calc_energy_force(force_env, calc_force=.TRUE.)
     232              : 
     233            0 :             IF (output_unit > 0) WRITE (output_unit, *) " @ DRIVER MODE: Received positions "
     234              : 
     235            0 :             combuf = 0
     236            0 :             ii = 0
     237            0 :             DO ip = 1, subsys%particles%n_els
     238            0 :                DO idir = 1, 3
     239            0 :                   ii = ii + 1
     240            0 :                   combuf(ii) = subsys%particles%els(ip)%f(idir)
     241              :                END DO
     242              :             END DO
     243            0 :             CALL force_env_get(force_env, potential_energy=pot)
     244            0 :             CALL force_env_get(force_env, cell=cpcell)
     245            0 :             CALL cp_subsys_get(subsys, virial=virial)
     246            0 :             vir = TRANSPOSE(virial%pv_virial)
     247              : 
     248            0 :             CALL external_control(should_stop, "IPI", globenv=globenv)
     249            0 :             IF (should_stop) EXIT driver_loop
     250              : 
     251              :             hasdata = .TRUE.
     252            0 :          ELSE IF (TRIM(header) == "GETFORCE") THEN
     253            0 :             IF (output_unit > 0) WRITE (output_unit, *) " @ DRIVER MODE: Returning v,forces,stress "
     254            0 :             IF (ionode) THEN
     255            0 :                CALL writebuffer(socket, "FORCEREADY  ", MSGLEN)
     256            0 :                CALL writebuffer(socket, pot)
     257            0 :                CALL writebuffer(socket, nat)
     258            0 :                CALL writebuffer(socket, combuf, 3*nat)
     259            0 :                CALL writebuffer(socket, RESHAPE(vir, [9]), 9)
     260              : 
     261              :                ! i-pi can also receive an arbitrary string, that will be printed out to the "extra"
     262              :                ! trajectory file. this is useful if you want to return additional information, e.g.
     263              :                ! atomic charges, wannier centres, etc. one must return the number of characters, then
     264              :                ! the string. here we just send back zero characters.
     265            0 :                nat = 0
     266            0 :                CALL writebuffer(socket, nat) ! writes out zero for the length of the "extra" field (not implemented yet!)
     267              :             END IF
     268              :             hasdata = .FALSE.
     269              :          ELSE
     270            0 :             IF (output_unit > 0) WRITE (output_unit, *) " @DRIVER MODE:  Socket disconnected, time to exit."
     271              :             EXIT driver_loop
     272              :          END IF
     273              :       END DO driver_loop
     274              : 
     275              :       ! clean up
     276            0 :       CALL cell_release(cpcell)
     277            0 :       DEALLOCATE (wait_msg)
     278              : #endif
     279              : 
     280            0 :       CALL timestop(handle)
     281              : 
     282            0 :    END SUBROUTINE run_driver
     283              : END MODULE ipi_driver
        

Generated by: LCOV version 2.0-1