(git:ed6f26b)
Loading...
Searching...
No Matches
ipi_server.F
Go to the documentation of this file.
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 i–PI server mode: Communication with i–PI clients
10!> \par History
11!> 03.2024 created
12!> \author Sebastian Seidenath (sebastian.seidenath@uni-jena.de)
13! **************************************************************************************************
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 cell_methods, ONLY: cell_create, &
23 USE cell_types, ONLY: cell_release, &
27 USE cp_subsys_types, ONLY: cp_subsys_get, &
36 USE kinds, ONLY: default_path_length, &
38 dp, &
39 int_4
45#ifndef __NO_SOCKETS
46 USE sockets_interface, ONLY: writebuffer, &
47 readbuffer, &
48 uwait, &
54#endif
55 USE virial_types, ONLY: virial_type
56#include "./base/base_uses.f90"
57
58 IMPLICIT NONE
59
60 PRIVATE
61
62 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ipi_server'
63 INTEGER, PARAMETER :: msglength = 12
64
65 PUBLIC :: start_server, &
68
69CONTAINS
70
71! **************************************************************************************************
72!> \brief Starts the i–PI server. Will block until it recieves a connection.
73!> \param driver_section The driver section from the input file
74!> \param para_env ...
75!> \param ipi_env The ipi environment
76!> \author Sebastian Seidenath (sebastian.seidenath@uni-jena.de)
77! **************************************************************************************************
78 SUBROUTINE start_server(driver_section, para_env, ipi_env)
79 TYPE(section_vals_type), POINTER :: driver_section
80 TYPE(mp_para_env_type), POINTER :: para_env
81 TYPE(ipi_environment_type), POINTER :: ipi_env
82
83 CHARACTER(len=*), PARAMETER :: routinen = 'start_server'
84
85#ifdef __NO_SOCKETS
86 INTEGER :: handle
87 CALL timeset(routinen, handle)
88 cpabort("CP2K was compiled with the __NO_SOCKETS option!")
89#else
90 CHARACTER(len=default_path_length) :: c_hostname, drv_hostname
91 INTEGER :: drv_port, handle, i_drv_unix, &
92 output_unit, socket, comm_socket
93 CHARACTER(len=msglength) :: msgbuffer
94 CHARACTER(len=msglength), PARAMETER :: initmsg = "INIT"
95 LOGICAL :: drv_unix, ionode
96
97 CALL timeset(routinen, handle)
98 ionode = para_env%is_source()
99 output_unit = cp_logger_get_default_io_unit()
100
101 ! Read connection parameters
102 CALL section_vals_val_get(driver_section, "HOST", c_val=drv_hostname)
103 CALL section_vals_val_get(driver_section, "PORT", i_val=drv_port)
104 CALL section_vals_val_get(driver_section, "UNIX", l_val=drv_unix)
105 IF (output_unit > 0) THEN
106 WRITE (output_unit, *) "@ i-PI SERVER BEING STARTED"
107 WRITE (output_unit, *) "@ HOSTNAME: ", trim(drv_hostname)
108 WRITE (output_unit, *) "@ PORT: ", drv_port
109 WRITE (output_unit, *) "@ UNIX SOCKET: ", drv_unix
110 END IF
111
112 ! opens the socket
113 socket = 0
114 !inet = 1
115 i_drv_unix = 1 ! a bit convoluted. socket.c uses a different convention...
116 IF (drv_unix) i_drv_unix = 0
117
118 c_hostname = trim(drv_hostname)//c_null_char
119 IF (ionode) THEN
120 CALL open_bind_socket(socket, i_drv_unix, drv_port, c_hostname)
121 CALL listen_socket(socket, 1_c_int)
122 CALL accept_socket(socket, comm_socket)
123 CALL close_socket(socket)
124 CALL remove_socket_file(c_hostname)
125 CALL ipi_env_set(ipi_env=ipi_env, sockfd=comm_socket)
126 END IF
127
128 ! Check if the client needs initialization
129 ! We only send a meaningless message since we have no general way of
130 ! knowing what the client is expecting
131 CALL ask_status(comm_socket, msgbuffer)
132 IF (trim(msgbuffer) == "NEEDINIT") THEN
133 CALL writebuffer(comm_socket, initmsg, msglength)
134 CALL writebuffer(comm_socket, 1) ! Bead index - just send 1
135 CALL writebuffer(comm_socket, 12) ! Bits in the following message
136 CALL writebuffer(comm_socket, "Initializing", 12)
137 END IF
138
139#endif
140
141 CALL timestop(handle)
142
143 END SUBROUTINE start_server
144
145! **************************************************************************************************
146!> \brief Shut down the i–PI server.
147!> \param ipi_env The ipi environment in charge of the server
148!> \author Sebastian Seidenath (sebastian.seidenath@uni-jena.de)
149! **************************************************************************************************
150 SUBROUTINE shutdown_server(ipi_env)
151 TYPE(ipi_environment_type), POINTER :: ipi_env
152
153 CHARACTER(len=msglength), PARAMETER :: msg = "EXIT"
154
155 INTEGER :: output_unit
156
157 output_unit = cp_logger_get_default_io_unit()
158 WRITE (output_unit, *) –"@ iPI: Shutting down server."
159 CALL writebuffer(ipi_env%sockfd, msg, msglength)
160 CALL close_socket(ipi_env%sockfd)
161 END SUBROUTINE shutdown_server
162
163! **************************************************************************************************
164!> \brief Send atomic positions to a client and retrieve forces
165!> \param ipi_env The ipi environment in charge of the connection
166!> \author Sebastian Seidenath
167! **************************************************************************************************
168 SUBROUTINE request_forces(ipi_env)
169 TYPE(ipi_environment_type), POINTER :: ipi_env
170
171 CHARACTER(len=msglength) :: msgbuffer
172 INTEGER :: comm_socket, i, natom, p, xyz
173 REAL(kind=dp) :: energy
174 REAL(kind=dp), DIMENSION(:, :), POINTER :: forces
175
176 i = 0
177 natom = ipi_env%subsys%particles%n_els
178 comm_socket = ipi_env%sockfd
179
180 ! Step 1: See if the client is ready
181 CALL ask_status(comm_socket, msgbuffer)
182 IF (trim(msgbuffer) /= "READY") &
183 cpabort(–"iPI: Expected READY header but recieved "//trim(msgbuffer))
184
185 ! Step 2: Send cell and position data to client
186 CALL send_posdata(comm_socket, subsys=ipi_env%subsys)
187
188 ! Step 3: Ask for status, should be done now
189 CALL ask_status(comm_socket, msgbuffer)
190 IF (trim(msgbuffer) /= "HAVEDATA") &
191 cpabort(–"iPI: Expected HAVEDATA header but recieved "//trim(msgbuffer))
192
193 ! Step 4: Ask for data
194 ALLOCATE (forces(3, natom))
195 CALL ask_getforce(comm_socket, energy=energy, forces=forces)
196
197 ! Step 4.5: Check for sanity
198 IF (SIZE(forces) /= (natom*3)) THEN
199 cpabort(––"iPI: Mismatch in particle number between CP2K and iPI client")
200 END IF
201
202 ! Step 5: Return data
203 DO p = 1, natom
204 DO xyz = 1, 3
205 ipi_env%subsys%particles%els(p)%f(xyz) = forces(xyz, p)
206 END DO
207 END DO
208 CALL ipi_env_set(ipi_env=ipi_env, ipi_energy=energy, ipi_forces=forces)
209 END SUBROUTINE request_forces
210
211! **************************************************************************************************
212!> \brief ...
213!> \param sockfd ...
214!> \param buffer ...
215! **************************************************************************************************
216 SUBROUTINE get_header(sockfd, buffer)
217 INTEGER, INTENT(IN) :: sockfd
218 CHARACTER(len=msglength), INTENT(OUT) :: buffer
219
220 INTEGER :: output_unit
221
222 CALL readbuffer(sockfd, buffer, msglength)
223 output_unit = cp_logger_get_default_io_unit()
224 IF (output_unit > 0) WRITE (output_unit, *) –" @ iPI Server: recieved ", trim(buffer)
225 END SUBROUTINE get_header
226
227! **************************************************************************************************
228!> \brief ...
229!> \param sockfd ...
230!> \param buffer ...
231! **************************************************************************************************
232 SUBROUTINE ask_status(sockfd, buffer)
233 INTEGER, INTENT(IN) :: sockfd
234 CHARACTER(len=msglength), INTENT(OUT) :: buffer
235
236 CHARACTER(len=msglength), PARAMETER :: msg = "STATUS"
237
238 CALL writebuffer(sockfd, msg, msglength)
239 CALL get_header(sockfd, buffer)
240 END SUBROUTINE ask_status
241
242! **************************************************************************************************
243!> \brief ...
244!> \param sockfd ...
245!> \param energy ...
246!> \param forces ...
247!> \param virial ...
248!> \param extra ...
249! **************************************************************************************************
250 SUBROUTINE ask_getforce(sockfd, energy, forces, virial, extra)
251 INTEGER, INTENT(IN) :: sockfd
252 REAL(kind=dp), INTENT(OUT) :: energy
253 REAL(kind=dp), DIMENSION(:, :), INTENT(OUT), &
254 OPTIONAL, POINTER :: forces
255 REAL(kind=dp), DIMENSION(3, 3), INTENT(OUT), &
256 OPTIONAL :: virial
257 CHARACTER(len=:), INTENT(OUT), OPTIONAL, POINTER :: extra
258
259 CHARACTER(len=msglength), PARAMETER :: msg = "GETFORCE"
260
261 CHARACTER(len=:), ALLOCATABLE :: extra_buffer
262 CHARACTER(len=msglength) :: msgbuffer
263 INTEGER :: extralength, natom
264 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: forces_buffer
265 REAL(kind=dp), DIMENSION(9) :: virial_buffer
266
267 ! Exchange headers
268 CALL writebuffer(sockfd, msg, msglength)
269 CALL get_header(sockfd, msgbuffer)
270 IF (trim(msgbuffer) /= "FORCEREADY") &
271 cpabort(–"iPI: Expected FORCEREADY header but recieved "//trim(msgbuffer))
272
273 ! Recieve data
274 CALL readbuffer(sockfd, energy)
275 CALL readbuffer(sockfd, natom)
276 ALLOCATE (forces_buffer(3*natom))
277 CALL readbuffer(sockfd, forces_buffer, natom*3)
278 CALL readbuffer(sockfd, virial_buffer, 9)
279 CALL readbuffer(sockfd, extralength)
280 ALLOCATE (CHARACTER(len=extraLength) :: extra_buffer)
281 IF (extralength /= 0) THEN ! readbuffer(x,y,0) is always an error
282 CALL readbuffer(sockfd, extra_buffer, extralength)
283 END IF
284
285 IF (PRESENT(forces)) forces = reshape(forces_buffer, shape=[3, natom])
286 IF (PRESENT(virial)) virial = reshape(virial_buffer, shape=[3, 3])
287 IF (PRESENT(extra)) extra = extra_buffer
288 END SUBROUTINE ask_getforce
289
290! **************************************************************************************************
291!> \brief ...
292!> \param sockfd ...
293!> \param subsys ...
294! **************************************************************************************************
295 SUBROUTINE send_posdata(sockfd, subsys)
296 INTEGER, INTENT(IN) :: sockfd
297 TYPE(cp_subsys_type), POINTER :: subsys
298
299 CHARACTER(len=msglength), PARAMETER :: msg = "POSDATA"
300
301 INTEGER :: i, natom, p, xyz
302 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: particle_buffer
303 REAL(kind=dp), DIMENSION(9) :: cell_data, icell_data
304
305 i = 0
306
307 CALL writebuffer(sockfd, msg, msglength)
308
309 cell_data = reshape(transpose(subsys%cell%hmat), (/9/))
310 CALL writebuffer(sockfd, cell_data, 9)
311
312 icell_data = reshape(transpose(subsys%cell%h_inv), (/9/))
313 CALL writebuffer(sockfd, icell_data, 9)
314
315 natom = subsys%particles%n_els
316 CALL writebuffer(sockfd, natom)
317
318 ALLOCATE (particle_buffer(3*natom))
319 DO p = 1, natom
320 DO xyz = 1, 3
321 i = i + 1
322 particle_buffer(i) = subsys%particles%els(p)%r(xyz)
323 END DO
324 END DO
325 CALL writebuffer(sockfd, particle_buffer, natom*3)
326
327 END SUBROUTINE send_posdata
328
329END MODULE ipi_server
Handles all functions related to the CELL.
subroutine, public init_cell(cell, hmat, periodic)
Initialise/readjust a simulation cell after hmat has been changed.
subroutine, public cell_create(cell, hmat, periodic, tag)
allocates and initializes a cell
Handles all functions related to the CELL.
Definition cell_types.F:15
subroutine, public cell_release(cell)
releases the given cell (see doc/ReferenceCounting.html)
Definition cell_types.F:559
Routines to handle the external control of CP2K.
subroutine, public external_control(should_stop, flag, globenv, target_time, start_time, force_check)
External manipulations during a run : when the <PROJECT_NAME>.EXIT_$runtype command is sent the progr...
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
types that represent a subsys, i.e. a part of the system
subroutine, public cp_subsys_set(subsys, atomic_kinds, particles, local_particles, molecules, molecule_kinds, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, results, cell)
sets various propreties of the subsys
subroutine, public cp_subsys_get(subsys, ref_count, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell)
returns information about various attributes of the given subsys
Define type storing the global information of a run. Keep the amount of stored data small....
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
The environment for the empirical interatomic potential methods.
subroutine, public ipi_env_set(ipi_env, ipi_energy, ipi_forces, subsys, atomic_kind_set, particle_set, local_particles, molecule_kind_set, molecule_set, local_molecules, force_env_input, cell_ref, sockfd)
Sets various attributes of the ipi environment.
i–PI server mode: Communication with i–PI clients
Definition ipi_server.F:14
subroutine, public shutdown_server(ipi_env)
Shut down the i–PI server.
Definition ipi_server.F:151
subroutine, public request_forces(ipi_env)
Send atomic positions to a client and retrieve forces.
Definition ipi_server.F:169
subroutine, public start_server(driver_section, para_env, ipi_env)
Starts the i–PI server. Will block until it recieves a connection.
Definition ipi_server.F:79
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public default_path_length
Definition kinds.F:58
integer, parameter, public int_4
Definition kinds.F:51
Interface to the message passing library MPI.
represent a simple array based list of the given type
Define the data structure for the particle information.
Implements UNIX and INET sockets.
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
represents a system: atoms, molecules, their pos,vel,...
contains the initially parsed file and the initial parallel environment
stores all the informations relevant to an mpi environment