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