9c84d7718b6445cbe7ab4206f29597d2829ce2f7
[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/commrec.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, const rvec x[]);
207     /*! \brief Interact with any connected VMD session */
208     bool run(int64_t step, bool bNS, const matrix box, const rvec x[], 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(MdModulesNotifier* /* notifier */) override {}
330     void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) 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), "IMDgroup", &IMDatoms,
530                                state->x.rvec_array(), state->v.rvec_array(), ir->pbcType,
531                                state->box, ir->imd->nat, ir->imd->ind);
532     }
533 }
534
535
536 void ImdSession::dd_make_local_IMD_atoms(const gmx_domdec_t* dd)
537 {
538     if (!impl_->sessionPossible)
539     {
540         return;
541     }
542
543     dd_make_local_group_indices(dd->ga2la, impl_->nat, impl_->ind, &impl_->nat_loc, &impl_->ind_loc,
544                                 &impl_->nalloc_loc, impl_->xa_ind);
545 }
546
547
548 /*! \brief Send positions from rvec.
549  *
550  * We need a separate send buffer and conversion to Angstrom.
551  */
552 static int imd_send_rvecs(IMDSocket* socket, int nat, rvec* x, char* buffer)
553 {
554     int32_t size;
555     int     i;
556     float   sendx[3];
557     int     tuplesize = 3 * sizeof(float);
558
559
560     /* Required size for the send buffer */
561     size = c_headerSize + 3 * sizeof(float) * nat;
562
563     /* Prepare header */
564     fill_header(reinterpret_cast<IMDHeader*>(buffer), IMD_FCOORDS, static_cast<int32_t>(nat));
565     for (i = 0; i < nat; i++)
566     {
567         sendx[0] = static_cast<float>(x[i][0]) * NM2A;
568         sendx[1] = static_cast<float>(x[i][1]) * NM2A;
569         sendx[2] = static_cast<float>(x[i][2]) * NM2A;
570         memcpy(buffer + c_headerSize + i * tuplesize, sendx, tuplesize);
571     }
572
573     return static_cast<int>(imd_write_multiple(socket, buffer, size) != size);
574 }
575
576
577 void ImdSession::Impl::prepareMasterSocket()
578 {
579     if (imdsock_winsockinit() == -1)
580     {
581         gmx_fatal(FARGS, "%s Failed to initialize winsock.\n", IMDstr);
582     }
583
584     /* The rest is identical, first create and bind a socket and set to listen then. */
585     GMX_LOG(mdlog.warning).appendTextFormatted("%s Setting up incoming socket.", IMDstr);
586     socket = imdsock_create();
587     if (!socket)
588     {
589         gmx_fatal(FARGS, "%s Failed to create socket.", IMDstr);
590     }
591
592     /* Bind to port */
593     int ret = imdsock_bind(socket, port);
594     if (ret)
595     {
596         gmx_fatal(FARGS, "%s binding socket to port %d failed with error %d.\n", IMDstr, port, ret);
597     }
598
599     if (imd_sock_listen(socket))
600     {
601         gmx_fatal(FARGS, "%s socket listen failed with error %d.\n", IMDstr, ret);
602     }
603
604     if (imdsock_getport(socket, &port))
605     {
606         gmx_fatal(FARGS, "%s Could not determine port number.\n", IMDstr);
607     }
608
609     GMX_LOG(mdlog.warning).appendTextFormatted("%s Listening for IMD connection on port %d.", IMDstr, port);
610 }
611
612
613 void ImdSession::Impl::disconnectClient()
614 {
615     /* Write out any buffered pulling data */
616     fflush(outf);
617
618     /* we first try to shut down the clientsocket */
619     imdsock_shutdown(clientsocket);
620     if (!imdsock_destroy(clientsocket))
621     {
622         GMX_LOG(mdlog.warning).appendTextFormatted("%s Failed to destroy socket.", IMDstr);
623     }
624
625     /* then we reset the IMD step to its default, and reset the connection boolean */
626     nstimd_new   = defaultNstImd;
627     clientsocket = nullptr;
628     bConnected   = false;
629 }
630
631
632 void ImdSession::Impl::issueFatalError(const char* msg)
633 {
634     GMX_LOG(mdlog.warning).appendTextFormatted("%s %s", IMDstr, msg);
635     disconnectClient();
636     GMX_LOG(mdlog.warning).appendTextFormatted("%s disconnected.", IMDstr);
637 }
638
639
640 bool ImdSession::Impl::tryConnect()
641 {
642     if (imdsock_tryread(socket, 0, 0) > 0)
643     {
644         /* yes, we got something, accept on clientsocket */
645         clientsocket = imdsock_accept(socket);
646         if (!clientsocket)
647         {
648             GMX_LOG(mdlog.warning)
649                     .appendTextFormatted("%s Accepting the connection on the socket failed.", IMDstr);
650             return false;
651         }
652
653         /* handshake with client */
654         if (imd_handshake(clientsocket))
655         {
656             issueFatalError("Connection failed.");
657             return false;
658         }
659
660         GMX_LOG(mdlog.warning)
661                 .appendTextFormatted("%s Connection established, checking if I got IMD_GO orders.", IMDstr);
662
663         /* Check if we get the proper "GO" command from client. */
664         if (imdsock_tryread(clientsocket, c_connectWait, 0) != 1
665             || imd_recv_header(clientsocket, &(length)) != IMD_GO)
666         {
667             issueFatalError("No IMD_GO order received. IMD connection failed.");
668         }
669
670         /* IMD connected */
671         bConnected = true;
672
673         return true;
674     }
675
676     return false;
677 }
678
679
680 void ImdSession::Impl::blockConnect()
681 {
682     /* do not wait for connection, when e.g. ctrl+c is pressed and we will terminate anyways. */
683     if (!(static_cast<int>(gmx_get_stop_condition()) == gmx_stop_cond_none))
684     {
685         return;
686     }
687
688     GMX_LOG(mdlog.warning)
689             .appendTextFormatted("%s Will wait until I have a connection and IMD_GO orders.", IMDstr);
690
691     /* while we have no clientsocket... 2nd part: we should still react on ctrl+c */
692     while ((!clientsocket) && (static_cast<int>(gmx_get_stop_condition()) == gmx_stop_cond_none))
693     {
694         tryConnect();
695         imd_sleep(c_loopWait);
696     }
697 }
698
699
700 void ImdSession::Impl::prepareVmdForces()
701 {
702     srenew((vmd_f_ind), vmd_nforces);
703     srenew((vmd_forces), 3 * vmd_nforces);
704 }
705
706
707 void ImdSession::Impl::readVmdForces()
708 {
709     /* the length of the previously received header tells us the nr of forces we will receive */
710     vmd_nforces = length;
711     /* prepare the arrays */
712     prepareVmdForces();
713     /* Now we read the forces... */
714     if (!(imd_recv_mdcomm(clientsocket, vmd_nforces, vmd_f_ind, vmd_forces)))
715     {
716         issueFatalError("Error while reading forces from remote. Disconnecting");
717     }
718 }
719
720
721 void ImdSession::Impl::prepareMDForces()
722 {
723     srenew((f_ind), nforces);
724     srenew((f), nforces);
725 }
726
727
728 void ImdSession::Impl::copyToMDForces()
729 {
730     int  i;
731     real conversion = CAL2JOULE * NM2A;
732
733
734     for (i = 0; i < nforces; i++)
735     {
736         /* Copy the indices, a copy is important because we may update the incoming forces
737          * whenever we receive new forces while the MD forces are only communicated upon
738          * IMD communication.*/
739         f_ind[i] = vmd_f_ind[i];
740
741         /* Convert to rvecs and do a proper unit conversion */
742         f[i][0] = vmd_forces[3 * i] * conversion;
743         f[i][1] = vmd_forces[3 * i + 1] * conversion;
744         f[i][2] = vmd_forces[3 * i + 2] * conversion;
745     }
746 }
747
748
749 /*! \brief Returns true if any component of the two rvecs differs. */
750 static inline bool rvecs_differ(const rvec v1, const rvec v2)
751 {
752     for (int i = 0; i < DIM; i++)
753     {
754         if (v1[i] != v2[i])
755         {
756             return true;
757         }
758     }
759
760     return false;
761 }
762
763 bool ImdSession::Impl::bForcesChanged() const
764 {
765     /* First, check whether the number of pulled atoms changed */
766     if (nforces != old_nforces)
767     {
768         return true;
769     }
770
771     /* Second, check whether any of the involved atoms changed */
772     for (int i = 0; i < nforces; i++)
773     {
774         if (f_ind[i] != old_f_ind[i])
775         {
776             return true;
777         }
778     }
779
780     /* Third, check whether all forces are the same */
781     for (int i = 0; i < nforces; i++)
782     {
783         if (rvecs_differ(f[i], old_forces[i]))
784         {
785             return true;
786         }
787     }
788
789     /* All old and new forces are identical! */
790     return false;
791 }
792
793
794 void ImdSession::Impl::keepOldValues()
795 {
796     old_nforces = nforces;
797
798     for (int i = 0; i < nforces; i++)
799     {
800         old_f_ind[i] = f_ind[i];
801         copy_rvec(f[i], old_forces[i]);
802     }
803 }
804
805
806 void ImdSession::Impl::outputForces(double time)
807 {
808     if (!bForcesChanged())
809     {
810         return;
811     }
812
813     /* Write time and total number of applied IMD forces */
814     fprintf(outf, "%14.6e%6d", time, nforces);
815
816     /* Write out the global atom indices of the pulled atoms and the forces itself,
817      * write out a force only if it has changed since the last output */
818     for (int i = 0; i < nforces; i++)
819     {
820         if (rvecs_differ(f[i], old_forces[i]))
821         {
822             fprintf(outf, "%9d", ind[f_ind[i]] + 1);
823             fprintf(outf, "%12.4e%12.4e%12.4e", f[i][0], f[i][1], f[i][2]);
824         }
825     }
826     fprintf(outf, "\n");
827
828     keepOldValues();
829 }
830
831
832 void ImdSession::Impl::syncNodes(const t_commrec* cr, double t)
833 {
834     /* Notify the other nodes whether we are still connected. */
835     if (PAR(cr))
836     {
837         block_bc(cr->mpi_comm_mygroup, bConnected);
838     }
839
840     /* ...if not connected, the job is done here. */
841     if (!bConnected)
842     {
843         return;
844     }
845
846     /* Let the other nodes know whether we got a new IMD synchronization frequency. */
847     if (PAR(cr))
848     {
849         block_bc(cr->mpi_comm_mygroup, nstimd_new);
850     }
851
852     /* Now we all set the (new) nstimd communication time step */
853     nstimd = nstimd_new;
854
855     /* We're done if we don't allow pulling at all */
856     if (!(bForceActivated))
857     {
858         return;
859     }
860
861     /* OK, let's check if we have received forces which we need to communicate
862      * to the other nodes */
863     int new_nforces = 0;
864     if (MASTER(cr))
865     {
866         if (bNewForces)
867         {
868             new_nforces = vmd_nforces;
869         }
870         /* make the "new_forces" negative, when we did not receive new ones */
871         else
872         {
873             new_nforces = vmd_nforces * -1;
874         }
875     }
876
877     /* make new_forces known to the clients */
878     if (PAR(cr))
879     {
880         block_bc(cr->mpi_comm_mygroup, new_nforces);
881     }
882
883     /* When new_natoms < 0 then we know that these are still the same forces
884      * so we don't communicate them, otherwise... */
885     if (new_nforces < 0)
886     {
887         return;
888     }
889
890     /* set local VMD and nforces */
891     vmd_nforces = new_nforces;
892     nforces     = vmd_nforces;
893
894     /* now everybody knows the number of forces in f_ind, so we can prepare
895      * the target arrays for indices and forces */
896     prepareMDForces();
897
898     /* we first update the MD forces on the master by converting the VMD forces */
899     if (MASTER(cr))
900     {
901         copyToMDForces();
902         /* We also write out forces on every update, so that we know which
903          * forces are applied for every step */
904         if (outf)
905         {
906             outputForces(t);
907         }
908     }
909
910     /* In parallel mode we communicate the to-be-applied forces to the other nodes */
911     if (PAR(cr))
912     {
913         nblock_bc(cr->mpi_comm_mygroup, nforces, f_ind);
914         nblock_bc(cr->mpi_comm_mygroup, nforces, f);
915     }
916
917     /* done communicating the forces, reset bNewForces */
918     bNewForces = false;
919 }
920
921
922 void ImdSession::Impl::readCommand()
923 {
924     bool IMDpaused = false;
925
926     while (clientsocket && (imdsock_tryread(clientsocket, 0, 0) > 0 || IMDpaused))
927     {
928         IMDMessageType itype = imd_recv_header(clientsocket, &(length));
929         /* let's see what we got: */
930         switch (itype)
931         {
932             /* IMD asks us to terminate the simulation, check if the user allowed this */
933             case IMD_KILL:
934                 if (bTerminatable)
935                 {
936                     GMX_LOG(mdlog.warning)
937                             .appendTextFormatted(
938                                     " %s Terminating connection and running simulation (if "
939                                     "supported by integrator).",
940                                     IMDstr);
941                     bTerminated = true;
942                     bWConnect   = false;
943                     gmx_set_stop_condition(gmx_stop_cond_next);
944                 }
945                 else
946                 {
947                     GMX_LOG(mdlog.warning)
948                             .appendTextFormatted(
949                                     " %s Set -imdterm command line switch to allow mdrun "
950                                     "termination from within IMD.",
951                                     IMDstr);
952                 }
953
954                 break;
955
956             /* the client doen't want to talk to us anymore */
957             case IMD_DISCONNECT:
958                 GMX_LOG(mdlog.warning).appendTextFormatted(" %s Disconnecting client.", IMDstr);
959                 disconnectClient();
960                 break;
961
962             /* we got new forces, read them and set bNewForces flag */
963             case IMD_MDCOMM:
964                 readVmdForces();
965                 bNewForces = true;
966                 break;
967
968             /* the client asks us to (un)pause the simulation. So we toggle the IMDpaused state */
969             case IMD_PAUSE:
970                 if (IMDpaused)
971                 {
972                     GMX_LOG(mdlog.warning).appendTextFormatted(" %s Un-pause command received.", IMDstr);
973                     IMDpaused = false;
974                 }
975                 else
976                 {
977                     GMX_LOG(mdlog.warning).appendTextFormatted(" %s Pause command received.", IMDstr);
978                     IMDpaused = true;
979                 }
980
981                 break;
982
983             /* the client sets a new transfer rate, if we get 0, we reset the rate
984              * to the default. VMD filters 0 however */
985             case IMD_TRATE:
986                 nstimd_new = (length > 0) ? length : defaultNstImd;
987                 GMX_LOG(mdlog.warning)
988                         .appendTextFormatted(" %s Update frequency will be set to %d.", IMDstr, nstimd_new);
989                 break;
990
991             /* Catch all rule for the remaining IMD types which we don't expect */
992             default:
993                 GMX_LOG(mdlog.warning)
994                         .appendTextFormatted(" %s Received unexpected %s.", IMDstr,
995                                              enum_name(static_cast<int>(itype), IMD_NR, eIMDType_names));
996                 issueFatalError("Terminating connection");
997                 break;
998         } /* end switch */
999     }     /* end while  */
1000 }
1001
1002
1003 void ImdSession::Impl::openOutputFile(const char*                 fn,
1004                                       int                         nat_total,
1005                                       const gmx_output_env_t*     oenv,
1006                                       const gmx::StartingBehavior startingBehavior)
1007 {
1008     /* Open log file of applied IMD forces if requested */
1009     if (!fn || !oenv)
1010     {
1011         fprintf(stdout,
1012                 "%s For a log of the IMD pull forces explicitly specify '-if' on the command "
1013                 "line.\n"
1014                 "%s (Not possible with energy minimization.)\n",
1015                 IMDstr, IMDstr);
1016         return;
1017     }
1018
1019     /* If we append to an existing file, all the header information is already there */
1020     if (startingBehavior == StartingBehavior::RestartWithAppending)
1021     {
1022         outf = gmx_fio_fopen(fn, "a+");
1023     }
1024     else
1025     {
1026         outf = gmx_fio_fopen(fn, "w+");
1027         if (nat == nat_total)
1028         {
1029             fprintf(outf,
1030                     "# Note that you can select an IMD index group in the .mdp file if a subset of "
1031                     "the atoms suffices.\n");
1032         }
1033
1034         xvgr_header(outf, "IMD Pull Forces", "Time (ps)",
1035                     "# of Forces / Atom IDs / Forces (kJ/mol)", exvggtNONE, oenv);
1036
1037         fprintf(outf, "# Can display and manipulate %d (of a total of %d) atoms via IMD.\n", nat, nat_total);
1038         fprintf(outf, "# column 1    : time (ps)\n");
1039         fprintf(outf,
1040                 "# column 2    : total number of atoms feeling an IMD pulling force at that "
1041                 "time\n");
1042         fprintf(outf,
1043                 "# cols. 3.-6  : global atom number of pulled atom, x-force, y-force, z-force "
1044                 "(kJ/mol)\n");
1045         fprintf(outf,
1046                 "# then follow : atom-ID, f[x], f[y], f[z] for more atoms in case the force on "
1047                 "multiple atoms is changed simultaneously.\n");
1048         fprintf(outf,
1049                 "# Note that the force on any atom is always equal to the last value for that "
1050                 "atom-ID found in the data.\n");
1051         fflush(outf);
1052     }
1053
1054     /* To reduce the output file size we remember the old values and output only
1055      * when something changed */
1056     snew(old_f_ind, nat); /* One can never pull on more atoms */
1057     snew(old_forces, nat);
1058 }
1059
1060
1061 ImdSession::Impl::Impl(const MDLogger& mdlog) : mdlog(mdlog)
1062 {
1063     init_block(&mols);
1064 }
1065
1066 ImdSession::Impl::~Impl()
1067 {
1068     if (outf)
1069     {
1070         gmx_fio_fclose(outf);
1071     }
1072     done_block(&mols);
1073 }
1074
1075
1076 void ImdSession::Impl::prepareMoleculesInImdGroup(const gmx_mtop_t* top_global)
1077 {
1078     /* check whether index is sorted */
1079     for (int i = 0; i < nat - 1; i++)
1080     {
1081         if (ind[i] > ind[i + 1])
1082         {
1083             gmx_fatal(FARGS, "%s IMD index is not sorted. This is currently not supported.\n", IMDstr);
1084         }
1085     }
1086
1087     RangePartitioning gmols = gmx_mtop_molecules(*top_global);
1088     t_block           lmols;
1089     lmols.nr = 0;
1090     snew(lmols.index, gmols.numBlocks() + 1);
1091     lmols.index[0] = 0;
1092
1093     for (int i = 0; i < gmols.numBlocks(); i++)
1094     {
1095         auto mol   = gmols.block(i);
1096         int  count = 0;
1097         for (int ii = 0; ii < nat; ii++)
1098         {
1099             if (mol.isInRange(ind[ii]))
1100             {
1101                 count += 1;
1102             }
1103         }
1104         if (count > 0)
1105         {
1106             lmols.index[lmols.nr + 1] = lmols.index[lmols.nr] + count;
1107             lmols.nr += 1;
1108         }
1109     }
1110     srenew(lmols.index, lmols.nr + 1);
1111     lmols.nalloc_index = lmols.nr + 1;
1112     mols               = lmols;
1113 }
1114
1115
1116 /*! \brief Copied and modified from groupcoord.c shift_positions_group(). */
1117 static void shift_positions(const matrix box,
1118                             rvec         x[], /* The positions [0..nr] */
1119                             const ivec   is,  /* The shift [0..nr] */
1120                             int          nr)           /* The number of positions */
1121 {
1122     int i, tx, ty, tz;
1123
1124     /* Loop over the group's atoms */
1125     if (TRICLINIC(box))
1126     {
1127         for (i = 0; i < nr; i++)
1128         {
1129             tx = is[XX];
1130             ty = is[YY];
1131             tz = is[ZZ];
1132
1133             x[i][XX] = x[i][XX] - tx * box[XX][XX] - ty * box[YY][XX] - tz * box[ZZ][XX];
1134             x[i][YY] = x[i][YY] - ty * box[YY][YY] - tz * box[ZZ][YY];
1135             x[i][ZZ] = x[i][ZZ] - tz * box[ZZ][ZZ];
1136         }
1137     }
1138     else
1139     {
1140         for (i = 0; i < nr; i++)
1141         {
1142             tx = is[XX];
1143             ty = is[YY];
1144             tz = is[ZZ];
1145
1146             x[i][XX] = x[i][XX] - tx * box[XX][XX];
1147             x[i][YY] = x[i][YY] - ty * box[YY][YY];
1148             x[i][ZZ] = x[i][ZZ] - tz * box[ZZ][ZZ];
1149         }
1150     }
1151 }
1152
1153
1154 void ImdSession::Impl::removeMolecularShifts(const matrix box)
1155 {
1156     /* for each molecule also present in IMD group */
1157     for (int i = 0; i < mols.nr; i++)
1158     {
1159         /* first we determine the minimum and maximum shifts for each molecule */
1160
1161         ivec largest, smallest, shift;
1162         clear_ivec(largest);
1163         clear_ivec(smallest);
1164         clear_ivec(shift);
1165
1166         copy_ivec(xa_shifts[mols.index[i]], largest);
1167         copy_ivec(xa_shifts[mols.index[i]], smallest);
1168
1169         for (int ii = mols.index[i] + 1; ii < mols.index[i + 1]; ii++)
1170         {
1171             if (xa_shifts[ii][XX] > largest[XX])
1172             {
1173                 largest[XX] = xa_shifts[ii][XX];
1174             }
1175             if (xa_shifts[ii][XX] < smallest[XX])
1176             {
1177                 smallest[XX] = xa_shifts[ii][XX];
1178             }
1179
1180             if (xa_shifts[ii][YY] > largest[YY])
1181             {
1182                 largest[YY] = xa_shifts[ii][YY];
1183             }
1184             if (xa_shifts[ii][YY] < smallest[YY])
1185             {
1186                 smallest[YY] = xa_shifts[ii][YY];
1187             }
1188
1189             if (xa_shifts[ii][ZZ] > largest[ZZ])
1190             {
1191                 largest[ZZ] = xa_shifts[ii][ZZ];
1192             }
1193             if (xa_shifts[ii][ZZ] < smallest[ZZ])
1194             {
1195                 smallest[ZZ] = xa_shifts[ii][ZZ];
1196             }
1197         }
1198
1199         /* check if we what we can subtract/add to the positions
1200          * to put them back into the central box */
1201         if (smallest[XX] > 0)
1202         {
1203             shift[XX] = smallest[XX];
1204         }
1205         if (smallest[YY] > 0)
1206         {
1207             shift[YY] = smallest[YY];
1208         }
1209         if (smallest[ZZ] > 0)
1210         {
1211             shift[ZZ] = smallest[ZZ];
1212         }
1213
1214         if (largest[XX] < 0)
1215         {
1216             shift[XX] = largest[XX];
1217         }
1218         if (largest[YY] < 0)
1219         {
1220             shift[YY] = largest[YY];
1221         }
1222         if (largest[ZZ] < 0)
1223         {
1224             shift[ZZ] = largest[ZZ];
1225         }
1226
1227         /* is there a shift at all? */
1228         if ((shift[XX]) || (shift[YY]) || (shift[ZZ]))
1229         {
1230             int molsize = mols.index[i + 1] - mols.index[i];
1231             /* shift the positions */
1232             shift_positions(box, &(xa[mols.index[i]]), shift, molsize);
1233         }
1234     }
1235 }
1236
1237
1238 void ImdSession::Impl::prepareForPositionAssembly(const t_commrec* cr, const rvec x[])
1239 {
1240     snew(xa, nat);
1241     snew(xa_ind, nat);
1242     snew(xa_shifts, nat);
1243     snew(xa_eshifts, nat);
1244     snew(xa_old, nat);
1245
1246     /* Save the original (whole) set of positions such that later the
1247      * molecule can always be made whole again */
1248     if (MASTER(cr))
1249     {
1250         for (int i = 0; i < nat; i++)
1251         {
1252             int ii = ind[i];
1253             copy_rvec(x[ii], xa_old[i]);
1254         }
1255     }
1256
1257     if (!PAR(cr))
1258     {
1259         nat_loc = nat;
1260         ind_loc = ind;
1261
1262         /* xa_ind[i] needs to be set to i for serial runs */
1263         for (int i = 0; i < nat; i++)
1264         {
1265             xa_ind[i] = i;
1266         }
1267     }
1268
1269     /* Communicate initial coordinates xa_old to all processes */
1270     if (PAR(cr))
1271     {
1272         gmx_bcast(nat * sizeof(xa_old[0]), xa_old, cr->mpi_comm_mygroup);
1273     }
1274 }
1275
1276
1277 /*! \brief Check for non-working integrator / parallel options. */
1278 static void imd_check_integrator_parallel(const t_inputrec* ir, const t_commrec* cr)
1279 {
1280     if (PAR(cr))
1281     {
1282         if (((ir->eI) == eiSteep) || ((ir->eI) == eiCG) || ((ir->eI) == eiLBFGS) || ((ir->eI) == eiNM))
1283         {
1284             gmx_fatal(FARGS,
1285                       "%s Energy minimization via steep, CG, lbfgs and nm in parallel is currently "
1286                       "not supported by IMD.\n",
1287                       IMDstr);
1288         }
1289     }
1290 }
1291
1292 std::unique_ptr<ImdSession> makeImdSession(const t_inputrec*           ir,
1293                                            const t_commrec*            cr,
1294                                            gmx_wallcycle*              wcycle,
1295                                            gmx_enerdata_t*             enerd,
1296                                            const gmx_multisim_t*       ms,
1297                                            const gmx_mtop_t*           top_global,
1298                                            const MDLogger&             mdlog,
1299                                            const rvec                  x[],
1300                                            int                         nfile,
1301                                            const t_filenm              fnm[],
1302                                            const gmx_output_env_t*     oenv,
1303                                            const ImdOptions&           options,
1304                                            const gmx::StartingBehavior startingBehavior)
1305 {
1306     std::unique_ptr<ImdSession> session(new ImdSession(mdlog));
1307     auto                        impl = session->impl_.get();
1308
1309     /* We will allow IMD sessions only if supported by the binary and
1310        explicitly enabled in the .tpr file */
1311     if (!GMX_IMD || !ir->bIMD)
1312     {
1313         return session;
1314     }
1315
1316     // TODO As IMD is intended for interactivity, and the .tpr file
1317     // opted in for that, it is acceptable to write more terminal
1318     // output than in a typical simulation. However, all the GMX_LOG
1319     // statements below should go to both the log file and to the
1320     // terminal. This is probably be implemented by adding a logging
1321     // stream named like ImdInfo, to separate it from warning and to
1322     // send it to both destinations.
1323
1324     if (EI_DYNAMICS(ir->eI))
1325     {
1326         impl->defaultNstImd = ir->nstcalcenergy;
1327     }
1328     else if (EI_ENERGY_MINIMIZATION(ir->eI))
1329     {
1330         impl->defaultNstImd = 1;
1331     }
1332     else
1333     {
1334         GMX_LOG(mdlog.warning)
1335                 .appendTextFormatted(
1336                         "%s Integrator '%s' is not supported for Interactive Molecular Dynamics, "
1337                         "running normally instead",
1338                         IMDstr, ei_names[ir->eI]);
1339         return session;
1340     }
1341     if (isMultiSim(ms))
1342     {
1343         GMX_LOG(mdlog.warning)
1344                 .appendTextFormatted(
1345                         "%s Cannot use IMD for multiple simulations or replica exchange, running "
1346                         "normally instead",
1347                         IMDstr);
1348         return session;
1349     }
1350
1351     bool createSession = false;
1352     /* It seems we have a .tpr file that defines an IMD group and thus allows IMD connections.
1353      * Check whether we can actually provide the IMD functionality for this setting: */
1354     if (MASTER(cr))
1355     {
1356         /* Check whether IMD was enabled by one of the command line switches: */
1357         if (options.wait || options.terminatable || options.pull)
1358         {
1359             GMX_LOG(mdlog.warning)
1360                     .appendTextFormatted(
1361                             "%s Enabled. This simulation will accept incoming IMD connections.", IMDstr);
1362             createSession = true;
1363         }
1364         else
1365         {
1366             GMX_LOG(mdlog.warning)
1367                     .appendTextFormatted(
1368                             "%s None of the -imd switches was used.\n"
1369                             "%s This run will not accept incoming IMD connections",
1370                             IMDstr, IMDstr);
1371         }
1372     } /* end master only */
1373
1374     /* Let the other nodes know whether we want IMD */
1375     if (PAR(cr))
1376     {
1377         block_bc(cr->mpi_comm_mygroup, createSession);
1378     }
1379
1380     /*... if not we are done.*/
1381     if (!createSession)
1382     {
1383         return session;
1384     }
1385
1386
1387     /* check if we're using a sane integrator / parallel combination */
1388     imd_check_integrator_parallel(ir, cr);
1389
1390
1391     /*
1392      *****************************************************
1393      * From here on we assume that IMD is turned on      *
1394      *****************************************************
1395      */
1396
1397     int nat_total = top_global->natoms;
1398
1399     /* Initialize IMD session. If we read in a pre-IMD .tpr file, ir->imd->nat
1400      * will be zero. For those cases we transfer _all_ atomic positions */
1401     impl->sessionPossible = true;
1402     impl->nat             = ir->imd->nat > 0 ? ir->imd->nat : nat_total;
1403     if (options.port >= 1)
1404     {
1405         impl->port = options.port;
1406     }
1407     impl->cr     = cr;
1408     impl->wcycle = wcycle;
1409     impl->enerd  = enerd;
1410
1411     /* We might need to open an output file for IMD forces data */
1412     if (MASTER(cr))
1413     {
1414         impl->openOutputFile(opt2fn("-if", nfile, fnm), nat_total, oenv, startingBehavior);
1415     }
1416
1417     /* Make sure that we operate with a valid atom index array for the IMD atoms */
1418     if (ir->imd->nat > 0)
1419     {
1420         /* Point to the user-supplied array of atom numbers */
1421         impl->ind = ir->imd->ind;
1422     }
1423     else
1424     {
1425         /* Make a dummy (ind[i] = i) array of all atoms */
1426         snew(impl->ind, nat_total);
1427         for (int i = 0; i < nat_total; i++)
1428         {
1429             impl->ind[i] = i;
1430         }
1431     }
1432
1433     /* read environment on master and prepare socket for incoming connections */
1434     if (MASTER(cr))
1435     {
1436         /* we allocate memory for our IMD energy structure */
1437         int32_t recsize = c_headerSize + sizeof(IMDEnergyBlock);
1438         snew(impl->energysendbuf, recsize);
1439
1440         /* Shall we wait for a connection? */
1441         if (options.wait)
1442         {
1443             impl->bWConnect = true;
1444             GMX_LOG(mdlog.warning)
1445                     .appendTextFormatted(
1446                             "%s Pausing simulation while no IMD connection present (-imdwait).", IMDstr);
1447         }
1448
1449         /* Will the IMD clients be able to terminate the simulation? */
1450         if (options.terminatable)
1451         {
1452             impl->bTerminatable = true;
1453             GMX_LOG(mdlog.warning)
1454                     .appendTextFormatted(
1455                             "%s Allow termination of the simulation from IMD client (-imdterm).", IMDstr);
1456         }
1457
1458         /* Is pulling from IMD client allowed? */
1459         if (options.pull)
1460         {
1461             impl->bForceActivated = true;
1462             GMX_LOG(mdlog.warning)
1463                     .appendTextFormatted("%s Pulling from IMD remote is enabled (-imdpull).", IMDstr);
1464         }
1465
1466         /* Initialize send buffers with constant size */
1467         snew(impl->sendxbuf, impl->nat);
1468         snew(impl->energies, 1);
1469         int32_t bufxsize = c_headerSize + 3 * sizeof(float) * impl->nat;
1470         snew(impl->coordsendbuf, bufxsize);
1471     }
1472
1473     /* do we allow interactive pulling? If so let the other nodes know. */
1474     if (PAR(cr))
1475     {
1476         block_bc(cr->mpi_comm_mygroup, impl->bForceActivated);
1477     }
1478
1479     /* setup the listening socket on master process */
1480     if (MASTER(cr))
1481     {
1482         GMX_LOG(mdlog.warning).appendTextFormatted("%s Setting port for connection requests to %d.", IMDstr, impl->port);
1483         impl->prepareMasterSocket();
1484         /* Wait until we have a connection if specified before */
1485         if (impl->bWConnect)
1486         {
1487             impl->blockConnect();
1488         }
1489         else
1490         {
1491             GMX_LOG(mdlog.warning).appendTextFormatted("%s -imdwait not set, starting simulation.", IMDstr);
1492         }
1493     }
1494     /* Let the other nodes know whether we are connected */
1495     impl->syncNodes(cr, 0);
1496
1497     /* Initialize arrays used to assemble the positions from the other nodes */
1498     impl->prepareForPositionAssembly(cr, x);
1499
1500     /* Initialize molecule blocks to make them whole later...*/
1501     if (MASTER(cr))
1502     {
1503         impl->prepareMoleculesInImdGroup(top_global);
1504     }
1505
1506     return session;
1507 }
1508
1509
1510 bool ImdSession::Impl::run(int64_t step, bool bNS, const matrix box, const rvec x[], double t)
1511 {
1512     /* IMD at all? */
1513     if (!sessionPossible)
1514     {
1515         return false;
1516     }
1517
1518     wallcycle_start(wcycle, ewcIMD);
1519
1520     /* read command from client and check if new incoming connection */
1521     if (MASTER(cr))
1522     {
1523         /* If not already connected, check for new connections */
1524         if (!clientsocket)
1525         {
1526             if (bWConnect)
1527             {
1528                 blockConnect();
1529             }
1530             else
1531             {
1532                 tryConnect();
1533             }
1534         }
1535
1536         /* Let's see if we have new IMD messages for us */
1537         if (clientsocket)
1538         {
1539             readCommand();
1540         }
1541     }
1542
1543     /* is this an IMD communication step? */
1544     bool imdstep = do_per_step(step, nstimd);
1545
1546     /* OK so this is an IMD step ... */
1547     if (imdstep)
1548     {
1549         /* First we sync all nodes to let everybody know whether we are connected to VMD */
1550         syncNodes(cr, t);
1551     }
1552
1553     /* If a client is connected, we collect the positions
1554      * and put molecules back into the box before transfer */
1555     if ((imdstep && bConnected) || bNS) /* independent of imdstep, we communicate positions at each NS step */
1556     {
1557         /* Transfer the IMD positions to the master node. Every node contributes
1558          * its local positions x and stores them in the assembled xa array. */
1559         communicate_group_positions(cr, xa, xa_shifts, xa_eshifts, true, x, nat, nat_loc, ind_loc,
1560                                     xa_ind, xa_old, box);
1561
1562         /* If connected and master -> remove shifts */
1563         if ((imdstep && bConnected) && MASTER(cr))
1564         {
1565             removeMolecularShifts(box);
1566         }
1567     }
1568
1569     wallcycle_stop(wcycle, ewcIMD);
1570
1571     return imdstep;
1572 }
1573
1574 bool ImdSession::run(int64_t step, bool bNS, const matrix box, const rvec x[], double t)
1575 {
1576     return impl_->run(step, bNS, box, x, t);
1577 }
1578
1579 void ImdSession::fillEnergyRecord(int64_t step, bool bHaveNewEnergies)
1580 {
1581     if (!impl_->sessionPossible || !impl_->clientsocket)
1582     {
1583         return;
1584     }
1585
1586     IMDEnergyBlock* ene = impl_->energies;
1587
1588     ene->tstep = step;
1589
1590     /* In MPI-parallel simulations the energies are not accessible a at every time step.
1591      * We update them if we have new values, otherwise, the energy values from the
1592      * last global communication step are still on display in the viewer. */
1593     if (bHaveNewEnergies)
1594     {
1595         ene->T_abs   = static_cast<float>(impl_->enerd->term[F_TEMP]);
1596         ene->E_pot   = static_cast<float>(impl_->enerd->term[F_EPOT]);
1597         ene->E_tot   = static_cast<float>(impl_->enerd->term[F_ETOT]);
1598         ene->E_bond  = static_cast<float>(impl_->enerd->term[F_BONDS]);
1599         ene->E_angle = static_cast<float>(impl_->enerd->term[F_ANGLES]);
1600         ene->E_dihe  = static_cast<float>(impl_->enerd->term[F_PDIHS]);
1601         ene->E_impr  = static_cast<float>(impl_->enerd->term[F_IDIHS]);
1602         ene->E_vdw   = static_cast<float>(impl_->enerd->term[F_LJ]);
1603         ene->E_coul  = static_cast<float>(impl_->enerd->term[F_COUL_SR]);
1604     }
1605 }
1606
1607
1608 void ImdSession::sendPositionsAndEnergies()
1609 {
1610     if (!impl_->sessionPossible || !impl_->clientsocket)
1611     {
1612         return;
1613     }
1614
1615     if (imd_send_energies(impl_->clientsocket, impl_->energies, impl_->energysendbuf))
1616     {
1617         impl_->issueFatalError("Error sending updated energies. Disconnecting client.");
1618     }
1619
1620     if (imd_send_rvecs(impl_->clientsocket, impl_->nat, impl_->xa, impl_->coordsendbuf))
1621     {
1622         impl_->issueFatalError("Error sending updated positions. Disconnecting client.");
1623     }
1624 }
1625
1626
1627 void ImdSession::updateEnergyRecordAndSendPositionsAndEnergies(bool bIMDstep, int64_t step, bool bHaveNewEnergies)
1628 {
1629     if (!impl_->sessionPossible)
1630     {
1631         return;
1632     }
1633
1634     wallcycle_start(impl_->wcycle, ewcIMD);
1635
1636     /* Update time step for IMD and prepare IMD energy record if we have new energies. */
1637     fillEnergyRecord(step, bHaveNewEnergies);
1638
1639     if (bIMDstep)
1640     {
1641         /* Send positions and energies to VMD client via IMD */
1642         sendPositionsAndEnergies();
1643     }
1644
1645     wallcycle_stop(impl_->wcycle, ewcIMD);
1646 }
1647
1648 void ImdSession::applyForces(rvec* f)
1649 {
1650     if (!impl_->sessionPossible || !impl_->bForceActivated)
1651     {
1652         return;
1653     }
1654
1655     wallcycle_start(impl_->wcycle, ewcIMD);
1656
1657     for (int i = 0; i < impl_->nforces; i++)
1658     {
1659         /* j are the indices in the "System group".*/
1660         int j = impl_->ind[impl_->f_ind[i]];
1661
1662         /* check if this is a local atom and find out locndx */
1663         const int*       locndx;
1664         const t_commrec* cr = impl_->cr;
1665         if (PAR(cr) && (locndx = cr->dd->ga2la->findHome(j)))
1666         {
1667             j = *locndx;
1668         }
1669
1670         rvec_inc(f[j], impl_->f[i]);
1671     }
1672
1673     wallcycle_stop(impl_->wcycle, ewcIMD);
1674 }
1675
1676 ImdSession::ImdSession(const MDLogger& mdlog) : impl_(new Impl(mdlog)) {}
1677
1678 ImdSession::~ImdSession() = default;
1679
1680 } // namespace gmx