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