LCOV - code coverage report
Current view: top level - src - ipi_driver.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 0.0 % 108 0
Test Date: 2025-07-25 12:55:17 Functions: 0.0 % 1 0

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 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              : 
     109            0 :       CALL timeset(routineN, handle)
     110              : 
     111            0 :       CALL cite_reference(Ceriotti2014)
     112            0 :       CALL cite_reference(Kapil2016)
     113              : 
     114              : ! server address parsing
     115              : ! buffers and temporaries for communication
     116              : ! access cp2k structures
     117              : 
     118            0 :       CPASSERT(ASSOCIATED(force_env))
     119            0 :       CALL force_env_get(force_env, para_env=para_env)
     120              : 
     121            0 :       hasdata = .FALSE.
     122            0 :       ionode = para_env%is_source()
     123              : 
     124            0 :       output_unit = cp_logger_get_default_io_unit()
     125              : 
     126              :       ! reads driver parameters from input
     127            0 :       motion_section => section_vals_get_subs_vals(force_env%root_section, "MOTION")
     128            0 :       drv_section => section_vals_get_subs_vals(motion_section, "DRIVER")
     129              : 
     130            0 :       CALL section_vals_val_get(drv_section, "HOST", c_val=drv_hostname)
     131            0 :       CALL section_vals_val_get(drv_section, "PORT", i_val=drv_port)
     132            0 :       CALL section_vals_val_get(drv_section, "UNIX", l_val=drv_unix)
     133            0 :       CALL section_vals_val_get(drv_section, "SLEEP_TIME", r_val=sleeptime)
     134            0 :       CPASSERT(sleeptime >= 0)
     135              : 
     136              :       ! opens the socket
     137            0 :       socket = 0
     138            0 :       inet = 1
     139            0 :       i_drv_unix = 1 ! a bit convoluted. socket.c uses a different convention...
     140            0 :       IF (drv_unix) i_drv_unix = 0
     141            0 :       IF (output_unit > 0) THEN
     142            0 :          WRITE (output_unit, *) "@ i-PI DRIVER BEING LOADED"
     143            0 :          WRITE (output_unit, *) "@ INPUT DATA: ", TRIM(drv_hostname), drv_port, drv_unix
     144              :       END IF
     145              : 
     146            0 :       c_hostname = TRIM(drv_hostname)//C_NULL_CHAR
     147            0 :       IF (ionode) CALL open_connect_socket(socket, i_drv_unix, drv_port, c_hostname)
     148              : 
     149              :       NULLIFY (wait_msg)
     150            0 :       ALLOCATE (wait_msg(1))
     151              :       !now we have a socket, so we can initialize the CP2K environments.
     152            0 :       NULLIFY (cpcell)
     153            0 :       CALL cell_create(cpcell)
     154              :       driver_loop: DO
     155              :          ! do communication on master node only...
     156            0 :          header = ""
     157              : 
     158            0 :          CALL para_env%sync()
     159              : 
     160              :          ! non-blocking sync to avoid useless CPU consumption
     161            0 :          IF (ionode) THEN
     162            0 :             CALL readbuffer(socket, header, MSGLEN)
     163            0 :             wait_msg = 0
     164            0 :             DO iwait = 0, para_env%num_pe - 1
     165            0 :                IF (iwait /= para_env%source) THEN
     166            0 :                   CALL para_env%send(msg=wait_msg, dest=iwait, tag=666)
     167              :                END IF
     168              :             END DO
     169              :          ELSE
     170              :             CALL para_env%irecv(msgout=wait_msg, source=para_env%source, &
     171            0 :                                 tag=666, request=wait_req(2))
     172            0 :             CALL mp_testany(wait_req(2:), flag=fwait)
     173            0 :             DO WHILE (.NOT. fwait)
     174            0 :                CALL mp_testany(wait_req(2:), flag=fwait)
     175            0 :                CALL uwait(sleeptime)
     176              :             END DO
     177              :          END IF
     178              : 
     179            0 :          CALL para_env%sync()
     180              : 
     181            0 :          CALL para_env%bcast(header)
     182              : 
     183            0 :          IF (output_unit > 0) WRITE (output_unit, *) " @ DRIVER MODE: Message from server: ", TRIM(header)
     184            0 :          IF (TRIM(header) == "STATUS") THEN
     185              : 
     186            0 :             CALL para_env%sync()
     187            0 :             IF (ionode) THEN ! does not  need init (well, maybe it should, just to check atom numbers and the like... )
     188            0 :                IF (hasdata) THEN
     189            0 :                   CALL writebuffer(socket, "HAVEDATA    ", MSGLEN)
     190              :                ELSE
     191            0 :                   CALL writebuffer(socket, "READY       ", MSGLEN)
     192              :                END IF
     193              :             END IF
     194            0 :             CALL para_env%sync()
     195            0 :          ELSE IF (TRIM(header) == "POSDATA") THEN
     196            0 :             IF (ionode) THEN
     197            0 :                CALL readbuffer(socket, mxmat, 9)
     198            0 :                cellh = RESHAPE(mxmat, (/3, 3/))
     199            0 :                CALL readbuffer(socket, mxmat, 9)
     200            0 :                cellih = RESHAPE(mxmat, (/3, 3/))
     201            0 :                CALL readbuffer(socket, nat)
     202            0 :                cellh = TRANSPOSE(cellh)
     203            0 :                cellih = TRANSPOSE(cellih)
     204              :             END IF
     205            0 :             CALL para_env%bcast(cellh)
     206            0 :             CALL para_env%bcast(cellih)
     207            0 :             CALL para_env%bcast(nat)
     208            0 :             IF (.NOT. ALLOCATED(combuf)) ALLOCATE (combuf(3*nat))
     209            0 :             IF (ionode) CALL readbuffer(socket, combuf, nat*3)
     210            0 :             CALL para_env%bcast(combuf)
     211              : 
     212            0 :             CALL force_env_get(force_env, subsys=subsys)
     213            0 :             IF (nat /= subsys%particles%n_els) &
     214            0 :                CPABORT("@DRIVER MODE: Uh-oh! Particle number mismatch between i-PI and cp2k input!")
     215            0 :             ii = 0
     216            0 :             DO ip = 1, subsys%particles%n_els
     217            0 :                DO idir = 1, 3
     218            0 :                   ii = ii + 1
     219            0 :                   subsys%particles%els(ip)%r(idir) = combuf(ii)
     220              :                END DO
     221              :             END DO
     222            0 :             CALL init_cell(cpcell, hmat=cellh)
     223            0 :             CALL cp_subsys_set(subsys, cell=cpcell)
     224              : 
     225            0 :             CALL force_env_calc_energy_force(force_env, calc_force=.TRUE.)
     226              : 
     227            0 :             IF (output_unit > 0) WRITE (output_unit, *) " @ DRIVER MODE: Received positions "
     228              : 
     229            0 :             combuf = 0
     230            0 :             ii = 0
     231            0 :             DO ip = 1, subsys%particles%n_els
     232            0 :                DO idir = 1, 3
     233            0 :                   ii = ii + 1
     234            0 :                   combuf(ii) = subsys%particles%els(ip)%f(idir)
     235              :                END DO
     236              :             END DO
     237            0 :             CALL force_env_get(force_env, potential_energy=pot)
     238            0 :             CALL force_env_get(force_env, cell=cpcell)
     239            0 :             CALL cp_subsys_get(subsys, virial=virial)
     240            0 :             vir = TRANSPOSE(virial%pv_virial)
     241              : 
     242            0 :             CALL external_control(should_stop, "IPI", globenv=globenv)
     243            0 :             IF (should_stop) EXIT
     244              : 
     245              :             hasdata = .TRUE.
     246            0 :          ELSE IF (TRIM(header) == "GETFORCE") THEN
     247            0 :             IF (output_unit > 0) WRITE (output_unit, *) " @ DRIVER MODE: Returning v,forces,stress "
     248            0 :             IF (ionode) THEN
     249            0 :                CALL writebuffer(socket, "FORCEREADY  ", MSGLEN)
     250            0 :                CALL writebuffer(socket, pot)
     251            0 :                CALL writebuffer(socket, nat)
     252            0 :                CALL writebuffer(socket, combuf, 3*nat)
     253            0 :                CALL writebuffer(socket, RESHAPE(vir, (/9/)), 9)
     254              : 
     255              :                ! i-pi can also receive an arbitrary string, that will be printed out to the "extra"
     256              :                ! trajectory file. this is useful if you want to return additional information, e.g.
     257              :                ! atomic charges, wannier centres, etc. one must return the number of characters, then
     258              :                ! the string. here we just send back zero characters.
     259            0 :                nat = 0
     260            0 :                CALL writebuffer(socket, nat) ! writes out zero for the length of the "extra" field (not implemented yet!)
     261              :             END IF
     262              :             hasdata = .FALSE.
     263              :          ELSE
     264            0 :             IF (output_unit > 0) WRITE (output_unit, *) " @DRIVER MODE:  Socket disconnected, time to exit."
     265              :             EXIT
     266              :          END IF
     267              :       END DO driver_loop
     268              : 
     269              :       ! clean up
     270            0 :       CALL cell_release(cpcell)
     271            0 :       DEALLOCATE (wait_msg)
     272              : #endif
     273              : 
     274            0 :       CALL timestop(handle)
     275              : 
     276            0 :    END SUBROUTINE run_driver
     277              : END MODULE ipi_driver
        

Generated by: LCOV version 2.0-1