(git:42db5d2)
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-2026 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, drv_prefix
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 CALL section_vals_val_get(driver_section, "PREFIX", c_val=drv_prefix)
106 IF (output_unit > 0) THEN
107 WRITE (output_unit, *) "@ i-PI SERVER BEING STARTED"
108 WRITE (output_unit, *) "@ HOSTNAME: ", trim(drv_hostname)
109 WRITE (output_unit, *) "@ PORT: ", drv_port
110 WRITE (output_unit, *) "@ UNIX SOCKET: ", drv_unix
111 END IF
112
113 ! opens the socket
114 socket = 0
115 !inet = 1
116 i_drv_unix = 1 ! a bit convoluted. socket.c uses a different convention...
117 IF (drv_unix) i_drv_unix = 0
118
119 IF (drv_unix) THEN
120 ! for UNIX sockets, HOST names the socket file which lives at
121 ! /tmp/<PREFIX>_<HOST> (PREFIX must match the peer's convention,
122 ! e.g. "ipi" for i-PI)
123 c_hostname = "/tmp/"//trim(drv_prefix)//"_"//trim(drv_hostname)//c_null_char
124 ELSE
125 c_hostname = trim(drv_hostname)//c_null_char
126 END IF
127 IF (ionode) THEN
128 CALL open_bind_socket(socket, i_drv_unix, drv_port, c_hostname)
129 CALL listen_socket(socket, 1_c_int)
130 CALL accept_socket(socket, comm_socket)
131 CALL close_socket(socket)
132 CALL remove_socket_file(c_hostname)
133 CALL ipi_env_set(ipi_env=ipi_env, sockfd=comm_socket)
134 END IF
135
136 ! Check if the client needs initialization
137 ! We only send a meaningless message since we have no general way of
138 ! knowing what the client is expecting
139 CALL ask_status(comm_socket, msgbuffer)
140 IF (trim(msgbuffer) == "NEEDINIT") THEN
141 CALL writebuffer(comm_socket, initmsg, msglength)
142 CALL writebuffer(comm_socket, 1) ! Bead index - just send 1
143 CALL writebuffer(comm_socket, 12) ! Bits in the following message
144 CALL writebuffer(comm_socket, "Initializing", 12)
145 END IF
146
147#endif
148
149 CALL timestop(handle)
150
151 END SUBROUTINE start_server
152
153! **************************************************************************************************
154!> \brief Shut down the i–PI server.
155!> \param ipi_env The ipi environment in charge of the server
156!> \author Sebastian Seidenath (sebastian.seidenath@uni-jena.de)
157! **************************************************************************************************
158 SUBROUTINE shutdown_server(ipi_env)
159 TYPE(ipi_environment_type), POINTER :: ipi_env
160
161 CHARACTER(len=msglength), PARAMETER :: msg = "EXIT"
162
163 INTEGER :: output_unit
164
165 output_unit = cp_logger_get_default_io_unit()
166 WRITE (output_unit, *) –"@ iPI: Shutting down server."
167 CALL writebuffer(ipi_env%sockfd, msg, msglength)
168 CALL close_socket(ipi_env%sockfd)
169 END SUBROUTINE shutdown_server
170
171! **************************************************************************************************
172!> \brief Send atomic positions to a client and retrieve forces
173!> \param ipi_env The ipi environment in charge of the connection
174!> \author Sebastian Seidenath
175! **************************************************************************************************
176 SUBROUTINE request_forces(ipi_env)
177 TYPE(ipi_environment_type), POINTER :: ipi_env
178
179 CHARACTER(len=msglength) :: msgbuffer
180 INTEGER :: comm_socket, i, natom, p, xyz
181 REAL(kind=dp) :: energy
182 REAL(kind=dp), DIMENSION(:, :), POINTER :: forces
183
184 i = 0
185 natom = ipi_env%subsys%particles%n_els
186 comm_socket = ipi_env%sockfd
187
188 ! Step 1: See if the client is ready
189 CALL ask_status(comm_socket, msgbuffer)
190 IF (trim(msgbuffer) /= "READY") THEN
191 cpabort(–"iPI: Expected READY header but recieved "//trim(msgbuffer))
192 END IF
193
194 ! Step 2: Send cell and position data to client
195 CALL send_posdata(comm_socket, subsys=ipi_env%subsys)
196
197 ! Step 3: Ask for status, should be done now
198 CALL ask_status(comm_socket, msgbuffer)
199 IF (trim(msgbuffer) /= "HAVEDATA") THEN
200 cpabort(–"iPI: Expected HAVEDATA header but recieved "//trim(msgbuffer))
201 END IF
202
203 ! Step 4: Ask for data
204 ALLOCATE (forces(3, natom))
205 CALL ask_getforce(comm_socket, energy=energy, forces=forces)
206
207 ! Step 4.5: Check for sanity
208 IF (SIZE(forces) /= (natom*3)) THEN
209 cpabort(––"iPI: Mismatch in particle number between CP2K and iPI client")
210 END IF
211
212 ! Step 5: Return data
213 DO p = 1, natom
214 DO xyz = 1, 3
215 ipi_env%subsys%particles%els(p)%f(xyz) = forces(xyz, p)
216 END DO
217 END DO
218 CALL ipi_env_set(ipi_env=ipi_env, ipi_energy=energy, ipi_forces=forces)
219 END SUBROUTINE request_forces
220
221! **************************************************************************************************
222!> \brief ...
223!> \param sockfd ...
224!> \param buffer ...
225! **************************************************************************************************
226 SUBROUTINE get_header(sockfd, buffer)
227 INTEGER, INTENT(IN) :: sockfd
228 CHARACTER(len=msglength), INTENT(OUT) :: buffer
229
230 INTEGER :: output_unit
231
232 CALL readbuffer(sockfd, buffer, msglength)
233 output_unit = cp_logger_get_default_io_unit()
234 IF (output_unit > 0) WRITE (output_unit, *) –" @ iPI Server: recieved ", trim(buffer)
235 END SUBROUTINE get_header
236
237! **************************************************************************************************
238!> \brief ...
239!> \param sockfd ...
240!> \param buffer ...
241! **************************************************************************************************
242 SUBROUTINE ask_status(sockfd, buffer)
243 INTEGER, INTENT(IN) :: sockfd
244 CHARACTER(len=msglength), INTENT(OUT) :: buffer
245
246 CHARACTER(len=msglength), PARAMETER :: msg = "STATUS"
247
248 CALL writebuffer(sockfd, msg, msglength)
249 CALL get_header(sockfd, buffer)
250 END SUBROUTINE ask_status
251
252! **************************************************************************************************
253!> \brief ...
254!> \param sockfd ...
255!> \param energy ...
256!> \param forces ...
257!> \param virial ...
258!> \param extra ...
259! **************************************************************************************************
260 SUBROUTINE ask_getforce(sockfd, energy, forces, virial, extra)
261 INTEGER, INTENT(IN) :: sockfd
262 REAL(kind=dp), INTENT(OUT) :: energy
263 REAL(kind=dp), DIMENSION(:, :), INTENT(OUT), &
264 OPTIONAL, POINTER :: forces
265 REAL(kind=dp), DIMENSION(3, 3), INTENT(OUT), &
266 OPTIONAL :: virial
267 CHARACTER(len=:), INTENT(OUT), OPTIONAL, POINTER :: extra
268
269 CHARACTER(len=msglength), PARAMETER :: msg = "GETFORCE"
270
271 CHARACTER(len=:), ALLOCATABLE :: extra_buffer
272 CHARACTER(len=msglength) :: msgbuffer
273 INTEGER :: extralength, natom
274 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: forces_buffer
275 REAL(kind=dp), DIMENSION(9) :: virial_buffer
276
277 ! Exchange headers
278 CALL writebuffer(sockfd, msg, msglength)
279 CALL get_header(sockfd, msgbuffer)
280 IF (trim(msgbuffer) /= "FORCEREADY") THEN
281 cpabort(–"iPI: Expected FORCEREADY header but recieved "//trim(msgbuffer))
282 END IF
283
284 ! Recieve data
285 CALL readbuffer(sockfd, energy)
286 CALL readbuffer(sockfd, natom)
287 ALLOCATE (forces_buffer(3*natom))
288 CALL readbuffer(sockfd, forces_buffer, natom*3)
289 CALL readbuffer(sockfd, virial_buffer, 9)
290 CALL readbuffer(sockfd, extralength)
291 ALLOCATE (CHARACTER(len=extraLength) :: extra_buffer)
292 IF (extralength /= 0) THEN ! readbuffer(x,y,0) is always an error
293 CALL readbuffer(sockfd, extra_buffer, extralength)
294 END IF
295
296 IF (PRESENT(forces)) forces = reshape(forces_buffer, shape=[3, natom])
297 IF (PRESENT(virial)) virial = reshape(virial_buffer, shape=[3, 3])
298 IF (PRESENT(extra)) extra = extra_buffer
299 END SUBROUTINE ask_getforce
300
301! **************************************************************************************************
302!> \brief ...
303!> \param sockfd ...
304!> \param subsys ...
305! **************************************************************************************************
306 SUBROUTINE send_posdata(sockfd, subsys)
307 INTEGER, INTENT(IN) :: sockfd
308 TYPE(cp_subsys_type), POINTER :: subsys
309
310 CHARACTER(len=msglength), PARAMETER :: msg = "POSDATA"
311
312 INTEGER :: i, natom, p, xyz
313 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: particle_buffer
314 REAL(kind=dp), DIMENSION(9) :: cell_data, icell_data
315
316 i = 0
317
318 CALL writebuffer(sockfd, msg, msglength)
319
320 cell_data = reshape(transpose(subsys%cell%hmat), [9])
321 CALL writebuffer(sockfd, cell_data, 9)
322
323 icell_data = reshape(transpose(subsys%cell%h_inv), [9])
324 CALL writebuffer(sockfd, icell_data, 9)
325
326 natom = subsys%particles%n_els
327 CALL writebuffer(sockfd, natom)
328
329 ALLOCATE (particle_buffer(3*natom))
330 DO p = 1, natom
331 DO xyz = 1, 3
332 i = i + 1
333 particle_buffer(i) = subsys%particles%els(p)%r(xyz)
334 END DO
335 END DO
336 CALL writebuffer(sockfd, particle_buffer, natom*3)
337
338 END SUBROUTINE send_posdata
339
340END 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:668
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, cell_ref, use_ref_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, cell_ref, use_ref_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:159
subroutine, public request_forces(ipi_env)
Send atomic positions to a client and retrieve forces.
Definition ipi_server.F:177
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:60
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