LCOV - code coverage report
Current view: top level - src - ipi_driver.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b279b6b) Lines: 0 108 0.0 %
Date: 2024-04-24 07:13:09 Functions: 0 1 0.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 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 1.15