Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / imd / imd.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 /*! \internal \file
37  *
38  * \brief
39  * Implements Interactive Molecular Dynamics
40  *
41  * Re-implementation of basic IMD functions to work with VMD,
42  * see imdsocket.h for references to the IMD API.
43  *
44  * \author Martin Hoefling, Carsten Kutzner <ckutzne@gwdg.de>
45  *
46  * \ingroup module_imd
47  */
48 #include "gmxpre.h"
49
50 #include "imd.h"
51
52 #include "config.h"
53
54 #include <cerrno>
55 #include <cstring>
56
57 #include "gromacs/commandline/filenm.h"
58 #include "gromacs/domdec/domdec_struct.h"
59 #include "gromacs/domdec/ga2la.h"
60 #include "gromacs/fileio/confio.h"
61 #include "gromacs/fileio/gmxfio.h"
62 #include "gromacs/fileio/xvgr.h"
63 #include "gromacs/gmxlib/network.h"
64 #include "gromacs/imd/imdsocket.h"
65 #include "gromacs/math/units.h"
66 #include "gromacs/math/vec.h"
67 #include "gromacs/mdlib/broadcaststructs.h"
68 #include "gromacs/mdlib/groupcoord.h"
69 #include "gromacs/mdlib/sighandler.h"
70 #include "gromacs/mdlib/stat.h"
71 #include "gromacs/mdrunutility/handlerestart.h"
72 #include "gromacs/mdrunutility/multisim.h"
73 #include "gromacs/mdtypes/enerdata.h"
74 #include "gromacs/mdtypes/imdmodule.h"
75 #include "gromacs/mdtypes/inputrec.h"
76 #include "gromacs/mdtypes/md_enums.h"
77 #include "gromacs/mdtypes/mdrunoptions.h"
78 #include "gromacs/mdtypes/state.h"
79 #include "gromacs/pbcutil/pbc.h"
80 #include "gromacs/timing/wallcycle.h"
81 #include "gromacs/topology/mtop_util.h"
82 #include "gromacs/topology/topology.h"
83 #include "gromacs/utility/fatalerror.h"
84 #include "gromacs/utility/logger.h"
85 #include "gromacs/utility/smalloc.h"
86 #include "gromacs/utility/stringutil.h"
87
88 namespace gmx
89 {
90
91 /*! \brief How long shall we wait in seconds until we check for a connection again? */
92 constexpr int c_loopWait = 1;
93
94 /*! \brief How long shall we check for the IMD_GO? */
95 constexpr int c_connectWait = 1;
96
97 /*! \brief IMD Header Size. */
98 constexpr int c_headerSize = 8;
99
100 /*! \brief IMD Protocol Version. */
101 constexpr int c_protocolVersion = 2;
102
103 /*! \internal
104  * \brief
105  * IMD (interactive molecular dynamics) energy record.
106  *
107  * As in the original IMD implementation. Energies in kcal/mol.
108  * NOTE: We return the energies in GROMACS / SI units,
109  * so they also show up as SI in VMD.
110  *
111  */
112 typedef struct
113 {
114     int32_t tstep;   /**< time step                                     */
115     float   T_abs;   /**< absolute temperature                          */
116     float   E_tot;   /**< total energy                                  */
117     float   E_pot;   /**< potential energy                              */
118     float   E_vdw;   /**< van der Waals energy                          */
119     float   E_coul;  /**< Coulomb interaction energy                    */
120     float   E_bond;  /**< bonds energy                                  */
121     float   E_angle; /**< angles energy                                 */
122     float   E_dihe;  /**< dihedrals energy                              */
123     float   E_impr;  /**< improper dihedrals energy                     */
124 } IMDEnergyBlock;
125
126
127 /*! \internal
128  * \brief IMD (interactive molecular dynamics) communication structure.
129  *
130  * This structure defines the IMD communication message header & protocol version.
131  */
132 typedef struct
133 {
134     int32_t type;   /**< Type of IMD message, see IMDType_t above      */
135     int32_t length; /**< Length                                        */
136 } IMDHeader;
137
138
139 /*! \internal
140  * \brief Implementation type for the IMD session
141  *
142  * \todo Make this class (or one extracted from it) model
143  * IForceProvider.
144  * \todo Use RAII for files and allocations
145  */
146 class ImdSession::Impl
147 {
148 public:
149     //! Constructor
150     Impl(const MDLogger& mdlog);
151     ~Impl();
152
153     /*! \brief Prepare the socket on the MASTER. */
154     void prepareMasterSocket();
155     /*! \brief Disconnect the client. */
156     void disconnectClient();
157     /*! \brief Prints an error message and disconnects the client.
158      *
159      *  Does not terminate mdrun!
160      */
161     void issueFatalError(const char* msg);
162     /*! \brief Check whether we got an incoming connection. */
163     bool tryConnect();
164     /*! \brief Wrap imd_tryconnect in order to make it blocking.
165      *
166      * Used when the simulation should wait for an incoming connection.
167      */
168     void blockConnect();
169     /*! \brief Make sure that our array holding the forces received via IMD is large enough. */
170     void prepareVmdForces();
171     /*! \brief Reads forces received via IMD. */
172     void readVmdForces();
173     /*! \brief Prepares the MD force arrays. */
174     void prepareMDForces();
175     /*! \brief Copy IMD forces to MD forces.
176      *
177      * Do conversion from Cal->Joule and from
178      * Angstrom -> nm and from a pointer array to arrays to 3*N array.
179      */
180     void copyToMDForces();
181     /*! \brief Return true if any of the forces or indices changed. */
182     bool bForcesChanged() const;
183     /*! \brief Update the old_f_ind and old_forces arrays to contain the current values. */
184     void keepOldValues();
185     /*! \brief Write the applied pull forces to logfile.
186      *
187      * Call on master only!
188      */
189     void outputForces(double time);
190     /*! \brief Synchronize the nodes. */
191     void syncNodes(const t_commrec* cr, double t);
192     /*! \brief Reads header from the client and decides what to do. */
193     void readCommand();
194     /*! \brief Open IMD output file and write header information.
195      *
196      * Call on master only.
197      */
198     void openOutputFile(const char* fn, int nat_total, const gmx_output_env_t* oenv, StartingBehavior startingBehavior);
199     /*! \brief Creates the molecule start-end position array of molecules in the IMD group. */
200     void prepareMoleculesInImdGroup(const gmx_mtop_t* top_global);
201     /*! \brief Removes shifts of molecules diffused outside of the box. */
202     void removeMolecularShifts(const matrix box);
203     /*! \brief Initialize arrays used to assemble the positions from the other nodes. */
204     void prepareForPositionAssembly(const t_commrec* cr, const rvec x[]);
205     /*! \brief Interact with any connected VMD session */
206     bool run(int64_t step, bool bNS, const matrix box, const rvec x[], double t);
207
208     // TODO rename all the data members to have underscore suffixes
209
210     //! True if tpr and mdrun input combine to permit IMD sessions
211     bool sessionPossible = false;
212     //! Output file for IMD data, mainly forces.
213     FILE* outf = nullptr;
214
215     //! Number of atoms that can be pulled via IMD.
216     int nat = 0;
217     //! Part of the atoms that are local.
218     int nat_loc = 0;
219     //! Global indices of the IMD atoms.
220     int* ind = nullptr;
221     //! Local indices of the IMD atoms.
222     int* ind_loc = nullptr;
223     //! Allocation size for ind_loc.
224     int nalloc_loc = 0;
225     //! Positions for all IMD atoms assembled on the master node.
226     rvec* xa = nullptr;
227     //! Shifts for all IMD atoms, to make molecule(s) whole.
228     ivec* xa_shifts = nullptr;
229     //! Extra shifts since last DD step.
230     ivec* xa_eshifts = nullptr;
231     //! Old positions for all IMD atoms on master.
232     rvec* xa_old = nullptr;
233     //! Position of each local atom in the collective array.
234     int* xa_ind = nullptr;
235
236     //! Global IMD frequency, known to all ranks.
237     int nstimd = 1;
238     //! New frequency from IMD client, master only.
239     int nstimd_new = 1;
240     //! Default IMD frequency when disconnected.
241     int defaultNstImd = -1;
242
243     //! Port to use for network socket.
244     int port = 0;
245     //! The IMD socket on the master node.
246     IMDSocket* socket = nullptr;
247     //! The IMD socket on the client.
248     IMDSocket* clientsocket = nullptr;
249     //! Length we got with last header.
250     int length = 0;
251
252     //! Shall we block and wait for connection?
253     bool bWConnect = false;
254     //! Set if MD is terminated.
255     bool bTerminated = false;
256     //! Set if MD can be terminated.
257     bool bTerminatable = false;
258     //! Set if connection is present.
259     bool bConnected = false;
260     //! Set if we received new forces.
261     bool bNewForces = false;
262     //! Set if pulling from VMD is allowed.
263     bool bForceActivated = false;
264
265     //! Pointer to energies we send back.
266     IMDEnergyBlock* energies = nullptr;
267
268     //! Number of VMD forces.
269     int32_t vmd_nforces = 0;
270     //! VMD forces indices.
271     int32_t* vmd_f_ind = nullptr;
272     //! The VMD forces flat in memory.
273     float* vmd_forces = nullptr;
274     //! Number of actual MD forces; this gets communicated to the clients.
275     int nforces = 0;
276     //! Force indices.
277     int* f_ind = nullptr;
278     //! The IMD pulling forces.
279     rvec* f = nullptr;
280
281     //! Buffer for force sending.
282     char* forcesendbuf = nullptr;
283     //! Buffer for coordinate sending.
284     char* coordsendbuf = nullptr;
285     //! Send buffer for energies.
286     char* energysendbuf = nullptr;
287     //! Buffer to make molecules whole before sending.
288     rvec* sendxbuf = nullptr;
289
290     //! Molecules block in IMD group.
291     t_block mols;
292
293     /* The next block is used on the master node only to reduce the output
294      * without sacrificing information. If any of these values changes,
295      * we need to write output */
296     //! Old value for nforces.
297     int old_nforces = 0;
298     //! Old values for force indices.
299     int* old_f_ind = nullptr;
300     //! Old values for IMD pulling forces.
301     rvec* old_forces = nullptr;
302
303     //! Logger
304     const MDLogger& mdlog;
305     //! Commmunication object
306     const t_commrec* cr = nullptr;
307     //! Wallcycle counting manager.
308     gmx_wallcycle* wcycle = nullptr;
309     //! Energy output handler
310     gmx_enerdata_t* enerd = nullptr;
311 };
312
313 /*! \internal
314  * \brief Implement interactive molecular dynamics.
315  *
316  * \todo Some aspects of this module provides forces (when the user
317  * pulls on things in VMD), so in future it should have a class that
318  * models IForceProvider and is contributed to the collection of such
319  * things.
320  */
321 class InteractiveMolecularDynamics final : public IMDModule
322 {
323     // From IMDModule
324     IMdpOptionProvider* mdpOptionProvider() override { return nullptr; }
325     IMDOutputProvider*  outputProvider() override { return nullptr; }
326     void                initForceProviders(ForceProviders* /* forceProviders */) override {}
327 };
328
329 std::unique_ptr<IMDModule> createInteractiveMolecularDynamicsModule()
330 {
331     return std::make_unique<InteractiveMolecularDynamics>();
332 }
333
334 /*! \brief Enum for types of IMD messages.
335  *
336  * We use the same records as the NAMD/VMD IMD implementation.
337  */
338 typedef enum IMDType_t
339 {
340     IMD_DISCONNECT, /**< client disconnect                               */
341     IMD_ENERGIES,   /**< energy data                                     */
342     IMD_FCOORDS,    /**< atomic coordinates                              */
343     IMD_GO,         /**< start command for the simulation                */
344     IMD_HANDSHAKE,  /**< handshake to determine little/big endianness    */
345     IMD_KILL,       /**< terminates the simulation                       */
346     IMD_MDCOMM,     /**< force data                                      */
347     IMD_PAUSE,      /**< pauses the simulation                           */
348     IMD_TRATE,      /**< sets the IMD transmission and processing rate   */
349     IMD_IOERROR,    /**< I/O error                                       */
350     IMD_NR          /**< number of entries                               */
351 } IMDMessageType;
352
353
354 /*! \brief Names of the IMDType for error messages.
355  */
356 static const char* eIMDType_names[IMD_NR + 1] = { "IMD_DISCONNECT", "IMD_ENERGIES",  "IMD_FCOORDS",
357                                                   "IMD_GO",         "IMD_HANDSHAKE", "IMD_KILL",
358                                                   "IMD_MDCOMM",     "IMD_PAUSE",     "IMD_TRATE",
359                                                   "IMD_IOERROR",    nullptr };
360
361
362 /*! \brief Fills the header with message and the length argument. */
363 static void fill_header(IMDHeader* header, IMDMessageType type, int32_t length)
364 {
365     /* We (ab-)use htonl network function for the correct endianness */
366     header->type   = imd_htonl(static_cast<int32_t>(type));
367     header->length = imd_htonl(length);
368 }
369
370
371 /*! \brief Swaps the endianess of the header. */
372 static void swap_header(IMDHeader* header)
373 {
374     /* and vice versa... */
375     header->type   = imd_ntohl(header->type);
376     header->length = imd_ntohl(header->length);
377 }
378
379
380 /*! \brief Reads multiple bytes from socket. */
381 static int32_t imd_read_multiple(IMDSocket* socket, char* datptr, int32_t toread)
382 {
383     int32_t leftcount, countread;
384
385
386     leftcount = toread;
387     /* Try to read while we haven't reached toread */
388     while (leftcount != 0)
389     {
390         if ((countread = imdsock_read(socket, datptr, leftcount)) < 0)
391         {
392             /* interrupted function call, try again... */
393             if (errno == EINTR)
394             {
395                 countread = 0;
396             }
397             /* this is an unexpected error, return what we got */
398             else
399             {
400                 return toread - leftcount;
401             }
402
403             /* nothing read, finished */
404         }
405         else if (countread == 0)
406         {
407             break;
408         }
409         leftcount -= countread;
410         datptr += countread;
411     } /* end while */
412
413     /* return nr of bytes read */
414     return toread - leftcount;
415 }
416
417
418 /*! \brief Writes multiple bytes to socket in analogy to imd_read_multiple. */
419 static int32_t imd_write_multiple(IMDSocket* socket, const char* datptr, int32_t towrite)
420 {
421     int32_t leftcount, countwritten;
422
423
424     leftcount = towrite;
425     while (leftcount != 0)
426     {
427         if ((countwritten = imdsock_write(socket, datptr, leftcount)) <= 0)
428         {
429             if (errno == EINTR)
430             {
431                 countwritten = 0;
432             }
433             else
434             {
435                 return towrite - leftcount;
436             }
437         }
438         leftcount -= countwritten;
439         datptr += countwritten;
440     } /* end while */
441
442     return towrite - leftcount;
443 }
444
445
446 /*! \brief Handshake with IMD client. */
447 static int imd_handshake(IMDSocket* socket)
448 {
449     IMDHeader header;
450
451
452     fill_header(&header, IMD_HANDSHAKE, 1);
453     header.length = c_protocolVersion; /* client wants unswapped version */
454
455     return static_cast<int>(imd_write_multiple(socket, reinterpret_cast<char*>(&header), c_headerSize)
456                             != c_headerSize);
457 }
458
459
460 /*! \brief Send energies using the energy block and the send buffer. */
461 static int imd_send_energies(IMDSocket* socket, const IMDEnergyBlock* energies, char* buffer)
462 {
463     int32_t recsize;
464
465
466     recsize = c_headerSize + sizeof(IMDEnergyBlock);
467     fill_header(reinterpret_cast<IMDHeader*>(buffer), IMD_ENERGIES, 1);
468     memcpy(buffer + c_headerSize, energies, sizeof(IMDEnergyBlock));
469
470     return static_cast<int>(imd_write_multiple(socket, buffer, recsize) != recsize);
471 }
472
473
474 /*! \brief Receive IMD header from socket, sets the length and returns the IMD message. */
475 static IMDMessageType imd_recv_header(IMDSocket* socket, int32_t* length)
476 {
477     IMDHeader header;
478
479
480     if (imd_read_multiple(socket, reinterpret_cast<char*>(&header), c_headerSize) != c_headerSize)
481     {
482         return IMD_IOERROR;
483     }
484     swap_header(&header);
485     *length = header.length;
486
487     return static_cast<IMDMessageType>(header.type);
488 }
489
490
491 /*! \brief Receive force indices and forces.
492  *
493  * The number of forces was previously communicated via the header.
494  */
495 static bool imd_recv_mdcomm(IMDSocket* socket, int32_t nforces, int32_t* forcendx, float* forces)
496 {
497     /* reading indices */
498     int retsize  = sizeof(int32_t) * nforces;
499     int retbytes = imd_read_multiple(socket, reinterpret_cast<char*>(forcendx), retsize);
500     if (retbytes != retsize)
501     {
502         return false;
503     }
504
505     /* reading forces as float array */
506     retsize  = 3 * sizeof(float) * nforces;
507     retbytes = imd_read_multiple(socket, reinterpret_cast<char*>(forces), retsize);
508     return (retbytes == retsize);
509 }
510
511 /* GROMACS specific functions for the IMD implementation */
512 void write_IMDgroup_to_file(bool              bIMD,
513                             t_inputrec*       ir,
514                             const t_state*    state,
515                             const gmx_mtop_t* sys,
516                             int               nfile,
517                             const t_filenm    fnm[])
518 {
519     t_atoms IMDatoms;
520
521
522     if (bIMD)
523     {
524         IMDatoms = gmx_mtop_global_atoms(sys);
525         write_sto_conf_indexed(opt2fn("-imd", nfile, fnm), "IMDgroup", &IMDatoms, state->x.rvec_array(),
526                                state->v.rvec_array(), ir->ePBC, state->box, ir->imd->nat, ir->imd->ind);
527     }
528 }
529
530
531 void ImdSession::dd_make_local_IMD_atoms(const gmx_domdec_t* dd)
532 {
533     if (!impl_->sessionPossible)
534     {
535         return;
536     }
537
538     dd_make_local_group_indices(dd->ga2la, impl_->nat, impl_->ind, &impl_->nat_loc, &impl_->ind_loc,
539                                 &impl_->nalloc_loc, impl_->xa_ind);
540 }
541
542
543 /*! \brief Send positions from rvec.
544  *
545  * We need a separate send buffer and conversion to Angstrom.
546  */
547 static int imd_send_rvecs(IMDSocket* socket, int nat, rvec* x, char* buffer)
548 {
549     int32_t size;
550     int     i;
551     float   sendx[3];
552     int     tuplesize = 3 * sizeof(float);
553
554
555     /* Required size for the send buffer */
556     size = c_headerSize + 3 * sizeof(float) * nat;
557
558     /* Prepare header */
559     fill_header(reinterpret_cast<IMDHeader*>(buffer), IMD_FCOORDS, static_cast<int32_t>(nat));
560     for (i = 0; i < nat; i++)
561     {
562         sendx[0] = static_cast<float>(x[i][0]) * NM2A;
563         sendx[1] = static_cast<float>(x[i][1]) * NM2A;
564         sendx[2] = static_cast<float>(x[i][2]) * NM2A;
565         memcpy(buffer + c_headerSize + i * tuplesize, sendx, tuplesize);
566     }
567
568     return static_cast<int>(imd_write_multiple(socket, buffer, size) != size);
569 }
570
571
572 void ImdSession::Impl::prepareMasterSocket()
573 {
574     if (imdsock_winsockinit() == -1)
575     {
576         gmx_fatal(FARGS, "%s Failed to initialize winsock.\n", IMDstr);
577     }
578
579     /* The rest is identical, first create and bind a socket and set to listen then. */
580     GMX_LOG(mdlog.warning).appendTextFormatted("%s Setting up incoming socket.", IMDstr);
581     socket = imdsock_create();
582     if (!socket)
583     {
584         gmx_fatal(FARGS, "%s Failed to create socket.", IMDstr);
585     }
586
587     /* Bind to port */
588     int ret = imdsock_bind(socket, port);
589     if (ret)
590     {
591         gmx_fatal(FARGS, "%s binding socket to port %d failed with error %d.\n", IMDstr, port, ret);
592     }
593
594     if (imd_sock_listen(socket))
595     {
596         gmx_fatal(FARGS, "%s socket listen failed with error %d.\n", IMDstr, ret);
597     }
598
599     if (imdsock_getport(socket, &port))
600     {
601         gmx_fatal(FARGS, "%s Could not determine port number.\n", IMDstr);
602     }
603
604     GMX_LOG(mdlog.warning).appendTextFormatted("%s Listening for IMD connection on port %d.", IMDstr, port);
605 }
606
607
608 void ImdSession::Impl::disconnectClient()
609 {
610     /* Write out any buffered pulling data */
611     fflush(outf);
612
613     /* we first try to shut down the clientsocket */
614     imdsock_shutdown(clientsocket);
615     if (!imdsock_destroy(clientsocket))
616     {
617         GMX_LOG(mdlog.warning).appendTextFormatted("%s Failed to destroy socket.", IMDstr);
618     }
619
620     /* then we reset the IMD step to its default, and reset the connection boolean */
621     nstimd_new   = defaultNstImd;
622     clientsocket = nullptr;
623     bConnected   = false;
624 }
625
626
627 void ImdSession::Impl::issueFatalError(const char* msg)
628 {
629     GMX_LOG(mdlog.warning).appendTextFormatted("%s %s", IMDstr, msg);
630     disconnectClient();
631     GMX_LOG(mdlog.warning).appendTextFormatted("%s disconnected.", IMDstr);
632 }
633
634
635 bool ImdSession::Impl::tryConnect()
636 {
637     if (imdsock_tryread(socket, 0, 0) > 0)
638     {
639         /* yes, we got something, accept on clientsocket */
640         clientsocket = imdsock_accept(socket);
641         if (!clientsocket)
642         {
643             GMX_LOG(mdlog.warning)
644                     .appendTextFormatted("%s Accepting the connection on the socket failed.", IMDstr);
645             return false;
646         }
647
648         /* handshake with client */
649         if (imd_handshake(clientsocket))
650         {
651             issueFatalError("Connection failed.");
652             return false;
653         }
654
655         GMX_LOG(mdlog.warning)
656                 .appendTextFormatted("%s Connection established, checking if I got IMD_GO orders.", IMDstr);
657
658         /* Check if we get the proper "GO" command from client. */
659         if (imdsock_tryread(clientsocket, c_connectWait, 0) != 1
660             || imd_recv_header(clientsocket, &(length)) != IMD_GO)
661         {
662             issueFatalError("No IMD_GO order received. IMD connection failed.");
663         }
664
665         /* IMD connected */
666         bConnected = true;
667
668         return true;
669     }
670
671     return false;
672 }
673
674
675 void ImdSession::Impl::blockConnect()
676 {
677     /* do not wait for connection, when e.g. ctrl+c is pressed and we will terminate anyways. */
678     if (!(static_cast<int>(gmx_get_stop_condition()) == gmx_stop_cond_none))
679     {
680         return;
681     }
682
683     GMX_LOG(mdlog.warning)
684             .appendTextFormatted("%s Will wait until I have a connection and IMD_GO orders.", IMDstr);
685
686     /* while we have no clientsocket... 2nd part: we should still react on ctrl+c */
687     while ((!clientsocket) && (static_cast<int>(gmx_get_stop_condition()) == gmx_stop_cond_none))
688     {
689         tryConnect();
690         imd_sleep(c_loopWait);
691     }
692 }
693
694
695 void ImdSession::Impl::prepareVmdForces()
696 {
697     srenew((vmd_f_ind), vmd_nforces);
698     srenew((vmd_forces), 3 * vmd_nforces);
699 }
700
701
702 void ImdSession::Impl::readVmdForces()
703 {
704     /* the length of the previously received header tells us the nr of forces we will receive */
705     vmd_nforces = length;
706     /* prepare the arrays */
707     prepareVmdForces();
708     /* Now we read the forces... */
709     if (!(imd_recv_mdcomm(clientsocket, vmd_nforces, vmd_f_ind, vmd_forces)))
710     {
711         issueFatalError("Error while reading forces from remote. Disconnecting");
712     }
713 }
714
715
716 void ImdSession::Impl::prepareMDForces()
717 {
718     srenew((f_ind), nforces);
719     srenew((f), nforces);
720 }
721
722
723 void ImdSession::Impl::copyToMDForces()
724 {
725     int  i;
726     real conversion = CAL2JOULE * NM2A;
727
728
729     for (i = 0; i < nforces; i++)
730     {
731         /* Copy the indices, a copy is important because we may update the incoming forces
732          * whenever we receive new forces while the MD forces are only communicated upon
733          * IMD communication.*/
734         f_ind[i] = vmd_f_ind[i];
735
736         /* Convert to rvecs and do a proper unit conversion */
737         f[i][0] = vmd_forces[3 * i] * conversion;
738         f[i][1] = vmd_forces[3 * i + 1] * conversion;
739         f[i][2] = vmd_forces[3 * i + 2] * conversion;
740     }
741 }
742
743
744 /*! \brief Returns true if any component of the two rvecs differs. */
745 static inline bool rvecs_differ(const rvec v1, const rvec v2)
746 {
747     for (int i = 0; i < DIM; i++)
748     {
749         if (v1[i] != v2[i])
750         {
751             return true;
752         }
753     }
754
755     return false;
756 }
757
758 bool ImdSession::Impl::bForcesChanged() const
759 {
760     /* First, check whether the number of pulled atoms changed */
761     if (nforces != old_nforces)
762     {
763         return true;
764     }
765
766     /* Second, check whether any of the involved atoms changed */
767     for (int i = 0; i < nforces; i++)
768     {
769         if (f_ind[i] != old_f_ind[i])
770         {
771             return true;
772         }
773     }
774
775     /* Third, check whether all forces are the same */
776     for (int i = 0; i < nforces; i++)
777     {
778         if (rvecs_differ(f[i], old_forces[i]))
779         {
780             return true;
781         }
782     }
783
784     /* All old and new forces are identical! */
785     return false;
786 }
787
788
789 void ImdSession::Impl::keepOldValues()
790 {
791     old_nforces = nforces;
792
793     for (int i = 0; i < nforces; i++)
794     {
795         old_f_ind[i] = f_ind[i];
796         copy_rvec(f[i], old_forces[i]);
797     }
798 }
799
800
801 void ImdSession::Impl::outputForces(double time)
802 {
803     if (!bForcesChanged())
804     {
805         return;
806     }
807
808     /* Write time and total number of applied IMD forces */
809     fprintf(outf, "%14.6e%6d", time, nforces);
810
811     /* Write out the global atom indices of the pulled atoms and the forces itself,
812      * write out a force only if it has changed since the last output */
813     for (int i = 0; i < nforces; i++)
814     {
815         if (rvecs_differ(f[i], old_forces[i]))
816         {
817             fprintf(outf, "%9d", ind[f_ind[i]] + 1);
818             fprintf(outf, "%12.4e%12.4e%12.4e", f[i][0], f[i][1], f[i][2]);
819         }
820     }
821     fprintf(outf, "\n");
822
823     keepOldValues();
824 }
825
826
827 void ImdSession::Impl::syncNodes(const t_commrec* cr, double t)
828 {
829     /* Notify the other nodes whether we are still connected. */
830     if (PAR(cr))
831     {
832         block_bc(cr, bConnected);
833     }
834
835     /* ...if not connected, the job is done here. */
836     if (!bConnected)
837     {
838         return;
839     }
840
841     /* Let the other nodes know whether we got a new IMD synchronization frequency. */
842     if (PAR(cr))
843     {
844         block_bc(cr, nstimd_new);
845     }
846
847     /* Now we all set the (new) nstimd communication time step */
848     nstimd = nstimd_new;
849
850     /* We're done if we don't allow pulling at all */
851     if (!(bForceActivated))
852     {
853         return;
854     }
855
856     /* OK, let's check if we have received forces which we need to communicate
857      * to the other nodes */
858     int new_nforces = 0;
859     if (MASTER(cr))
860     {
861         if (bNewForces)
862         {
863             new_nforces = vmd_nforces;
864         }
865         /* make the "new_forces" negative, when we did not receive new ones */
866         else
867         {
868             new_nforces = vmd_nforces * -1;
869         }
870     }
871
872     /* make new_forces known to the clients */
873     if (PAR(cr))
874     {
875         block_bc(cr, new_nforces);
876     }
877
878     /* When new_natoms < 0 then we know that these are still the same forces
879      * so we don't communicate them, otherwise... */
880     if (new_nforces < 0)
881     {
882         return;
883     }
884
885     /* set local VMD and nforces */
886     vmd_nforces = new_nforces;
887     nforces     = vmd_nforces;
888
889     /* now everybody knows the number of forces in f_ind, so we can prepare
890      * the target arrays for indices and forces */
891     prepareMDForces();
892
893     /* we first update the MD forces on the master by converting the VMD forces */
894     if (MASTER(cr))
895     {
896         copyToMDForces();
897         /* We also write out forces on every update, so that we know which
898          * forces are applied for every step */
899         if (outf)
900         {
901             outputForces(t);
902         }
903     }
904
905     /* In parallel mode we communicate the to-be-applied forces to the other nodes */
906     if (PAR(cr))
907     {
908         nblock_bc(cr, nforces, f_ind);
909         nblock_bc(cr, nforces, f);
910     }
911
912     /* done communicating the forces, reset bNewForces */
913     bNewForces = false;
914 }
915
916
917 void ImdSession::Impl::readCommand()
918 {
919     bool IMDpaused = false;
920
921     while (clientsocket && (imdsock_tryread(clientsocket, 0, 0) > 0 || IMDpaused))
922     {
923         IMDMessageType itype = imd_recv_header(clientsocket, &(length));
924         /* let's see what we got: */
925         switch (itype)
926         {
927             /* IMD asks us to terminate the simulation, check if the user allowed this */
928             case IMD_KILL:
929                 if (bTerminatable)
930                 {
931                     GMX_LOG(mdlog.warning)
932                             .appendTextFormatted(
933                                     " %s Terminating connection and running simulation (if "
934                                     "supported by integrator).",
935                                     IMDstr);
936                     bTerminated = true;
937                     bWConnect   = false;
938                     gmx_set_stop_condition(gmx_stop_cond_next);
939                 }
940                 else
941                 {
942                     GMX_LOG(mdlog.warning)
943                             .appendTextFormatted(
944                                     " %s Set -imdterm command line switch to allow mdrun "
945                                     "termination from within IMD.",
946                                     IMDstr);
947                 }
948
949                 break;
950
951             /* the client doen't want to talk to us anymore */
952             case IMD_DISCONNECT:
953                 GMX_LOG(mdlog.warning).appendTextFormatted(" %s Disconnecting client.", IMDstr);
954                 disconnectClient();
955                 break;
956
957             /* we got new forces, read them and set bNewForces flag */
958             case IMD_MDCOMM:
959                 readVmdForces();
960                 bNewForces = true;
961                 break;
962
963             /* the client asks us to (un)pause the simulation. So we toggle the IMDpaused state */
964             case IMD_PAUSE:
965                 if (IMDpaused)
966                 {
967                     GMX_LOG(mdlog.warning).appendTextFormatted(" %s Un-pause command received.", IMDstr);
968                     IMDpaused = false;
969                 }
970                 else
971                 {
972                     GMX_LOG(mdlog.warning).appendTextFormatted(" %s Pause command received.", IMDstr);
973                     IMDpaused = true;
974                 }
975
976                 break;
977
978             /* the client sets a new transfer rate, if we get 0, we reset the rate
979              * to the default. VMD filters 0 however */
980             case IMD_TRATE:
981                 nstimd_new = (length > 0) ? length : defaultNstImd;
982                 GMX_LOG(mdlog.warning)
983                         .appendTextFormatted(" %s Update frequency will be set to %d.", IMDstr, nstimd_new);
984                 break;
985
986             /* Catch all rule for the remaining IMD types which we don't expect */
987             default:
988                 GMX_LOG(mdlog.warning)
989                         .appendTextFormatted(" %s Received unexpected %s.", IMDstr,
990                                              enum_name(static_cast<int>(itype), IMD_NR, eIMDType_names));
991                 issueFatalError("Terminating connection");
992                 break;
993         } /* end switch */
994     }     /* end while  */
995 }
996
997
998 void ImdSession::Impl::openOutputFile(const char*                 fn,
999                                       int                         nat_total,
1000                                       const gmx_output_env_t*     oenv,
1001                                       const gmx::StartingBehavior startingBehavior)
1002 {
1003     /* Open log file of applied IMD forces if requested */
1004     if (!fn || !oenv)
1005     {
1006         fprintf(stdout,
1007                 "%s For a log of the IMD pull forces explicitly specify '-if' on the command "
1008                 "line.\n"
1009                 "%s (Not possible with energy minimization.)\n",
1010                 IMDstr, IMDstr);
1011         return;
1012     }
1013
1014     /* If we append to an existing file, all the header information is already there */
1015     if (startingBehavior == StartingBehavior::RestartWithAppending)
1016     {
1017         outf = gmx_fio_fopen(fn, "a+");
1018     }
1019     else
1020     {
1021         outf = gmx_fio_fopen(fn, "w+");
1022         if (nat == nat_total)
1023         {
1024             fprintf(outf,
1025                     "# Note that you can select an IMD index group in the .mdp file if a subset of "
1026                     "the atoms suffices.\n");
1027         }
1028
1029         xvgr_header(outf, "IMD Pull Forces", "Time (ps)",
1030                     "# of Forces / Atom IDs / Forces (kJ/mol)", exvggtNONE, oenv);
1031
1032         fprintf(outf, "# Can display and manipulate %d (of a total of %d) atoms via IMD.\n", nat, nat_total);
1033         fprintf(outf, "# column 1    : time (ps)\n");
1034         fprintf(outf,
1035                 "# column 2    : total number of atoms feeling an IMD pulling force at that "
1036                 "time\n");
1037         fprintf(outf,
1038                 "# cols. 3.-6  : global atom number of pulled atom, x-force, y-force, z-force "
1039                 "(kJ/mol)\n");
1040         fprintf(outf,
1041                 "# then follow : atom-ID, f[x], f[y], f[z] for more atoms in case the force on "
1042                 "multiple atoms is changed simultaneously.\n");
1043         fprintf(outf,
1044                 "# Note that the force on any atom is always equal to the last value for that "
1045                 "atom-ID found in the data.\n");
1046         fflush(outf);
1047     }
1048
1049     /* To reduce the output file size we remember the old values and output only
1050      * when something changed */
1051     snew(old_f_ind, nat); /* One can never pull on more atoms */
1052     snew(old_forces, nat);
1053 }
1054
1055
1056 ImdSession::Impl::Impl(const MDLogger& mdlog) : mdlog(mdlog)
1057 {
1058     init_block(&mols);
1059 }
1060
1061 ImdSession::Impl::~Impl()
1062 {
1063     if (outf)
1064     {
1065         gmx_fio_fclose(outf);
1066     }
1067     done_block(&mols);
1068 }
1069
1070
1071 void ImdSession::Impl::prepareMoleculesInImdGroup(const gmx_mtop_t* top_global)
1072 {
1073     /* check whether index is sorted */
1074     for (int i = 0; i < nat - 1; i++)
1075     {
1076         if (ind[i] > ind[i + 1])
1077         {
1078             gmx_fatal(FARGS, "%s IMD index is not sorted. This is currently not supported.\n", IMDstr);
1079         }
1080     }
1081
1082     RangePartitioning gmols = gmx_mtop_molecules(*top_global);
1083     t_block           lmols;
1084     lmols.nr = 0;
1085     snew(lmols.index, gmols.numBlocks() + 1);
1086     lmols.index[0] = 0;
1087
1088     for (int i = 0; i < gmols.numBlocks(); i++)
1089     {
1090         auto mol   = gmols.block(i);
1091         int  count = 0;
1092         for (int ii = 0; ii < nat; ii++)
1093         {
1094             if (mol.isInRange(ind[ii]))
1095             {
1096                 count += 1;
1097             }
1098         }
1099         if (count > 0)
1100         {
1101             lmols.index[lmols.nr + 1] = lmols.index[lmols.nr] + count;
1102             lmols.nr += 1;
1103         }
1104     }
1105     srenew(lmols.index, lmols.nr + 1);
1106     lmols.nalloc_index = lmols.nr + 1;
1107     mols               = lmols;
1108 }
1109
1110
1111 /*! \brief Copied and modified from groupcoord.c shift_positions_group(). */
1112 static void shift_positions(const matrix box,
1113                             rvec         x[], /* The positions [0..nr] */
1114                             const ivec   is,  /* The shift [0..nr] */
1115                             int          nr)           /* The number of positions */
1116 {
1117     int i, tx, ty, tz;
1118
1119     /* Loop over the group's atoms */
1120     if (TRICLINIC(box))
1121     {
1122         for (i = 0; i < nr; i++)
1123         {
1124             tx = is[XX];
1125             ty = is[YY];
1126             tz = is[ZZ];
1127
1128             x[i][XX] = x[i][XX] - tx * box[XX][XX] - ty * box[YY][XX] - tz * box[ZZ][XX];
1129             x[i][YY] = x[i][YY] - ty * box[YY][YY] - tz * box[ZZ][YY];
1130             x[i][ZZ] = x[i][ZZ] - tz * box[ZZ][ZZ];
1131         }
1132     }
1133     else
1134     {
1135         for (i = 0; i < nr; i++)
1136         {
1137             tx = is[XX];
1138             ty = is[YY];
1139             tz = is[ZZ];
1140
1141             x[i][XX] = x[i][XX] - tx * box[XX][XX];
1142             x[i][YY] = x[i][YY] - ty * box[YY][YY];
1143             x[i][ZZ] = x[i][ZZ] - tz * box[ZZ][ZZ];
1144         }
1145     }
1146 }
1147
1148
1149 void ImdSession::Impl::removeMolecularShifts(const matrix box)
1150 {
1151     /* for each molecule also present in IMD group */
1152     for (int i = 0; i < mols.nr; i++)
1153     {
1154         /* first we determine the minimum and maximum shifts for each molecule */
1155
1156         ivec largest, smallest, shift;
1157         clear_ivec(largest);
1158         clear_ivec(smallest);
1159         clear_ivec(shift);
1160
1161         copy_ivec(xa_shifts[mols.index[i]], largest);
1162         copy_ivec(xa_shifts[mols.index[i]], smallest);
1163
1164         for (int ii = mols.index[i] + 1; ii < mols.index[i + 1]; ii++)
1165         {
1166             if (xa_shifts[ii][XX] > largest[XX])
1167             {
1168                 largest[XX] = xa_shifts[ii][XX];
1169             }
1170             if (xa_shifts[ii][XX] < smallest[XX])
1171             {
1172                 smallest[XX] = xa_shifts[ii][XX];
1173             }
1174
1175             if (xa_shifts[ii][YY] > largest[YY])
1176             {
1177                 largest[YY] = xa_shifts[ii][YY];
1178             }
1179             if (xa_shifts[ii][YY] < smallest[YY])
1180             {
1181                 smallest[YY] = xa_shifts[ii][YY];
1182             }
1183
1184             if (xa_shifts[ii][ZZ] > largest[ZZ])
1185             {
1186                 largest[ZZ] = xa_shifts[ii][ZZ];
1187             }
1188             if (xa_shifts[ii][ZZ] < smallest[ZZ])
1189             {
1190                 smallest[ZZ] = xa_shifts[ii][ZZ];
1191             }
1192         }
1193
1194         /* check if we what we can subtract/add to the positions
1195          * to put them back into the central box */
1196         if (smallest[XX] > 0)
1197         {
1198             shift[XX] = smallest[XX];
1199         }
1200         if (smallest[YY] > 0)
1201         {
1202             shift[YY] = smallest[YY];
1203         }
1204         if (smallest[ZZ] > 0)
1205         {
1206             shift[ZZ] = smallest[ZZ];
1207         }
1208
1209         if (largest[XX] < 0)
1210         {
1211             shift[XX] = largest[XX];
1212         }
1213         if (largest[YY] < 0)
1214         {
1215             shift[YY] = largest[YY];
1216         }
1217         if (largest[ZZ] < 0)
1218         {
1219             shift[ZZ] = largest[ZZ];
1220         }
1221
1222         /* is there a shift at all? */
1223         if ((shift[XX]) || (shift[YY]) || (shift[ZZ]))
1224         {
1225             int molsize = mols.index[i + 1] - mols.index[i];
1226             /* shift the positions */
1227             shift_positions(box, &(xa[mols.index[i]]), shift, molsize);
1228         }
1229     }
1230 }
1231
1232
1233 void ImdSession::Impl::prepareForPositionAssembly(const t_commrec* cr, const rvec x[])
1234 {
1235     snew(xa, nat);
1236     snew(xa_ind, nat);
1237     snew(xa_shifts, nat);
1238     snew(xa_eshifts, nat);
1239     snew(xa_old, nat);
1240
1241     /* Save the original (whole) set of positions such that later the
1242      * molecule can always be made whole again */
1243     if (MASTER(cr))
1244     {
1245         for (int i = 0; i < nat; i++)
1246         {
1247             int ii = ind[i];
1248             copy_rvec(x[ii], xa_old[i]);
1249         }
1250     }
1251
1252     if (!PAR(cr))
1253     {
1254         nat_loc = nat;
1255         ind_loc = ind;
1256
1257         /* xa_ind[i] needs to be set to i for serial runs */
1258         for (int i = 0; i < nat; i++)
1259         {
1260             xa_ind[i] = i;
1261         }
1262     }
1263
1264     /* Communicate initial coordinates xa_old to all processes */
1265     if (PAR(cr))
1266     {
1267         gmx_bcast(nat * sizeof(xa_old[0]), xa_old, cr);
1268     }
1269 }
1270
1271
1272 /*! \brief Check for non-working integrator / parallel options. */
1273 static void imd_check_integrator_parallel(const t_inputrec* ir, const t_commrec* cr)
1274 {
1275     if (PAR(cr))
1276     {
1277         if (((ir->eI) == eiSteep) || ((ir->eI) == eiCG) || ((ir->eI) == eiLBFGS) || ((ir->eI) == eiNM))
1278         {
1279             gmx_fatal(FARGS,
1280                       "%s Energy minimization via steep, CG, lbfgs and nm in parallel is currently "
1281                       "not supported by IMD.\n",
1282                       IMDstr);
1283         }
1284     }
1285 }
1286
1287 std::unique_ptr<ImdSession> makeImdSession(const t_inputrec*           ir,
1288                                            const t_commrec*            cr,
1289                                            gmx_wallcycle*              wcycle,
1290                                            gmx_enerdata_t*             enerd,
1291                                            const gmx_multisim_t*       ms,
1292                                            const gmx_mtop_t*           top_global,
1293                                            const MDLogger&             mdlog,
1294                                            const rvec                  x[],
1295                                            int                         nfile,
1296                                            const t_filenm              fnm[],
1297                                            const gmx_output_env_t*     oenv,
1298                                            const ImdOptions&           options,
1299                                            const gmx::StartingBehavior startingBehavior)
1300 {
1301     std::unique_ptr<ImdSession> session(new ImdSession(mdlog));
1302     auto                        impl = session->impl_.get();
1303
1304     /* We will allow IMD sessions only if supported by the binary and
1305        explicitly enabled in the .tpr file */
1306     if (!GMX_IMD || !ir->bIMD)
1307     {
1308         return session;
1309     }
1310
1311     // TODO As IMD is intended for interactivity, and the .tpr file
1312     // opted in for that, it is acceptable to write more terminal
1313     // output than in a typical simulation. However, all the GMX_LOG
1314     // statements below should go to both the log file and to the
1315     // terminal. This is probably be implemented by adding a logging
1316     // stream named like ImdInfo, to separate it from warning and to
1317     // send it to both destinations.
1318
1319     if (EI_DYNAMICS(ir->eI))
1320     {
1321         impl->defaultNstImd = ir->nstcalcenergy;
1322     }
1323     else if (EI_ENERGY_MINIMIZATION(ir->eI))
1324     {
1325         impl->defaultNstImd = 1;
1326     }
1327     else
1328     {
1329         GMX_LOG(mdlog.warning)
1330                 .appendTextFormatted(
1331                         "%s Integrator '%s' is not supported for Interactive Molecular Dynamics, "
1332                         "running normally instead",
1333                         IMDstr, ei_names[ir->eI]);
1334         return session;
1335     }
1336     if (isMultiSim(ms))
1337     {
1338         GMX_LOG(mdlog.warning)
1339                 .appendTextFormatted(
1340                         "%s Cannot use IMD for multiple simulations or replica exchange, running "
1341                         "normally instead",
1342                         IMDstr);
1343         return session;
1344     }
1345
1346     bool createSession = false;
1347     /* It seems we have a .tpr file that defines an IMD group and thus allows IMD connections.
1348      * Check whether we can actually provide the IMD functionality for this setting: */
1349     if (MASTER(cr))
1350     {
1351         /* Check whether IMD was enabled by one of the command line switches: */
1352         if (options.wait || options.terminatable || options.pull)
1353         {
1354             GMX_LOG(mdlog.warning)
1355                     .appendTextFormatted(
1356                             "%s Enabled. This simulation will accept incoming IMD connections.", IMDstr);
1357             createSession = true;
1358         }
1359         else
1360         {
1361             GMX_LOG(mdlog.warning)
1362                     .appendTextFormatted(
1363                             "%s None of the -imd switches was used.\n"
1364                             "%s This run will not accept incoming IMD connections",
1365                             IMDstr, IMDstr);
1366         }
1367     } /* end master only */
1368
1369     /* Let the other nodes know whether we want IMD */
1370     if (PAR(cr))
1371     {
1372         block_bc(cr, createSession);
1373     }
1374
1375     /*... if not we are done.*/
1376     if (!createSession)
1377     {
1378         return session;
1379     }
1380
1381
1382     /* check if we're using a sane integrator / parallel combination */
1383     imd_check_integrator_parallel(ir, cr);
1384
1385
1386     /*
1387      *****************************************************
1388      * From here on we assume that IMD is turned on      *
1389      *****************************************************
1390      */
1391
1392     int nat_total = top_global->natoms;
1393
1394     /* Initialize IMD session. If we read in a pre-IMD .tpr file, ir->imd->nat
1395      * will be zero. For those cases we transfer _all_ atomic positions */
1396     impl->sessionPossible = true;
1397     impl->nat             = ir->imd->nat > 0 ? ir->imd->nat : nat_total;
1398     if (options.port >= 1)
1399     {
1400         impl->port = options.port;
1401     }
1402     impl->cr     = cr;
1403     impl->wcycle = wcycle;
1404     impl->enerd  = enerd;
1405
1406     /* We might need to open an output file for IMD forces data */
1407     if (MASTER(cr))
1408     {
1409         impl->openOutputFile(opt2fn("-if", nfile, fnm), nat_total, oenv, startingBehavior);
1410     }
1411
1412     /* Make sure that we operate with a valid atom index array for the IMD atoms */
1413     if (ir->imd->nat > 0)
1414     {
1415         /* Point to the user-supplied array of atom numbers */
1416         impl->ind = ir->imd->ind;
1417     }
1418     else
1419     {
1420         /* Make a dummy (ind[i] = i) array of all atoms */
1421         snew(impl->ind, nat_total);
1422         for (int i = 0; i < nat_total; i++)
1423         {
1424             impl->ind[i] = i;
1425         }
1426     }
1427
1428     /* read environment on master and prepare socket for incoming connections */
1429     if (MASTER(cr))
1430     {
1431         /* we allocate memory for our IMD energy structure */
1432         int32_t recsize = c_headerSize + sizeof(IMDEnergyBlock);
1433         snew(impl->energysendbuf, recsize);
1434
1435         /* Shall we wait for a connection? */
1436         if (options.wait)
1437         {
1438             impl->bWConnect = true;
1439             GMX_LOG(mdlog.warning)
1440                     .appendTextFormatted(
1441                             "%s Pausing simulation while no IMD connection present (-imdwait).", IMDstr);
1442         }
1443
1444         /* Will the IMD clients be able to terminate the simulation? */
1445         if (options.terminatable)
1446         {
1447             impl->bTerminatable = true;
1448             GMX_LOG(mdlog.warning)
1449                     .appendTextFormatted(
1450                             "%s Allow termination of the simulation from IMD client (-imdterm).", IMDstr);
1451         }
1452
1453         /* Is pulling from IMD client allowed? */
1454         if (options.pull)
1455         {
1456             impl->bForceActivated = true;
1457             GMX_LOG(mdlog.warning)
1458                     .appendTextFormatted("%s Pulling from IMD remote is enabled (-imdpull).", IMDstr);
1459         }
1460
1461         /* Initialize send buffers with constant size */
1462         snew(impl->sendxbuf, impl->nat);
1463         snew(impl->energies, 1);
1464         int32_t bufxsize = c_headerSize + 3 * sizeof(float) * impl->nat;
1465         snew(impl->coordsendbuf, bufxsize);
1466     }
1467
1468     /* do we allow interactive pulling? If so let the other nodes know. */
1469     if (PAR(cr))
1470     {
1471         block_bc(cr, impl->bForceActivated);
1472     }
1473
1474     /* setup the listening socket on master process */
1475     if (MASTER(cr))
1476     {
1477         GMX_LOG(mdlog.warning).appendTextFormatted("%s Setting port for connection requests to %d.", IMDstr, impl->port);
1478         impl->prepareMasterSocket();
1479         /* Wait until we have a connection if specified before */
1480         if (impl->bWConnect)
1481         {
1482             impl->blockConnect();
1483         }
1484         else
1485         {
1486             GMX_LOG(mdlog.warning).appendTextFormatted("%s -imdwait not set, starting simulation.", IMDstr);
1487         }
1488     }
1489     /* Let the other nodes know whether we are connected */
1490     impl->syncNodes(cr, 0);
1491
1492     /* Initialize arrays used to assemble the positions from the other nodes */
1493     impl->prepareForPositionAssembly(cr, x);
1494
1495     /* Initialize molecule blocks to make them whole later...*/
1496     if (MASTER(cr))
1497     {
1498         impl->prepareMoleculesInImdGroup(top_global);
1499     }
1500
1501     return session;
1502 }
1503
1504
1505 bool ImdSession::Impl::run(int64_t step, bool bNS, const matrix box, const rvec x[], double t)
1506 {
1507     /* IMD at all? */
1508     if (!sessionPossible)
1509     {
1510         return false;
1511     }
1512
1513     wallcycle_start(wcycle, ewcIMD);
1514
1515     /* read command from client and check if new incoming connection */
1516     if (MASTER(cr))
1517     {
1518         /* If not already connected, check for new connections */
1519         if (!clientsocket)
1520         {
1521             if (bWConnect)
1522             {
1523                 blockConnect();
1524             }
1525             else
1526             {
1527                 tryConnect();
1528             }
1529         }
1530
1531         /* Let's see if we have new IMD messages for us */
1532         if (clientsocket)
1533         {
1534             readCommand();
1535         }
1536     }
1537
1538     /* is this an IMD communication step? */
1539     bool imdstep = do_per_step(step, nstimd);
1540
1541     /* OK so this is an IMD step ... */
1542     if (imdstep)
1543     {
1544         /* First we sync all nodes to let everybody know whether we are connected to VMD */
1545         syncNodes(cr, t);
1546     }
1547
1548     /* If a client is connected, we collect the positions
1549      * and put molecules back into the box before transfer */
1550     if ((imdstep && bConnected) || bNS) /* independent of imdstep, we communicate positions at each NS step */
1551     {
1552         /* Transfer the IMD positions to the master node. Every node contributes
1553          * its local positions x and stores them in the assembled xa array. */
1554         communicate_group_positions(cr, xa, xa_shifts, xa_eshifts, true, x, nat, nat_loc, ind_loc,
1555                                     xa_ind, xa_old, box);
1556
1557         /* If connected and master -> remove shifts */
1558         if ((imdstep && bConnected) && MASTER(cr))
1559         {
1560             removeMolecularShifts(box);
1561         }
1562     }
1563
1564     wallcycle_stop(wcycle, ewcIMD);
1565
1566     return imdstep;
1567 }
1568
1569 bool ImdSession::run(int64_t step, bool bNS, const matrix box, const rvec x[], double t)
1570 {
1571     return impl_->run(step, bNS, box, x, t);
1572 }
1573
1574 void ImdSession::fillEnergyRecord(int64_t step, bool bHaveNewEnergies)
1575 {
1576     if (!impl_->sessionPossible || !impl_->clientsocket)
1577     {
1578         return;
1579     }
1580
1581     IMDEnergyBlock* ene = impl_->energies;
1582
1583     ene->tstep = step;
1584
1585     /* In MPI-parallel simulations the energies are not accessible a at every time step.
1586      * We update them if we have new values, otherwise, the energy values from the
1587      * last global communication step are still on display in the viewer. */
1588     if (bHaveNewEnergies)
1589     {
1590         ene->T_abs   = static_cast<float>(impl_->enerd->term[F_TEMP]);
1591         ene->E_pot   = static_cast<float>(impl_->enerd->term[F_EPOT]);
1592         ene->E_tot   = static_cast<float>(impl_->enerd->term[F_ETOT]);
1593         ene->E_bond  = static_cast<float>(impl_->enerd->term[F_BONDS]);
1594         ene->E_angle = static_cast<float>(impl_->enerd->term[F_ANGLES]);
1595         ene->E_dihe  = static_cast<float>(impl_->enerd->term[F_PDIHS]);
1596         ene->E_impr  = static_cast<float>(impl_->enerd->term[F_IDIHS]);
1597         ene->E_vdw   = static_cast<float>(impl_->enerd->term[F_LJ]);
1598         ene->E_coul  = static_cast<float>(impl_->enerd->term[F_COUL_SR]);
1599     }
1600 }
1601
1602
1603 void ImdSession::sendPositionsAndEnergies()
1604 {
1605     if (!impl_->sessionPossible || !impl_->clientsocket)
1606     {
1607         return;
1608     }
1609
1610     if (imd_send_energies(impl_->clientsocket, impl_->energies, impl_->energysendbuf))
1611     {
1612         impl_->issueFatalError("Error sending updated energies. Disconnecting client.");
1613     }
1614
1615     if (imd_send_rvecs(impl_->clientsocket, impl_->nat, impl_->xa, impl_->coordsendbuf))
1616     {
1617         impl_->issueFatalError("Error sending updated positions. Disconnecting client.");
1618     }
1619 }
1620
1621
1622 void ImdSession::updateEnergyRecordAndSendPositionsAndEnergies(bool bIMDstep, int64_t step, bool bHaveNewEnergies)
1623 {
1624     if (!impl_->sessionPossible)
1625     {
1626         return;
1627     }
1628
1629     wallcycle_start(impl_->wcycle, ewcIMD);
1630
1631     /* Update time step for IMD and prepare IMD energy record if we have new energies. */
1632     fillEnergyRecord(step, bHaveNewEnergies);
1633
1634     if (bIMDstep)
1635     {
1636         /* Send positions and energies to VMD client via IMD */
1637         sendPositionsAndEnergies();
1638     }
1639
1640     wallcycle_stop(impl_->wcycle, ewcIMD);
1641 }
1642
1643 void ImdSession::applyForces(rvec* f)
1644 {
1645     if (!impl_->sessionPossible || !impl_->bForceActivated)
1646     {
1647         return;
1648     }
1649
1650     wallcycle_start(impl_->wcycle, ewcIMD);
1651
1652     for (int i = 0; i < impl_->nforces; i++)
1653     {
1654         /* j are the indices in the "System group".*/
1655         int j = impl_->ind[impl_->f_ind[i]];
1656
1657         /* check if this is a local atom and find out locndx */
1658         const int*       locndx;
1659         const t_commrec* cr = impl_->cr;
1660         if (PAR(cr) && (locndx = cr->dd->ga2la->findHome(j)))
1661         {
1662             j = *locndx;
1663         }
1664
1665         rvec_inc(f[j], impl_->f[i]);
1666     }
1667
1668     wallcycle_stop(impl_->wcycle, ewcIMD);
1669 }
1670
1671 ImdSession::ImdSession(const MDLogger& mdlog) : impl_(new Impl(mdlog)) {}
1672
1673 ImdSession::~ImdSession() = default;
1674
1675 } // namespace gmx