Fix GPU X buffer ops with empty domain
[gromacs.git] / src / gromacs / essentialdynamics / edsam.cpp
blob2b9fd374a66c90f8f15d095520b8d4a91bee1775
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "edsam.h"
41 #include <cmath>
42 #include <cstdio>
43 #include <cstring>
44 #include <ctime>
46 #include <memory>
48 #include "gromacs/commandline/filenm.h"
49 #include "gromacs/domdec/domdec_struct.h"
50 #include "gromacs/fileio/gmxfio.h"
51 #include "gromacs/fileio/xvgr.h"
52 #include "gromacs/gmxlib/network.h"
53 #include "gromacs/gmxlib/nrnb.h"
54 #include "gromacs/linearalgebra/nrjac.h"
55 #include "gromacs/math/functions.h"
56 #include "gromacs/math/utilities.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/math/vectypes.h"
59 #include "gromacs/mdlib/broadcaststructs.h"
60 #include "gromacs/mdlib/constr.h"
61 #include "gromacs/mdlib/groupcoord.h"
62 #include "gromacs/mdlib/stat.h"
63 #include "gromacs/mdlib/update.h"
64 #include "gromacs/mdrunutility/handlerestart.h"
65 #include "gromacs/mdtypes/commrec.h"
66 #include "gromacs/mdtypes/edsamhistory.h"
67 #include "gromacs/mdtypes/inputrec.h"
68 #include "gromacs/mdtypes/md_enums.h"
69 #include "gromacs/mdtypes/observableshistory.h"
70 #include "gromacs/mdtypes/state.h"
71 #include "gromacs/pbcutil/pbc.h"
72 #include "gromacs/topology/mtop_lookup.h"
73 #include "gromacs/topology/topology.h"
74 #include "gromacs/utility/cstringutil.h"
75 #include "gromacs/utility/fatalerror.h"
76 #include "gromacs/utility/gmxassert.h"
77 #include "gromacs/utility/logger.h"
78 #include "gromacs/utility/smalloc.h"
79 #include "gromacs/utility/strconvert.h"
81 namespace
83 /*! \brief Identifies the type of ED: none, normal ED, flooding. */
84 enum class EssentialDynamicsType
86 //! No essential dynamics
87 None,
88 //! Essential dynamics sampling
89 EDSampling,
90 //! Essential dynamics flooding
91 Flooding
94 /*! \brief Identify on which structure to operate. */
95 enum class EssentialDynamicsStructure
97 //! Reference structure
98 Reference,
99 //! Average Structure
100 Average,
101 //! Origin Structure
102 Origin,
103 //! Target Structure
104 Target
107 /*! \brief Essential dynamics vector.
108 * TODO: split into working data and input data
109 * NOTE: called eigvec, because traditionally eigenvectors from PCA analysis
110 * were used as essential dynamics vectors, however, vectors used for ED need
111 * not have any special properties
113 struct t_eigvec
115 //! nr of eigenvectors
116 int neig = 0;
117 //! index nrs of eigenvectors
118 int *ieig = nullptr;
119 //! stepsizes (per eigenvector)
120 real *stpsz = nullptr;
121 //! eigenvector components
122 rvec **vec = nullptr;
123 //! instantaneous x projections
124 real *xproj = nullptr;
125 //! instantaneous f projections
126 real *fproj = nullptr;
127 //! instantaneous radius
128 real radius = 0.;
129 //! starting or target projections
130 real *refproj = nullptr;
133 /*! \brief Essential dynamics vectors per method implementation.
135 struct t_edvecs
137 //! only monitored, no constraints
138 t_eigvec mon = {};
139 //! fixed linear constraints
140 t_eigvec linfix = {};
141 //! acceptance linear constraints
142 t_eigvec linacc = {};
143 //! fixed radial constraints (exp)
144 t_eigvec radfix = {};
145 //! acceptance radial constraints (exp)
146 t_eigvec radacc = {};
147 //! acceptance rad. contraction constr.
148 t_eigvec radcon = {};
151 /*! \brief Essential dynamics flooding parameters and work data.
152 * TODO: split into working data and input parameters
153 * NOTE: The implementation here follows:
154 * O.E. Lange, L.V. Schafer, and H. Grubmuller,
155 * “Flooding in GROMACS: Accelerated barrier crossings in molecular dynamics,”
156 * J. Comp. Chem., 27 1693–1702 (2006)
158 struct t_edflood
160 /*! \brief Target destabilisation free energy.
161 * Controls the flooding potential strength.
162 * Linked to the expected speed-up of mean first passage time out of flooded minimum */
163 real deltaF0 = 0;
164 //! Do not calculate a flooding potential, instead flood with a constant force
165 bool bConstForce = false;
166 //! Relaxation time scale for slowest flooded degree of freedom
167 real tau = 0;
168 //! Current estimated destabilisation free energy
169 real deltaF = 0;
170 //! Flooding energy, acting as a proportionality factor for the flooding potential
171 real Efl = 0;
172 //! Boltzmann constant times temperature, provided by user
173 real kT = 0;
174 //! The flooding potential
175 real Vfl = 0;
176 //! Integration time step
177 real dt = 0;
178 //! Inital flooding strenth
179 real constEfl = 0;
180 //! Empirical global scaling parameter of the essential dynamics vectors.
181 real alpha2 = 0;
182 //! The forces from flooding in atom coordinate space (in contrast to projections onto essential dynamics vectors)
183 rvec *forces_cartesian = nullptr;
184 //! The vectors along which to flood
185 t_eigvec vecs = {};
186 //! Use flooding for harmonic restraint on the eigenvector
187 bool bHarmonic = false;
188 //! The initial reference projection of the flooding vectors. Only with harmonic restraint.
189 real *initialReferenceProjection = nullptr;
190 //! The current reference projection is the initialReferenceProjection + step * slope. Only with harmonic restraint.
191 real *referenceProjectionSlope = nullptr;
193 } // namespace
196 /* This type is for the average, reference, target, and origin structure */
197 struct gmx_edx
199 int nr = 0; /* number of atoms this structure contains */
200 int nr_loc = 0; /* number of atoms on local node */
201 int *anrs = nullptr; /* atom index numbers */
202 int *anrs_loc = nullptr; /* local atom index numbers */
203 int nalloc_loc = 0; /* allocation size of anrs_loc */
204 int *c_ind = nullptr; /* at which position of the whole anrs
205 * array is a local atom?, i.e.
206 * c_ind[0...nr_loc-1] gives the atom index
207 * with respect to the collective
208 * anrs[0...nr-1] array */
209 rvec *x = nullptr; /* positions for this structure */
210 rvec *x_old = nullptr; /* Last positions which have the correct PBC
211 representation of the ED group. In
212 combination with keeping track of the
213 shift vectors, the ED group can always
214 be made whole */
215 real *m = nullptr; /* masses */
216 real mtot = 0.; /* total mass (only used in sref) */
217 real *sqrtm = nullptr; /* sqrt of the masses used for mass-
218 * weighting of analysis (only used in sav) */
222 typedef struct edpar
224 int nini = 0; /* total Nr of atoms */
225 gmx_bool fitmas = false; /* true if trans fit with cm */
226 gmx_bool pcamas = false; /* true if mass-weighted PCA */
227 int presteps = 0; /* number of steps to run without any
228 * perturbations ... just monitoring */
229 int outfrq = 0; /* freq (in steps) of writing to edo */
230 int maxedsteps = 0; /* max nr of steps per cycle */
232 /* all gmx_edx datasets are copied to all nodes in the parallel case */
233 gmx_edx sref = {}; /* reference positions, to these fitting
234 * will be done */
235 gmx_bool bRefEqAv = false; /* If true, reference & average indices
236 * are the same. Used for optimization */
237 gmx_edx sav = {}; /* average positions */
238 gmx_edx star = {}; /* target positions */
239 gmx_edx sori = {}; /* origin positions */
241 t_edvecs vecs = {}; /* eigenvectors */
242 real slope = 0; /* minimal slope in acceptance radexp */
244 t_edflood flood = {}; /* parameters especially for flooding */
245 struct t_ed_buffer *buf = nullptr; /* handle to local buffers */
246 } t_edpar;
249 struct gmx_edsam
251 ~gmx_edsam();
252 //! The type of ED
253 EssentialDynamicsType eEDtype = EssentialDynamicsType::None;
254 //! output file pointer
255 FILE *edo = nullptr;
256 std::vector<t_edpar> edpar;
257 gmx_bool bFirst = false;
259 gmx_edsam::~gmx_edsam()
261 if (edo)
263 /* edo is opened sometimes with xvgropen, sometimes with
264 * gmx_fio_fopen, so we use the least common denominator for
265 * closing. */
266 gmx_fio_fclose(edo);
270 struct t_do_edsam
272 matrix old_rotmat;
273 real oldrad;
274 rvec old_transvec, older_transvec, transvec_compact;
275 rvec *xcoll; /* Positions from all nodes, this is the
276 collective set we work on.
277 These are the positions of atoms with
278 average structure indices */
279 rvec *xc_ref; /* same but with reference structure indices */
280 ivec *shifts_xcoll; /* Shifts for xcoll */
281 ivec *extra_shifts_xcoll; /* xcoll shift changes since last NS step */
282 ivec *shifts_xc_ref; /* Shifts for xc_ref */
283 ivec *extra_shifts_xc_ref; /* xc_ref shift changes since last NS step */
284 gmx_bool bUpdateShifts; /* TRUE in NS steps to indicate that the
285 ED shifts for this ED group need to
286 be updated */
290 /* definition of ED buffer structure */
291 struct t_ed_buffer
293 struct t_fit_to_ref * fit_to_ref;
294 struct t_do_edfit * do_edfit;
295 struct t_do_edsam * do_edsam;
296 struct t_do_radcon * do_radcon;
299 namespace gmx
301 class EssentialDynamics::Impl
303 public:
304 // TODO: move all fields from gmx_edsam here and remove gmx_edsam
305 gmx_edsam essentialDynamics_;
307 EssentialDynamics::EssentialDynamics() : impl_(new Impl)
310 EssentialDynamics::~EssentialDynamics() = default;
312 gmx_edsam *EssentialDynamics::getLegacyED()
314 return &impl_->essentialDynamics_;
316 } // namespace gmx
318 /* Function declarations */
319 static void fit_to_reference(rvec *xcoll, rvec transvec, matrix rotmat, t_edpar *edi);
320 static void translate_and_rotate(rvec *x, int nat, rvec transvec, matrix rotmat);
321 static real rmsd_from_structure(rvec *x, struct gmx_edx *s);
322 namespace
324 /*! \brief Read in the essential dynamics input file and return its contents.
325 * \param[in] fn the file name of the edi file to be read
326 * \param[in] nr_mdatoms the number of atoms in the simulation
327 * \returns A vector of containing the essentiail dyanmics parameters.
328 * NOTE: edi files may that it may contain several ED data sets from concatenated edi files.
329 * The standard case would be a single ED data set, though. */
330 std::vector<t_edpar> read_edi_file(const char *fn, int nr_mdatoms);
332 static void crosscheck_edi_file_vs_checkpoint(const gmx_edsam &ed, edsamhistory_t *EDstate);
333 static void init_edsamstate(const gmx_edsam &ed, edsamhistory_t *EDstate);
334 static void write_edo_legend(gmx_edsam * ed, int nED, const gmx_output_env_t *oenv);
335 /* End function declarations */
337 /* Define formats for the column width in the output file */
338 const char EDcol_sfmt[] = "%17s";
339 const char EDcol_efmt[] = "%17.5e";
340 const char EDcol_ffmt[] = "%17f";
342 /* Define a formats for reading, otherwise cppcheck complains for scanf without width limits */
343 const char max_ev_fmt_d[] = "%7d"; /* Number of eigenvectors. 9,999,999 should be enough */
344 const char max_ev_fmt_lf[] = "%12lf";
345 const char max_ev_fmt_dlf[] = "%7d%12lf";
346 const char max_ev_fmt_dlflflf[] = "%7d%12lf%12lf%12lf";
347 const char max_ev_fmt_lelele[] = "%12le%12le%12le";
349 namespace
351 /*!\brief Determines whether to perform essential dynamics constraints other than flooding.
352 * \param[in] edi the essential dynamics parameters
353 * \returns true if essential dyanmics constraints need to be performed
355 bool bNeedDoEdsam(const t_edpar &edi)
357 return (edi.vecs.mon.neig != 0)
358 || (edi.vecs.linfix.neig != 0)
359 || (edi.vecs.linacc.neig != 0)
360 || (edi.vecs.radfix.neig != 0)
361 || (edi.vecs.radacc.neig != 0)
362 || (edi.vecs.radcon.neig != 0);
364 } // namespace
367 /* Multiple ED groups will be labeled with letters instead of numbers
368 * to avoid confusion with eigenvector indices */
369 static char get_EDgroupChar(int nr_edi, int nED)
371 if (nED == 1)
373 return ' ';
376 /* nr_edi = 1 -> A
377 * nr_edi = 2 -> B ...
379 return 'A' + nr_edi - 1;
382 namespace
384 /*! \brief The mass-weighted inner product of two coordinate vectors.
385 * Does not subtract average positions, projection on single eigenvector is returned
386 * used by: do_linfix, do_linacc, do_radfix, do_radacc, do_radcon
387 * Average position is subtracted in ed_apply_constraints prior to calling projectx
388 * \param[in] edi Essential dynamics parameters
389 * \param[in] xcoll vector of atom coordinates
390 * \param[in] vec vector of coordinates to project onto
391 * \return mass-weighted projection.
393 real projectx(const t_edpar &edi, rvec *xcoll, rvec *vec)
395 int i;
396 real proj = 0.0;
399 for (i = 0; i < edi.sav.nr; i++)
401 proj += edi.sav.sqrtm[i]*iprod(vec[i], xcoll[i]);
404 return proj;
406 /*!\brief Project coordinates onto vector after substracting average position.
407 * projection is stored in vec->refproj which is used for radacc, radfix,
408 * radcon and center of flooding potential.
409 * Average positions are first substracted from x, then added back again.
410 * \param[in] edi essential dynamics parameters with average position
411 * \param[in] x Coordinates to be projected
412 * \param[out] vec eigenvector, radius and refproj are overwritten here
414 void rad_project(const t_edpar &edi, rvec *x, t_eigvec *vec)
416 int i;
417 real rad = 0.0;
419 /* Subtract average positions */
420 for (i = 0; i < edi.sav.nr; i++)
422 rvec_dec(x[i], edi.sav.x[i]);
425 for (i = 0; i < vec->neig; i++)
427 vec->refproj[i] = projectx(edi, x, vec->vec[i]);
428 rad += gmx::square((vec->refproj[i]-vec->xproj[i]));
430 vec->radius = sqrt(rad);
432 /* Add average positions */
433 for (i = 0; i < edi.sav.nr; i++)
435 rvec_inc(x[i], edi.sav.x[i]);
439 /*!\brief Projects coordinates onto eigenvectors and stores result in vec->xproj.
440 * Mass-weighting is applied. Subtracts average positions prior to projection and add
441 * them afterwards to retain the unchanged vector.
442 * \param[in] x The coordinates to project to an eigenvector
443 * \param[in,out] vec The eigenvectors
444 * \param[in] edi essential dynamics parameters holding average structure and masses
446 void project_to_eigvectors(rvec *x, t_eigvec *vec, const t_edpar &edi)
448 if (!vec->neig)
450 return;
453 /* Subtract average positions */
454 for (int i = 0; i < edi.sav.nr; i++)
456 rvec_dec(x[i], edi.sav.x[i]);
459 for (int i = 0; i < vec->neig; i++)
461 vec->xproj[i] = projectx(edi, x, vec->vec[i]);
464 /* Add average positions */
465 for (int i = 0; i < edi.sav.nr; i++)
467 rvec_inc(x[i], edi.sav.x[i]);
470 } // namespace
472 /* Project vector x onto all edi->vecs (mon, linfix,...) */
473 static void project(rvec *x, /* positions to project */
474 t_edpar *edi) /* edi data set */
476 /* It is not more work to subtract the average position in every
477 * subroutine again, because these routines are rarely used simultaneously */
478 project_to_eigvectors(x, &edi->vecs.mon, *edi);
479 project_to_eigvectors(x, &edi->vecs.linfix, *edi);
480 project_to_eigvectors(x, &edi->vecs.linacc, *edi);
481 project_to_eigvectors(x, &edi->vecs.radfix, *edi);
482 project_to_eigvectors(x, &edi->vecs.radacc, *edi);
483 project_to_eigvectors(x, &edi->vecs.radcon, *edi);
486 namespace
488 /*!\brief Evaluates the distance from reference to current eigenvector projection.
489 * \param[in] vec eigenvector
490 * \returns distance
492 real calc_radius(const t_eigvec &vec)
494 real rad = 0.0;
496 for (int i = 0; i < vec.neig; i++)
498 rad += gmx::square((vec.refproj[i]-vec.xproj[i]));
501 return rad = sqrt(rad);
503 } // namespace
505 struct t_do_edfit {
506 double **omega;
507 double **om;
510 static void do_edfit(int natoms, rvec *xp, rvec *x, matrix R, t_edpar *edi)
512 /* this is a copy of do_fit with some modifications */
513 int c, r, n, j, i, irot;
514 double d[6], xnr, xpc;
515 matrix vh, vk, u;
516 int index;
517 real max_d;
519 struct t_do_edfit *loc;
520 gmx_bool bFirst;
522 if (edi->buf->do_edfit != nullptr)
524 bFirst = FALSE;
526 else
528 bFirst = TRUE;
529 snew(edi->buf->do_edfit, 1);
531 loc = edi->buf->do_edfit;
533 if (bFirst)
535 snew(loc->omega, 2*DIM);
536 snew(loc->om, 2*DIM);
537 for (i = 0; i < 2*DIM; i++)
539 snew(loc->omega[i], 2*DIM);
540 snew(loc->om[i], 2*DIM);
544 for (i = 0; (i < 6); i++)
546 d[i] = 0;
547 for (j = 0; (j < 6); j++)
549 loc->omega[i][j] = 0;
550 loc->om[i][j] = 0;
554 /* calculate the matrix U */
555 clear_mat(u);
556 for (n = 0; (n < natoms); n++)
558 for (c = 0; (c < DIM); c++)
560 xpc = xp[n][c];
561 for (r = 0; (r < DIM); r++)
563 xnr = x[n][r];
564 u[c][r] += xnr*xpc;
569 /* construct loc->omega */
570 /* loc->omega is symmetric -> loc->omega==loc->omega' */
571 for (r = 0; (r < 6); r++)
573 for (c = 0; (c <= r); c++)
575 if ((r >= 3) && (c < 3))
577 loc->omega[r][c] = u[r-3][c];
578 loc->omega[c][r] = u[r-3][c];
580 else
582 loc->omega[r][c] = 0;
583 loc->omega[c][r] = 0;
588 /* determine h and k */
589 jacobi(loc->omega, 6, d, loc->om, &irot);
591 if (irot == 0)
593 fprintf(stderr, "IROT=0\n");
596 index = 0; /* For the compiler only */
598 for (j = 0; (j < 3); j++)
600 max_d = -1000;
601 for (i = 0; (i < 6); i++)
603 if (d[i] > max_d)
605 max_d = d[i];
606 index = i;
609 d[index] = -10000;
610 for (i = 0; (i < 3); i++)
612 vh[j][i] = M_SQRT2*loc->om[i][index];
613 vk[j][i] = M_SQRT2*loc->om[i+DIM][index];
617 /* determine R */
618 for (c = 0; (c < 3); c++)
620 for (r = 0; (r < 3); r++)
622 R[c][r] = vk[0][r]*vh[0][c]+
623 vk[1][r]*vh[1][c]+
624 vk[2][r]*vh[2][c];
627 if (det(R) < 0)
629 for (c = 0; (c < 3); c++)
631 for (r = 0; (r < 3); r++)
633 R[c][r] = vk[0][r]*vh[0][c]+
634 vk[1][r]*vh[1][c]-
635 vk[2][r]*vh[2][c];
642 static void rmfit(int nat, rvec *xcoll, const rvec transvec, matrix rotmat)
644 rvec vec;
645 matrix tmat;
648 /* Remove rotation.
649 * The inverse rotation is described by the transposed rotation matrix */
650 transpose(rotmat, tmat);
651 rotate_x(xcoll, nat, tmat);
653 /* Remove translation */
654 vec[XX] = -transvec[XX];
655 vec[YY] = -transvec[YY];
656 vec[ZZ] = -transvec[ZZ];
657 translate_x(xcoll, nat, vec);
661 /**********************************************************************************
662 ******************** FLOODING ****************************************************
663 **********************************************************************************
665 The flooding ability was added later to edsam. Many of the edsam functionality could be reused for that purpose.
666 The flooding covariance matrix, i.e. the selected eigenvectors and their corresponding eigenvalues are
667 read as 7th Component Group. The eigenvalues are coded into the stepsize parameter (as used by -linfix or -linacc).
669 do_md clls right in the beginning the function init_edsam, which reads the edi file, saves all the necessary information in
670 the edi structure and calls init_flood, to initialise some extra fields in the edi->flood structure.
672 since the flooding acts on forces do_flood is called from the function force() (force.c), while the other
673 edsam functionality is hooked into md via the update() (update.c) function acting as constraint on positions.
675 do_flood makes a copy of the positions,
676 fits them, projects them computes flooding_energy, and flooding forces. The forces are computed in the
677 space of the eigenvectors and are then blown up to the full cartesian space and rotated back to remove the
678 fit. Then do_flood adds these forces to the forcefield-forces
679 (given as parameter) and updates the adaptive flooding parameters Efl and deltaF.
681 To center the flooding potential at a different location one can use the -ori option in make_edi. The ori
682 structure is projected to the system of eigenvectors and then this position in the subspace is used as
683 center of the flooding potential. If the option is not used, the center will be zero in the subspace,
684 i.e. the average structure as given in the make_edi file.
686 To use the flooding potential as restraint, make_edi has the option -restrain, which leads to inverted
687 signs of alpha2 and Efl, such that the sign in the exponential of Vfl is not inverted but the sign of
688 Vfl is inverted. Vfl = Efl * exp (- .../Efl/alpha2*x^2...) With tau>0 the negative Efl will grow slowly
689 so that the restraint is switched off slowly. When Efl==0 and inverted flooding is ON is reached no
690 further adaption is applied, Efl will stay constant at zero.
692 To use restraints with harmonic potentials switch -restrain and -harmonic. Then the eigenvalues are
693 used as spring constants for the harmonic potential.
694 Note that eq3 in the flooding paper (J. Comp. Chem. 2006, 27, 1693-1702) defines the parameter lambda \
695 as the inverse of the spring constant, whereas the implementation uses lambda as the spring constant.
697 To use more than one flooding matrix just concatenate several .edi files (cat flood1.edi flood2.edi > flood_all.edi)
698 the routine read_edi_file reads all of theses flooding files.
699 The structure t_edi is now organized as a list of t_edis and the function do_flood cycles through the list
700 calling the do_single_flood() routine for every single entry. Since every state variables have been kept in one
701 edi there is no interdependence whatsoever. The forces are added together.
703 To write energies into the .edr file, call the function
704 get_flood_enx_names(char**, int *nnames) to get the Header (Vfl1 Vfl2... Vfln)
705 and call
706 get_flood_energies(real Vfl[],int nnames);
708 TODO:
709 - one could program the whole thing such that Efl, Vfl and deltaF is written to the .edr file. -- i dont know how to do that, yet.
711 Maybe one should give a range of atoms for which to remove motion, so that motion is removed with
712 two edsam files from two peptide chains
715 // TODO split this into multiple files
716 namespace
718 /*!\brief Output flooding simulation settings and results to file.
719 * \param[in] edi Essential dynamics input parameters
720 * \param[in] fp output file
721 * \param[in] rmsd rmsd to reference structure
723 void write_edo_flood(const t_edpar &edi, FILE *fp, real rmsd)
725 /* Output how well we fit to the reference structure */
726 fprintf(fp, EDcol_ffmt, rmsd);
728 for (int i = 0; i < edi.flood.vecs.neig; i++)
730 fprintf(fp, EDcol_efmt, edi.flood.vecs.xproj[i]);
732 /* Check whether the reference projection changes with time (this can happen
733 * in case flooding is used as harmonic restraint). If so, output the
734 * current reference projection */
735 if (edi.flood.bHarmonic && edi.flood.referenceProjectionSlope[i] != 0.0)
737 fprintf(fp, EDcol_efmt, edi.flood.vecs.refproj[i]);
740 /* Output Efl if we are doing adaptive flooding */
741 if (0 != edi.flood.tau)
743 fprintf(fp, EDcol_efmt, edi.flood.Efl);
745 fprintf(fp, EDcol_efmt, edi.flood.Vfl);
747 /* Output deltaF if we are doing adaptive flooding */
748 if (0 != edi.flood.tau)
750 fprintf(fp, EDcol_efmt, edi.flood.deltaF);
752 fprintf(fp, EDcol_efmt, edi.flood.vecs.fproj[i]);
755 } // namespace
758 /* From flood.xproj compute the Vfl(x) at this point */
759 static real flood_energy(t_edpar *edi, int64_t step)
761 /* compute flooding energy Vfl
762 Vfl = Efl * exp( - \frac {kT} {2Efl alpha^2} * sum_i { \lambda_i c_i^2 } )
763 \lambda_i is the reciprocal eigenvalue 1/\sigma_i
764 it is already computed by make_edi and stored in stpsz[i]
765 bHarmonic:
766 Vfl = - Efl * 1/2(sum _i {\frac 1{\lambda_i} c_i^2})
768 real sum;
769 real Vfl;
770 int i;
773 /* Each time this routine is called (i.e. each time step), we add a small
774 * value to the reference projection. This way a harmonic restraint towards
775 * a moving reference is realized. If no value for the additive constant
776 * is provided in the edi file, the reference will not change. */
777 if (edi->flood.bHarmonic)
779 for (i = 0; i < edi->flood.vecs.neig; i++)
781 edi->flood.vecs.refproj[i] = edi->flood.initialReferenceProjection[i] + step * edi->flood.referenceProjectionSlope[i];
785 sum = 0.0;
786 /* Compute sum which will be the exponent of the exponential */
787 for (i = 0; i < edi->flood.vecs.neig; i++)
789 /* stpsz stores the reciprocal eigenvalue 1/sigma_i */
790 sum += edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i])*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]);
793 /* Compute the Gauss function*/
794 if (edi->flood.bHarmonic)
796 Vfl = -0.5*edi->flood.Efl*sum; /* minus sign because Efl is negative, if restrain is on. */
798 else
800 Vfl = edi->flood.Efl != 0 ? edi->flood.Efl*std::exp(-edi->flood.kT/2/edi->flood.Efl/edi->flood.alpha2*sum) : 0;
803 return Vfl;
807 /* From the position and from Vfl compute forces in subspace -> store in edi->vec.flood.fproj */
808 static void flood_forces(t_edpar *edi)
810 /* compute the forces in the subspace of the flooding eigenvectors
811 * by the formula F_i= V_{fl}(c) * ( \frac {kT} {E_{fl}} \lambda_i c_i */
813 int i;
814 real energy = edi->flood.Vfl;
817 if (edi->flood.bHarmonic)
819 for (i = 0; i < edi->flood.vecs.neig; i++)
821 edi->flood.vecs.fproj[i] = edi->flood.Efl* edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]);
824 else
826 for (i = 0; i < edi->flood.vecs.neig; i++)
828 /* if Efl is zero the forces are zero if not use the formula */
829 edi->flood.vecs.fproj[i] = edi->flood.Efl != 0 ? edi->flood.kT/edi->flood.Efl/edi->flood.alpha2*energy*edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]) : 0;
834 namespace
836 /*!\brief Raise forces from subspace into cartesian space.
837 * This function lifts the forces from the subspace to the cartesian space
838 * all the values not contained in the subspace are assumed to be zero and then
839 * a coordinate transformation from eigenvector to cartesian vectors is performed
840 * The nonexistent values don't have to be set to zero explicitly, they would occur
841 * as zero valued summands, hence we just stop to compute this part of the sum.
842 * For every atom we add all the contributions to this atom from all the different eigenvectors.
843 * NOTE: one could add directly to the forcefield forces, would mean we wouldn't have to clear the
844 * field forces_cart prior the computation, but we compute the forces separately
845 * to have them accessible for diagnostics
847 * \param[in] edi Essential dynamics input parameters
848 * \param[out] forces_cart The cartesian forces
851 void flood_blowup(const t_edpar &edi, rvec *forces_cart)
853 const real * forces_sub = edi.flood.vecs.fproj;
854 /* Calculate the cartesian forces for the local atoms */
856 /* Clear forces first */
857 for (int j = 0; j < edi.sav.nr_loc; j++)
859 clear_rvec(forces_cart[j]);
862 /* Now compute atomwise */
863 for (int j = 0; j < edi.sav.nr_loc; j++)
865 /* Compute forces_cart[edi.sav.anrs[j]] */
866 for (int eig = 0; eig < edi.flood.vecs.neig; eig++)
868 rvec addedForce;
869 /* Force vector is force * eigenvector (compute only atom j) */
870 svmul(forces_sub[eig], edi.flood.vecs.vec[eig][edi.sav.c_ind[j]], addedForce);
871 /* Add this vector to the cartesian forces */
872 rvec_inc(forces_cart[j], addedForce);
877 } // namespace
880 /* Update the values of Efl, deltaF depending on tau and Vfl */
881 static void update_adaption(t_edpar *edi)
883 /* this function updates the parameter Efl and deltaF according to the rules given in
884 * 'predicting unimolecular chemical reactions: chemical flooding' M Mueller et al,
885 * J. chem Phys. */
887 if ((edi->flood.tau < 0 ? -edi->flood.tau : edi->flood.tau ) > 0.00000001)
889 edi->flood.Efl = edi->flood.Efl+edi->flood.dt/edi->flood.tau*(edi->flood.deltaF0-edi->flood.deltaF);
890 /* check if restrain (inverted flooding) -> don't let EFL become positive */
891 if (edi->flood.alpha2 < 0 && edi->flood.Efl > -0.00000001)
893 edi->flood.Efl = 0;
896 edi->flood.deltaF = (1-edi->flood.dt/edi->flood.tau)*edi->flood.deltaF+edi->flood.dt/edi->flood.tau*edi->flood.Vfl;
901 static void do_single_flood(
902 FILE *edo,
903 const rvec x[],
904 rvec force[],
905 t_edpar *edi,
906 int64_t step,
907 const matrix box,
908 const t_commrec *cr,
909 gmx_bool bNS) /* Are we in a neighbor searching step? */
911 int i;
912 matrix rotmat; /* rotation matrix */
913 matrix tmat; /* inverse rotation */
914 rvec transvec; /* translation vector */
915 real rmsdev;
916 struct t_do_edsam *buf;
919 buf = edi->buf->do_edsam;
922 /* Broadcast the positions of the AVERAGE structure such that they are known on
923 * every processor. Each node contributes its local positions x and stores them in
924 * the collective ED array buf->xcoll */
925 communicate_group_positions(cr, buf->xcoll, buf->shifts_xcoll, buf->extra_shifts_xcoll, bNS, x,
926 edi->sav.nr, edi->sav.nr_loc, edi->sav.anrs_loc, edi->sav.c_ind, edi->sav.x_old, box);
928 /* Only assembly REFERENCE positions if their indices differ from the average ones */
929 if (!edi->bRefEqAv)
931 communicate_group_positions(cr, buf->xc_ref, buf->shifts_xc_ref, buf->extra_shifts_xc_ref, bNS, x,
932 edi->sref.nr, edi->sref.nr_loc, edi->sref.anrs_loc, edi->sref.c_ind, edi->sref.x_old, box);
935 /* If bUpdateShifts was TRUE, the shifts have just been updated in get_positions.
936 * We do not need to update the shifts until the next NS step */
937 buf->bUpdateShifts = FALSE;
939 /* Now all nodes have all of the ED/flooding positions in edi->sav->xcoll,
940 * as well as the indices in edi->sav.anrs */
942 /* Fit the reference indices to the reference structure */
943 if (edi->bRefEqAv)
945 fit_to_reference(buf->xcoll, transvec, rotmat, edi);
947 else
949 fit_to_reference(buf->xc_ref, transvec, rotmat, edi);
952 /* Now apply the translation and rotation to the ED structure */
953 translate_and_rotate(buf->xcoll, edi->sav.nr, transvec, rotmat);
955 /* Project fitted structure onto supbspace -> store in edi->flood.vecs.xproj */
956 project_to_eigvectors(buf->xcoll, &edi->flood.vecs, *edi);
958 if (!edi->flood.bConstForce)
960 /* Compute Vfl(x) from flood.xproj */
961 edi->flood.Vfl = flood_energy(edi, step);
963 update_adaption(edi);
965 /* Compute the flooding forces */
966 flood_forces(edi);
969 /* Translate them into cartesian positions */
970 flood_blowup(*edi, edi->flood.forces_cartesian);
972 /* Rotate forces back so that they correspond to the given structure and not to the fitted one */
973 /* Each node rotates back its local forces */
974 transpose(rotmat, tmat);
975 rotate_x(edi->flood.forces_cartesian, edi->sav.nr_loc, tmat);
977 /* Finally add forces to the main force variable */
978 for (i = 0; i < edi->sav.nr_loc; i++)
980 rvec_inc(force[edi->sav.anrs_loc[i]], edi->flood.forces_cartesian[i]);
983 /* Output is written by the master process */
984 if (do_per_step(step, edi->outfrq) && MASTER(cr))
986 /* Output how well we fit to the reference */
987 if (edi->bRefEqAv)
989 /* Indices of reference and average structures are identical,
990 * thus we can calculate the rmsd to SREF using xcoll */
991 rmsdev = rmsd_from_structure(buf->xcoll, &edi->sref);
993 else
995 /* We have to translate & rotate the reference atoms first */
996 translate_and_rotate(buf->xc_ref, edi->sref.nr, transvec, rotmat);
997 rmsdev = rmsd_from_structure(buf->xc_ref, &edi->sref);
1000 write_edo_flood(*edi, edo, rmsdev);
1005 /* Main flooding routine, called from do_force */
1006 extern void do_flood(const t_commrec *cr,
1007 const t_inputrec *ir,
1008 const rvec x[],
1009 rvec force[],
1010 gmx_edsam *ed,
1011 const matrix box,
1012 int64_t step,
1013 gmx_bool bNS)
1015 /* Write time to edo, when required. Output the time anyhow since we need
1016 * it in the output file for ED constraints. */
1017 if (MASTER(cr) && do_per_step(step, ed->edpar.begin()->outfrq))
1019 fprintf(ed->edo, "\n%12f", ir->init_t + step*ir->delta_t);
1022 if (ed->eEDtype != EssentialDynamicsType::Flooding)
1024 return;
1027 for (auto &edi : ed->edpar)
1029 /* Call flooding for one matrix */
1030 if (edi.flood.vecs.neig)
1032 do_single_flood(ed->edo, x, force, &edi, step, box, cr, bNS);
1038 /* Called by init_edi, configure some flooding related variables and structures,
1039 * print headers to output files */
1040 static void init_flood(t_edpar *edi, gmx_edsam * ed, real dt)
1042 int i;
1045 edi->flood.Efl = edi->flood.constEfl;
1046 edi->flood.Vfl = 0;
1047 edi->flood.dt = dt;
1049 if (edi->flood.vecs.neig)
1051 /* If in any of the ED groups we find a flooding vector, flooding is turned on */
1052 ed->eEDtype = EssentialDynamicsType::Flooding;
1054 fprintf(stderr, "ED: Flooding %d eigenvector%s.\n", edi->flood.vecs.neig, edi->flood.vecs.neig > 1 ? "s" : "");
1056 if (edi->flood.bConstForce)
1058 /* We have used stpsz as a vehicle to carry the fproj values for constant
1059 * force flooding. Now we copy that to flood.vecs.fproj. Note that
1060 * in const force flooding, fproj is never changed. */
1061 for (i = 0; i < edi->flood.vecs.neig; i++)
1063 edi->flood.vecs.fproj[i] = edi->flood.vecs.stpsz[i];
1065 fprintf(stderr, "ED: applying on eigenvector %d a constant force of %g\n",
1066 edi->flood.vecs.ieig[i], edi->flood.vecs.fproj[i]);
1073 #ifdef DEBUGHELPERS
1074 /*********** Energy book keeping ******/
1075 static void get_flood_enx_names(t_edpar *edi, char** names, int *nnames) /* get header of energies */
1077 t_edpar *actual;
1078 int count;
1079 char buf[STRLEN];
1080 actual = edi;
1081 count = 1;
1082 while (actual)
1084 srenew(names, count);
1085 sprintf(buf, "Vfl_%d", count);
1086 names[count-1] = gmx_strdup(buf);
1087 actual = actual->next_edi;
1088 count++;
1090 *nnames = count-1;
1094 static void get_flood_energies(t_edpar *edi, real Vfl[], int nnames)
1096 /*fl has to be big enough to capture nnames-many entries*/
1097 t_edpar *actual;
1098 int count;
1101 actual = edi;
1102 count = 1;
1103 while (actual)
1105 Vfl[count-1] = actual->flood.Vfl;
1106 actual = actual->next_edi;
1107 count++;
1109 if (nnames != count-1)
1111 gmx_fatal(FARGS, "Number of energies is not consistent with t_edi structure");
1114 /************* END of FLOODING IMPLEMENTATION ****************************/
1115 #endif
1118 /* This function opens the ED input and output files, reads in all datasets it finds
1119 * in the input file, and cross-checks whether the .edi file information is consistent
1120 * with the essential dynamics data found in the checkpoint file (if present).
1121 * gmx make_edi can be used to create an .edi input file.
1123 static std::unique_ptr<gmx::EssentialDynamics> ed_open(
1124 int natoms,
1125 ObservablesHistory *oh,
1126 const char *ediFileName,
1127 const char *edoFileName,
1128 const gmx::StartingBehavior startingBehavior,
1129 const gmx_output_env_t *oenv,
1130 const t_commrec *cr)
1132 auto edHandle = std::make_unique<gmx::EssentialDynamics>();
1133 auto ed = edHandle->getLegacyED();
1134 /* We want to perform ED (this switch might later be upgraded to EssentialDynamicsType::Flooding) */
1135 ed->eEDtype = EssentialDynamicsType::EDSampling;
1137 if (MASTER(cr))
1139 // If we start from a checkpoint file, we already have an edsamHistory struct
1140 if (oh->edsamHistory == nullptr)
1142 oh->edsamHistory = std::make_unique<edsamhistory_t>(edsamhistory_t {});
1144 edsamhistory_t *EDstate = oh->edsamHistory.get();
1146 /* Read the edi input file: */
1147 ed->edpar = read_edi_file(ediFileName, natoms);
1149 /* Make sure the checkpoint was produced in a run using this .edi file */
1150 if (EDstate->bFromCpt)
1152 crosscheck_edi_file_vs_checkpoint(*ed, EDstate);
1154 else
1156 EDstate->nED = ed->edpar.size();
1158 init_edsamstate(*ed, EDstate);
1160 /* The master opens the ED output file */
1161 if (startingBehavior == gmx::StartingBehavior::RestartWithAppending)
1163 ed->edo = gmx_fio_fopen(edoFileName, "a+");
1165 else
1167 ed->edo = xvgropen(edoFileName,
1168 "Essential dynamics / flooding output",
1169 "Time (ps)",
1170 "RMSDs (nm), projections on EVs (nm), ...", oenv);
1172 /* Make a descriptive legend */
1173 write_edo_legend(ed, EDstate->nED, oenv);
1176 return edHandle;
1180 /* Broadcasts the structure data */
1181 static void bc_ed_positions(const t_commrec *cr, struct gmx_edx *s, EssentialDynamicsStructure stype)
1183 snew_bc(cr, s->anrs, s->nr ); /* Index numbers */
1184 snew_bc(cr, s->x, s->nr ); /* Positions */
1185 nblock_bc(cr, s->nr, s->anrs );
1186 nblock_bc(cr, s->nr, s->x );
1188 /* For the average & reference structures we need an array for the collective indices,
1189 * and we need to broadcast the masses as well */
1190 if (stype == EssentialDynamicsStructure::Average || stype == EssentialDynamicsStructure::Reference)
1192 /* We need these additional variables in the parallel case: */
1193 snew(s->c_ind, s->nr ); /* Collective indices */
1194 /* Local atom indices get assigned in dd_make_local_group_indices.
1195 * There, also memory is allocated */
1196 s->nalloc_loc = 0; /* allocation size of s->anrs_loc */
1197 snew_bc(cr, s->x_old, s->nr); /* To be able to always make the ED molecule whole, ... */
1198 nblock_bc(cr, s->nr, s->x_old); /* ... keep track of shift changes with the help of old coords */
1201 /* broadcast masses for the reference structure (for mass-weighted fitting) */
1202 if (stype == EssentialDynamicsStructure::Reference)
1204 snew_bc(cr, s->m, s->nr);
1205 nblock_bc(cr, s->nr, s->m);
1208 /* For the average structure we might need the masses for mass-weighting */
1209 if (stype == EssentialDynamicsStructure::Average)
1211 snew_bc(cr, s->sqrtm, s->nr);
1212 nblock_bc(cr, s->nr, s->sqrtm);
1213 snew_bc(cr, s->m, s->nr);
1214 nblock_bc(cr, s->nr, s->m);
1219 /* Broadcasts the eigenvector data */
1220 static void bc_ed_vecs(const t_commrec *cr, t_eigvec *ev, int length)
1222 int i;
1224 snew_bc(cr, ev->ieig, ev->neig); /* index numbers of eigenvector */
1225 snew_bc(cr, ev->stpsz, ev->neig); /* stepsizes per eigenvector */
1226 snew_bc(cr, ev->xproj, ev->neig); /* instantaneous x projection */
1227 snew_bc(cr, ev->fproj, ev->neig); /* instantaneous f projection */
1228 snew_bc(cr, ev->refproj, ev->neig); /* starting or target projection */
1230 nblock_bc(cr, ev->neig, ev->ieig );
1231 nblock_bc(cr, ev->neig, ev->stpsz );
1232 nblock_bc(cr, ev->neig, ev->xproj );
1233 nblock_bc(cr, ev->neig, ev->fproj );
1234 nblock_bc(cr, ev->neig, ev->refproj);
1236 snew_bc(cr, ev->vec, ev->neig); /* Eigenvector components */
1237 for (i = 0; i < ev->neig; i++)
1239 snew_bc(cr, ev->vec[i], length);
1240 nblock_bc(cr, length, ev->vec[i]);
1246 /* Broadcasts the ED / flooding data to other nodes
1247 * and allocates memory where needed */
1248 static void broadcast_ed_data(const t_commrec *cr, gmx_edsam * ed)
1250 /* Master lets the other nodes know if its ED only or also flooding */
1251 gmx_bcast(sizeof(ed->eEDtype), &(ed->eEDtype), cr);
1253 int numedis = ed->edpar.size();
1254 /* First let everybody know how many ED data sets to expect */
1255 gmx_bcast(sizeof(numedis), &numedis, cr);
1256 nblock_abc(cr, numedis, &(ed->edpar));
1257 /* Now transfer the ED data set(s) */
1258 for (auto &edi : ed->edpar)
1260 /* Broadcast a single ED data set */
1261 block_bc(cr, edi);
1263 /* Broadcast positions */
1264 bc_ed_positions(cr, &(edi.sref), EssentialDynamicsStructure::Reference); /* reference positions (don't broadcast masses) */
1265 bc_ed_positions(cr, &(edi.sav ), EssentialDynamicsStructure::Average ); /* average positions (do broadcast masses as well) */
1266 bc_ed_positions(cr, &(edi.star), EssentialDynamicsStructure::Target); /* target positions */
1267 bc_ed_positions(cr, &(edi.sori), EssentialDynamicsStructure::Origin); /* origin positions */
1269 /* Broadcast eigenvectors */
1270 bc_ed_vecs(cr, &edi.vecs.mon, edi.sav.nr);
1271 bc_ed_vecs(cr, &edi.vecs.linfix, edi.sav.nr);
1272 bc_ed_vecs(cr, &edi.vecs.linacc, edi.sav.nr);
1273 bc_ed_vecs(cr, &edi.vecs.radfix, edi.sav.nr);
1274 bc_ed_vecs(cr, &edi.vecs.radacc, edi.sav.nr);
1275 bc_ed_vecs(cr, &edi.vecs.radcon, edi.sav.nr);
1276 /* Broadcast flooding eigenvectors and, if needed, values for the moving reference */
1277 bc_ed_vecs(cr, &edi.flood.vecs, edi.sav.nr);
1279 /* For harmonic restraints the reference projections can change with time */
1280 if (edi.flood.bHarmonic)
1282 snew_bc(cr, edi.flood.initialReferenceProjection, edi.flood.vecs.neig);
1283 snew_bc(cr, edi.flood.referenceProjectionSlope, edi.flood.vecs.neig);
1284 nblock_bc(cr, edi.flood.vecs.neig, edi.flood.initialReferenceProjection);
1285 nblock_bc(cr, edi.flood.vecs.neig, edi.flood.referenceProjectionSlope);
1291 /* init-routine called for every *.edi-cycle, initialises t_edpar structure */
1292 static void init_edi(const gmx_mtop_t *mtop, t_edpar *edi)
1294 int i;
1295 real totalmass = 0.0;
1296 rvec com;
1298 /* NOTE Init_edi is executed on the master process only
1299 * The initialized data sets are then transmitted to the
1300 * other nodes in broadcast_ed_data */
1302 /* evaluate masses (reference structure) */
1303 snew(edi->sref.m, edi->sref.nr);
1304 int molb = 0;
1305 for (i = 0; i < edi->sref.nr; i++)
1307 if (edi->fitmas)
1309 edi->sref.m[i] = mtopGetAtomMass(mtop, edi->sref.anrs[i], &molb);
1311 else
1313 edi->sref.m[i] = 1.0;
1316 /* Check that every m > 0. Bad things will happen otherwise. */
1317 if (edi->sref.m[i] <= 0.0)
1319 gmx_fatal(FARGS, "Reference structure atom %d (sam.edi index %d) has a mass of %g.\n"
1320 "For a mass-weighted fit, all reference structure atoms need to have a mass >0.\n"
1321 "Either make the covariance analysis non-mass-weighted, or exclude massless\n"
1322 "atoms from the reference structure by creating a proper index group.\n",
1323 i, edi->sref.anrs[i]+1, edi->sref.m[i]);
1326 totalmass += edi->sref.m[i];
1328 edi->sref.mtot = totalmass;
1330 /* Masses m and sqrt(m) for the average structure. Note that m
1331 * is needed if forces have to be evaluated in do_edsam */
1332 snew(edi->sav.sqrtm, edi->sav.nr );
1333 snew(edi->sav.m, edi->sav.nr );
1334 for (i = 0; i < edi->sav.nr; i++)
1336 edi->sav.m[i] = mtopGetAtomMass(mtop, edi->sav.anrs[i], &molb);
1337 if (edi->pcamas)
1339 edi->sav.sqrtm[i] = sqrt(edi->sav.m[i]);
1341 else
1343 edi->sav.sqrtm[i] = 1.0;
1346 /* Check that every m > 0. Bad things will happen otherwise. */
1347 if (edi->sav.sqrtm[i] <= 0.0)
1349 gmx_fatal(FARGS, "Average structure atom %d (sam.edi index %d) has a mass of %g.\n"
1350 "For ED with mass-weighting, all average structure atoms need to have a mass >0.\n"
1351 "Either make the covariance analysis non-mass-weighted, or exclude massless\n"
1352 "atoms from the average structure by creating a proper index group.\n",
1353 i, edi->sav.anrs[i] + 1, edi->sav.m[i]);
1357 /* put reference structure in origin */
1358 get_center(edi->sref.x, edi->sref.m, edi->sref.nr, com);
1359 com[XX] = -com[XX];
1360 com[YY] = -com[YY];
1361 com[ZZ] = -com[ZZ];
1362 translate_x(edi->sref.x, edi->sref.nr, com);
1364 /* Init ED buffer */
1365 snew(edi->buf, 1);
1369 static void check(const char *line, const char *label)
1371 if (!strstr(line, label))
1373 gmx_fatal(FARGS, "Could not find input parameter %s at expected position in edsam input-file (.edi)\nline read instead is %s", label, line);
1378 static int read_checked_edint(FILE *file, const char *label)
1380 char line[STRLEN+1];
1381 int idum;
1383 fgets2 (line, STRLEN, file);
1384 check(line, label);
1385 fgets2 (line, STRLEN, file);
1386 sscanf (line, max_ev_fmt_d, &idum);
1387 return idum;
1390 static bool read_checked_edbool(FILE *file, const char *label)
1392 return read_checked_edint(file, label) != 0;
1395 static int read_edint(FILE *file, bool *bEOF)
1397 char line[STRLEN+1];
1398 int idum;
1399 char *eof;
1402 eof = fgets2 (line, STRLEN, file);
1403 if (eof == nullptr)
1405 *bEOF = TRUE;
1406 return -1;
1408 eof = fgets2 (line, STRLEN, file);
1409 if (eof == nullptr)
1411 *bEOF = TRUE;
1412 return -1;
1414 sscanf (line, max_ev_fmt_d, &idum);
1415 *bEOF = FALSE;
1416 return idum;
1420 static real read_checked_edreal(FILE *file, const char *label)
1422 char line[STRLEN+1];
1423 double rdum;
1426 fgets2 (line, STRLEN, file);
1427 check(line, label);
1428 fgets2 (line, STRLEN, file);
1429 sscanf (line, max_ev_fmt_lf, &rdum);
1430 return static_cast<real>(rdum); /* always read as double and convert to single */
1434 static void read_edx(FILE *file, int number, int *anrs, rvec *x)
1436 int i, j;
1437 char line[STRLEN+1];
1438 double d[3];
1441 for (i = 0; i < number; i++)
1443 fgets2 (line, STRLEN, file);
1444 sscanf (line, max_ev_fmt_dlflflf, &anrs[i], &d[0], &d[1], &d[2]);
1445 anrs[i]--; /* we are reading FORTRAN indices */
1446 for (j = 0; j < 3; j++)
1448 x[i][j] = d[j]; /* always read as double and convert to single */
1453 namespace
1455 /*!\brief Read eigenvector coordinates for multiple eigenvectors from a file.
1456 * \param[in] in the file to read from
1457 * \param[in] numAtoms the number of atoms/coordinates for the eigenvector
1458 * \param[out] vec the eigen-vectors
1459 * \param[in] nEig the number of eigenvectors
1461 void scan_edvec(FILE *in, int numAtoms, rvec ***vec, int nEig)
1463 snew(*vec, nEig);
1464 for (int iEigenvector = 0; iEigenvector < nEig; iEigenvector++)
1466 snew((*vec)[iEigenvector], numAtoms);
1467 for (int iAtom = 0; iAtom < numAtoms; iAtom++)
1469 char line[STRLEN+1];
1470 double x, y, z;
1471 fgets2(line, STRLEN, in);
1472 sscanf(line, max_ev_fmt_lelele, &x, &y, &z);
1473 (*vec)[iEigenvector][iAtom][XX] = x;
1474 (*vec)[iEigenvector][iAtom][YY] = y;
1475 (*vec)[iEigenvector][iAtom][ZZ] = z;
1480 /*!\brief Read an essential dynamics eigenvector and corresponding step size.
1481 * \param[in] in input file
1482 * \param[in] nrAtoms number of atoms/coordinates
1483 * \param[out] tvec the eigenvector
1485 void read_edvec(FILE *in, int nrAtoms, t_eigvec *tvec)
1487 tvec->neig = read_checked_edint(in, "NUMBER OF EIGENVECTORS");
1488 if (tvec->neig <= 0)
1490 return;
1493 snew(tvec->ieig, tvec->neig);
1494 snew(tvec->stpsz, tvec->neig);
1495 for (int i = 0; i < tvec->neig; i++)
1497 char line[STRLEN+1];
1498 fgets2(line, STRLEN, in);
1499 int numEigenVectors;
1500 double stepSize;
1501 const int nscan = sscanf(line, max_ev_fmt_dlf, &numEigenVectors, &stepSize);
1502 if (nscan != 2)
1504 gmx_fatal(FARGS, "Expected 2 values for flooding vec: <nr> <stpsz>\n");
1506 tvec->ieig[i] = numEigenVectors;
1507 tvec->stpsz[i] = stepSize;
1508 } /* end of loop over eigenvectors */
1510 scan_edvec(in, nrAtoms, &tvec->vec, tvec->neig);
1512 /*!\brief Read an essential dynamics eigenvector and intial reference projections and slopes if available.
1514 * Eigenvector and its intial reference and slope are stored on the
1515 * same line in the .edi format. To avoid re-winding the .edi file,
1516 * the reference eigen-vector and reference data are read in one go.
1518 * \param[in] in input file
1519 * \param[in] nrAtoms number of atoms/coordinates
1520 * \param[out] tvec the eigenvector
1521 * \param[out] initialReferenceProjection The projection onto eigenvectors as read from file.
1522 * \param[out] referenceProjectionSlope The slope of the reference projections.
1524 bool readEdVecWithReferenceProjection(FILE *in, int nrAtoms, t_eigvec *tvec, real ** initialReferenceProjection, real ** referenceProjectionSlope)
1526 bool providesReference = false;
1527 tvec->neig = read_checked_edint(in, "NUMBER OF EIGENVECTORS");
1528 if (tvec->neig <= 0)
1530 return false;
1533 snew(tvec->ieig, tvec->neig);
1534 snew(tvec->stpsz, tvec->neig);
1535 snew(*initialReferenceProjection, tvec->neig);
1536 snew(*referenceProjectionSlope, tvec->neig);
1537 for (int i = 0; i < tvec->neig; i++)
1539 char line[STRLEN+1];
1540 fgets2 (line, STRLEN, in);
1541 int numEigenVectors;
1542 double stepSize = 0.;
1543 double referenceProjection = 0.;
1544 double referenceSlope = 0.;
1545 const int nscan = sscanf(line, max_ev_fmt_dlflflf, &numEigenVectors, &stepSize, &referenceProjection, &referenceSlope);
1546 /* Zero out values which were not scanned */
1547 switch (nscan)
1549 case 4:
1550 /* Every 4 values read, including reference position */
1551 providesReference = true;
1552 break;
1553 case 3:
1554 /* A reference position is provided */
1555 providesReference = true;
1556 /* No value for slope, set to 0 */
1557 referenceSlope = 0.0;
1558 break;
1559 case 2:
1560 /* No values for reference projection and slope, set to 0 */
1561 referenceProjection = 0.0;
1562 referenceSlope = 0.0;
1563 break;
1564 default:
1565 gmx_fatal(FARGS, "Expected 2 - 4 (not %d) values for flooding vec: <nr> <spring const> <refproj> <refproj-slope>\n", nscan);
1567 (*initialReferenceProjection)[i] = referenceProjection;
1568 (*referenceProjectionSlope)[i] = referenceSlope;
1570 tvec->ieig[i] = numEigenVectors;
1571 tvec->stpsz[i] = stepSize;
1572 } /* end of loop over eigenvectors */
1574 scan_edvec(in, nrAtoms, &tvec->vec, tvec->neig);
1575 return providesReference;
1578 /*!\brief Allocate working memory for the eigenvectors.
1579 * \param[in,out] tvec eigenvector for which memory will be allocated
1581 void setup_edvec(t_eigvec *tvec)
1583 snew(tvec->xproj, tvec->neig);
1584 snew(tvec->fproj, tvec->neig);
1585 snew(tvec->refproj, tvec->neig);
1587 } // namespace
1590 /* Check if the same atom indices are used for reference and average positions */
1591 static gmx_bool check_if_same(struct gmx_edx sref, struct gmx_edx sav)
1593 int i;
1596 /* If the number of atoms differs between the two structures,
1597 * they cannot be identical */
1598 if (sref.nr != sav.nr)
1600 return FALSE;
1603 /* Now that we know that both stuctures have the same number of atoms,
1604 * check if also the indices are identical */
1605 for (i = 0; i < sav.nr; i++)
1607 if (sref.anrs[i] != sav.anrs[i])
1609 return FALSE;
1612 fprintf(stderr, "ED: Note: Reference and average structure are composed of the same atom indices.\n");
1614 return TRUE;
1617 namespace
1620 //! Oldest (lowest) magic number indicating unsupported essential dynamics input
1621 constexpr int c_oldestUnsupportedMagicNumber = 666;
1622 //! Oldest (lowest) magic number indicating supported essential dynamics input
1623 constexpr int c_oldestSupportedMagicNumber = 669;
1624 //! Latest (highest) magic number indicating supported essential dynamics input
1625 constexpr int c_latestSupportedMagicNumber = 670;
1627 /*!\brief Set up essential dynamics work parameters.
1628 * \param[in] edi Essential dynamics working structure.
1630 void setup_edi(t_edpar *edi)
1632 snew(edi->sref.x_old, edi->sref.nr);
1633 edi->sref.sqrtm = nullptr;
1634 snew(edi->sav.x_old, edi->sav.nr);
1635 if (edi->star.nr > 0)
1637 edi->star.sqrtm = nullptr;
1639 if (edi->sori.nr > 0)
1641 edi->sori.sqrtm = nullptr;
1643 setup_edvec(&edi->vecs.linacc);
1644 setup_edvec(&edi->vecs.mon);
1645 setup_edvec(&edi->vecs.linfix);
1646 setup_edvec(&edi->vecs.linacc);
1647 setup_edvec(&edi->vecs.radfix);
1648 setup_edvec(&edi->vecs.radacc);
1649 setup_edvec(&edi->vecs.radcon);
1650 setup_edvec(&edi->flood.vecs);
1653 /*!\brief Check if edi file version supports CONST_FORCE_FLOODING.
1654 * \param[in] magicNumber indicates the essential dynamics input file version
1655 * \returns true if CONST_FORCE_FLOODING is supported
1657 bool ediFileHasConstForceFlooding(int magicNumber)
1659 return magicNumber > c_oldestSupportedMagicNumber;
1662 /*!\brief Reports reading success of the essential dynamics input file magic number.
1663 * \param[in] in pointer to input file
1664 * \param[out] magicNumber determines the edi file version
1665 * \returns true if setting file version from input file was successful.
1667 bool ediFileHasValidDataSet(FILE *in, int * magicNumber)
1669 /* the edi file is not free format, so expect problems if the input is corrupt. */
1670 bool reachedEndOfFile = true;
1671 /* check the magic number */
1672 *magicNumber = read_edint(in, &reachedEndOfFile);
1673 /* Check whether we have reached the end of the input file */
1674 return !reachedEndOfFile;
1677 /*!\brief Trigger fatal error if magic number is unsupported.
1678 * \param[in] magicNumber A magic number read from the edi file
1679 * \param[in] fn name of input file for error reporting
1681 void exitWhenMagicNumberIsInvalid(int magicNumber, const char * fn)
1684 if (magicNumber < c_oldestSupportedMagicNumber || magicNumber > c_latestSupportedMagicNumber)
1686 if (magicNumber >= c_oldestUnsupportedMagicNumber && magicNumber < c_oldestSupportedMagicNumber)
1688 gmx_fatal(FARGS, "Wrong magic number: Use newest version of make_edi to produce edi file");
1690 else
1692 gmx_fatal(FARGS, "Wrong magic number %d in %s", magicNumber, fn);
1697 /*!\brief reads an essential dynamics input file into a essential dynamics data structure.
1699 * \param[in] in input file
1700 * \param[in] nr_mdatoms the number of md atoms, used for consistency checking
1701 * \param[in] hasConstForceFlooding determines if field "CONST_FORCE_FLOODING" is available in input file
1702 * \param[in] fn the file name of the input file for error reporting
1703 * \returns edi essential dynamics parameters
1705 t_edpar read_edi(FILE* in, int nr_mdatoms, bool hasConstForceFlooding, const char *fn)
1707 t_edpar edi;
1708 bool bEOF;
1709 /* check the number of atoms */
1710 edi.nini = read_edint(in, &bEOF);
1711 if (edi.nini != nr_mdatoms)
1713 gmx_fatal(FARGS, "Nr of atoms in %s (%d) does not match nr of md atoms (%d)", fn, edi.nini, nr_mdatoms);
1716 /* Done checking. For the rest we blindly trust the input */
1717 edi.fitmas = read_checked_edbool(in, "FITMAS");
1718 edi.pcamas = read_checked_edbool(in, "ANALYSIS_MAS");
1719 edi.outfrq = read_checked_edint(in, "OUTFRQ");
1720 edi.maxedsteps = read_checked_edint(in, "MAXLEN");
1721 edi.slope = read_checked_edreal(in, "SLOPECRIT");
1723 edi.presteps = read_checked_edint(in, "PRESTEPS");
1724 edi.flood.deltaF0 = read_checked_edreal(in, "DELTA_F0");
1725 edi.flood.deltaF = read_checked_edreal(in, "INIT_DELTA_F");
1726 edi.flood.tau = read_checked_edreal(in, "TAU");
1727 edi.flood.constEfl = read_checked_edreal(in, "EFL_NULL");
1728 edi.flood.alpha2 = read_checked_edreal(in, "ALPHA2");
1729 edi.flood.kT = read_checked_edreal(in, "KT");
1730 edi.flood.bHarmonic = read_checked_edbool(in, "HARMONIC");
1731 if (hasConstForceFlooding)
1733 edi.flood.bConstForce = read_checked_edbool(in, "CONST_FORCE_FLOODING");
1735 else
1737 edi.flood.bConstForce = FALSE;
1739 edi.sref.nr = read_checked_edint(in, "NREF");
1741 /* allocate space for reference positions and read them */
1742 snew(edi.sref.anrs, edi.sref.nr);
1743 snew(edi.sref.x, edi.sref.nr);
1744 read_edx(in, edi.sref.nr, edi.sref.anrs, edi.sref.x);
1746 /* average positions. they define which atoms will be used for ED sampling */
1747 edi.sav.nr = read_checked_edint(in, "NAV");
1748 snew(edi.sav.anrs, edi.sav.nr);
1749 snew(edi.sav.x, edi.sav.nr);
1750 read_edx(in, edi.sav.nr, edi.sav.anrs, edi.sav.x);
1752 /* Check if the same atom indices are used for reference and average positions */
1753 edi.bRefEqAv = check_if_same(edi.sref, edi.sav);
1755 /* eigenvectors */
1757 read_edvec(in, edi.sav.nr, &edi.vecs.mon);
1758 read_edvec(in, edi.sav.nr, &edi.vecs.linfix);
1759 read_edvec(in, edi.sav.nr, &edi.vecs.linacc);
1760 read_edvec(in, edi.sav.nr, &edi.vecs.radfix);
1761 read_edvec(in, edi.sav.nr, &edi.vecs.radacc);
1762 read_edvec(in, edi.sav.nr, &edi.vecs.radcon);
1764 /* Was a specific reference point for the flooding/umbrella potential provided in the edi file? */
1765 bool bHaveReference = false;
1766 if (edi.flood.bHarmonic)
1768 bHaveReference = readEdVecWithReferenceProjection(in, edi.sav.nr, &edi.flood.vecs, &edi.flood.initialReferenceProjection, &edi.flood.referenceProjectionSlope);
1770 else
1772 read_edvec(in, edi.sav.nr, &edi.flood.vecs);
1775 /* target positions */
1776 edi.star.nr = read_edint(in, &bEOF);
1777 if (edi.star.nr > 0)
1779 snew(edi.star.anrs, edi.star.nr);
1780 snew(edi.star.x, edi.star.nr);
1781 read_edx(in, edi.star.nr, edi.star.anrs, edi.star.x);
1784 /* positions defining origin of expansion circle */
1785 edi.sori.nr = read_edint(in, &bEOF);
1786 if (edi.sori.nr > 0)
1788 if (bHaveReference)
1790 /* Both an -ori structure and a at least one manual reference point have been
1791 * specified. That's ambiguous and probably not intentional. */
1792 gmx_fatal(FARGS, "ED: An origin structure has been provided and a at least one (moving) reference\n"
1793 " point was manually specified in the edi file. That is ambiguous. Aborting.\n");
1795 snew(edi.sori.anrs, edi.sori.nr);
1796 snew(edi.sori.x, edi.sori.nr);
1797 read_edx(in, edi.sori.nr, edi.sori.anrs, edi.sori.x);
1799 return edi;
1802 std::vector<t_edpar> read_edi_file(const char *fn, int nr_mdatoms)
1804 std::vector<t_edpar> essentialDynamicsParameters;
1805 FILE *in;
1806 /* This routine is executed on the master only */
1808 /* Open the .edi parameter input file */
1809 in = gmx_fio_fopen(fn, "r");
1810 fprintf(stderr, "ED: Reading edi file %s\n", fn);
1812 /* Now read a sequence of ED input parameter sets from the edi file */
1813 int ediFileMagicNumber;
1814 while (ediFileHasValidDataSet(in, &ediFileMagicNumber))
1816 exitWhenMagicNumberIsInvalid(ediFileMagicNumber, fn);
1817 bool hasConstForceFlooding = ediFileHasConstForceFlooding(ediFileMagicNumber);
1818 auto edi = read_edi(in, nr_mdatoms, hasConstForceFlooding, fn);
1819 setup_edi(&edi);
1820 essentialDynamicsParameters.emplace_back(edi);
1822 /* Since we arrived within this while loop we know that there is still another data set to be read in */
1823 /* We need to allocate space for the data: */
1825 if (essentialDynamicsParameters.empty())
1827 gmx_fatal(FARGS, "No complete ED data set found in edi file %s.", fn);
1830 fprintf(stderr, "ED: Found %zu ED group%s.\n", essentialDynamicsParameters.size(), essentialDynamicsParameters.size() > 1 ? "s" : "");
1832 /* Close the .edi file again */
1833 gmx_fio_fclose(in);
1835 return essentialDynamicsParameters;
1837 } // anonymous namespace
1840 struct t_fit_to_ref {
1841 rvec *xcopy; /* Working copy of the positions in fit_to_reference */
1844 /* Fit the current positions to the reference positions
1845 * Do not actually do the fit, just return rotation and translation.
1846 * Note that the COM of the reference structure was already put into
1847 * the origin by init_edi. */
1848 static void fit_to_reference(rvec *xcoll, /* The positions to be fitted */
1849 rvec transvec, /* The translation vector */
1850 matrix rotmat, /* The rotation matrix */
1851 t_edpar *edi) /* Just needed for do_edfit */
1853 rvec com; /* center of mass */
1854 int i;
1855 struct t_fit_to_ref *loc;
1858 /* Allocate memory the first time this routine is called for each edi group */
1859 if (nullptr == edi->buf->fit_to_ref)
1861 snew(edi->buf->fit_to_ref, 1);
1862 snew(edi->buf->fit_to_ref->xcopy, edi->sref.nr);
1864 loc = edi->buf->fit_to_ref;
1866 /* We do not touch the original positions but work on a copy. */
1867 for (i = 0; i < edi->sref.nr; i++)
1869 copy_rvec(xcoll[i], loc->xcopy[i]);
1872 /* Calculate the center of mass */
1873 get_center(loc->xcopy, edi->sref.m, edi->sref.nr, com);
1875 transvec[XX] = -com[XX];
1876 transvec[YY] = -com[YY];
1877 transvec[ZZ] = -com[ZZ];
1879 /* Subtract the center of mass from the copy */
1880 translate_x(loc->xcopy, edi->sref.nr, transvec);
1882 /* Determine the rotation matrix */
1883 do_edfit(edi->sref.nr, edi->sref.x, loc->xcopy, rotmat, edi);
1887 static void translate_and_rotate(rvec *x, /* The positions to be translated and rotated */
1888 int nat, /* How many positions are there? */
1889 rvec transvec, /* The translation vector */
1890 matrix rotmat) /* The rotation matrix */
1892 /* Translation */
1893 translate_x(x, nat, transvec);
1895 /* Rotation */
1896 rotate_x(x, nat, rotmat);
1900 /* Gets the rms deviation of the positions to the structure s */
1901 /* fit_to_structure has to be called before calling this routine! */
1902 static real rmsd_from_structure(rvec *x, /* The positions under consideration */
1903 struct gmx_edx *s) /* The structure from which the rmsd shall be computed */
1905 real rmsd = 0.0;
1906 int i;
1909 for (i = 0; i < s->nr; i++)
1911 rmsd += distance2(s->x[i], x[i]);
1914 rmsd /= static_cast<real>(s->nr);
1915 rmsd = sqrt(rmsd);
1917 return rmsd;
1921 void dd_make_local_ed_indices(gmx_domdec_t *dd, struct gmx_edsam *ed)
1923 if (ed->eEDtype != EssentialDynamicsType::None)
1925 /* Loop over ED groups */
1927 for (auto &edi : ed->edpar)
1929 /* Local atoms of the reference structure (for fitting), need only be assembled
1930 * if their indices differ from the average ones */
1931 if (!edi.bRefEqAv)
1933 dd_make_local_group_indices(dd->ga2la, edi.sref.nr, edi.sref.anrs,
1934 &edi.sref.nr_loc, &edi.sref.anrs_loc, &edi.sref.nalloc_loc, edi.sref.c_ind);
1937 /* Local atoms of the average structure (on these ED will be performed) */
1938 dd_make_local_group_indices(dd->ga2la, edi.sav.nr, edi.sav.anrs,
1939 &edi.sav.nr_loc, &edi.sav.anrs_loc, &edi.sav.nalloc_loc, edi.sav.c_ind);
1941 /* Indicate that the ED shift vectors for this structure need to be updated
1942 * at the next call to communicate_group_positions, since obviously we are in a NS step */
1943 edi.buf->do_edsam->bUpdateShifts = TRUE;
1949 static inline void ed_unshift_single_coord(const matrix box, const rvec x, const ivec is, rvec xu)
1951 int tx, ty, tz;
1954 tx = is[XX];
1955 ty = is[YY];
1956 tz = is[ZZ];
1958 if (TRICLINIC(box))
1960 xu[XX] = x[XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
1961 xu[YY] = x[YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
1962 xu[ZZ] = x[ZZ]-tz*box[ZZ][ZZ];
1964 else
1966 xu[XX] = x[XX]-tx*box[XX][XX];
1967 xu[YY] = x[YY]-ty*box[YY][YY];
1968 xu[ZZ] = x[ZZ]-tz*box[ZZ][ZZ];
1972 namespace
1974 /*!\brief Apply fixed linear constraints to essential dynamics variable.
1975 * \param[in,out] xcoll The collected coordinates.
1976 * \param[in] edi the essential dynamics parameters
1977 * \param[in] step the current simulation step
1979 void do_linfix(rvec *xcoll, const t_edpar &edi, int64_t step)
1981 /* loop over linfix vectors */
1982 for (int i = 0; i < edi.vecs.linfix.neig; i++)
1984 /* calculate the projection */
1985 real proj = projectx(edi, xcoll, edi.vecs.linfix.vec[i]);
1987 /* calculate the correction */
1988 real preFactor = edi.vecs.linfix.refproj[i] + step*edi.vecs.linfix.stpsz[i] - proj;
1990 /* apply the correction */
1991 preFactor /= edi.sav.sqrtm[i];
1992 for (int j = 0; j < edi.sav.nr; j++)
1994 rvec differenceVector;
1995 svmul(preFactor, edi.vecs.linfix.vec[i][j], differenceVector);
1996 rvec_inc(xcoll[j], differenceVector);
2001 /*!\brief Apply acceptance linear constraints to essential dynamics variable.
2002 * \param[in,out] xcoll The collected coordinates.
2003 * \param[in] edi the essential dynamics parameters
2005 void do_linacc(rvec *xcoll, t_edpar *edi)
2007 /* loop over linacc vectors */
2008 for (int i = 0; i < edi->vecs.linacc.neig; i++)
2010 /* calculate the projection */
2011 real proj = projectx(*edi, xcoll, edi->vecs.linacc.vec[i]);
2013 /* calculate the correction */
2014 real preFactor = 0.0;
2015 if (edi->vecs.linacc.stpsz[i] > 0.0)
2017 if ((proj-edi->vecs.linacc.refproj[i]) < 0.0)
2019 preFactor = edi->vecs.linacc.refproj[i] - proj;
2022 if (edi->vecs.linacc.stpsz[i] < 0.0)
2024 if ((proj-edi->vecs.linacc.refproj[i]) > 0.0)
2026 preFactor = edi->vecs.linacc.refproj[i] - proj;
2030 /* apply the correction */
2031 preFactor /= edi->sav.sqrtm[i];
2032 for (int j = 0; j < edi->sav.nr; j++)
2034 rvec differenceVector;
2035 svmul(preFactor, edi->vecs.linacc.vec[i][j], differenceVector);
2036 rvec_inc(xcoll[j], differenceVector);
2039 /* new positions will act as reference */
2040 edi->vecs.linacc.refproj[i] = proj + preFactor;
2043 } // namespace
2046 static void do_radfix(rvec *xcoll, t_edpar *edi)
2048 int i, j;
2049 real *proj, rad = 0.0, ratio;
2050 rvec vec_dum;
2053 if (edi->vecs.radfix.neig == 0)
2055 return;
2058 snew(proj, edi->vecs.radfix.neig);
2060 /* loop over radfix vectors */
2061 for (i = 0; i < edi->vecs.radfix.neig; i++)
2063 /* calculate the projections, radius */
2064 proj[i] = projectx(*edi, xcoll, edi->vecs.radfix.vec[i]);
2065 rad += gmx::square(proj[i] - edi->vecs.radfix.refproj[i]);
2068 rad = sqrt(rad);
2069 ratio = (edi->vecs.radfix.stpsz[0]+edi->vecs.radfix.radius)/rad - 1.0;
2070 edi->vecs.radfix.radius += edi->vecs.radfix.stpsz[0];
2072 /* loop over radfix vectors */
2073 for (i = 0; i < edi->vecs.radfix.neig; i++)
2075 proj[i] -= edi->vecs.radfix.refproj[i];
2077 /* apply the correction */
2078 proj[i] /= edi->sav.sqrtm[i];
2079 proj[i] *= ratio;
2080 for (j = 0; j < edi->sav.nr; j++)
2082 svmul(proj[i], edi->vecs.radfix.vec[i][j], vec_dum);
2083 rvec_inc(xcoll[j], vec_dum);
2087 sfree(proj);
2091 static void do_radacc(rvec *xcoll, t_edpar *edi)
2093 int i, j;
2094 real *proj, rad = 0.0, ratio = 0.0;
2095 rvec vec_dum;
2098 if (edi->vecs.radacc.neig == 0)
2100 return;
2103 snew(proj, edi->vecs.radacc.neig);
2105 /* loop over radacc vectors */
2106 for (i = 0; i < edi->vecs.radacc.neig; i++)
2108 /* calculate the projections, radius */
2109 proj[i] = projectx(*edi, xcoll, edi->vecs.radacc.vec[i]);
2110 rad += gmx::square(proj[i] - edi->vecs.radacc.refproj[i]);
2112 rad = sqrt(rad);
2114 /* only correct when radius decreased */
2115 if (rad < edi->vecs.radacc.radius)
2117 ratio = edi->vecs.radacc.radius/rad - 1.0;
2119 else
2121 edi->vecs.radacc.radius = rad;
2124 /* loop over radacc vectors */
2125 for (i = 0; i < edi->vecs.radacc.neig; i++)
2127 proj[i] -= edi->vecs.radacc.refproj[i];
2129 /* apply the correction */
2130 proj[i] /= edi->sav.sqrtm[i];
2131 proj[i] *= ratio;
2132 for (j = 0; j < edi->sav.nr; j++)
2134 svmul(proj[i], edi->vecs.radacc.vec[i][j], vec_dum);
2135 rvec_inc(xcoll[j], vec_dum);
2138 sfree(proj);
2142 struct t_do_radcon {
2143 real *proj;
2146 static void do_radcon(rvec *xcoll, t_edpar *edi)
2148 int i, j;
2149 real rad = 0.0, ratio = 0.0;
2150 struct t_do_radcon *loc;
2151 gmx_bool bFirst;
2152 rvec vec_dum;
2155 if (edi->buf->do_radcon != nullptr)
2157 bFirst = FALSE;
2159 else
2161 bFirst = TRUE;
2162 snew(edi->buf->do_radcon, 1);
2164 loc = edi->buf->do_radcon;
2166 if (edi->vecs.radcon.neig == 0)
2168 return;
2171 if (bFirst)
2173 snew(loc->proj, edi->vecs.radcon.neig);
2176 /* loop over radcon vectors */
2177 for (i = 0; i < edi->vecs.radcon.neig; i++)
2179 /* calculate the projections, radius */
2180 loc->proj[i] = projectx(*edi, xcoll, edi->vecs.radcon.vec[i]);
2181 rad += gmx::square(loc->proj[i] - edi->vecs.radcon.refproj[i]);
2183 rad = sqrt(rad);
2184 /* only correct when radius increased */
2185 if (rad > edi->vecs.radcon.radius)
2187 ratio = edi->vecs.radcon.radius/rad - 1.0;
2189 /* loop over radcon vectors */
2190 for (i = 0; i < edi->vecs.radcon.neig; i++)
2192 /* apply the correction */
2193 loc->proj[i] -= edi->vecs.radcon.refproj[i];
2194 loc->proj[i] /= edi->sav.sqrtm[i];
2195 loc->proj[i] *= ratio;
2197 for (j = 0; j < edi->sav.nr; j++)
2199 svmul(loc->proj[i], edi->vecs.radcon.vec[i][j], vec_dum);
2200 rvec_inc(xcoll[j], vec_dum);
2205 else
2207 edi->vecs.radcon.radius = rad;
2213 static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, int64_t step)
2215 int i;
2218 /* subtract the average positions */
2219 for (i = 0; i < edi->sav.nr; i++)
2221 rvec_dec(xcoll[i], edi->sav.x[i]);
2224 /* apply the constraints */
2225 if (step >= 0)
2227 do_linfix(xcoll, *edi, step);
2229 do_linacc(xcoll, edi);
2230 if (step >= 0)
2232 do_radfix(xcoll, edi);
2234 do_radacc(xcoll, edi);
2235 do_radcon(xcoll, edi);
2237 /* add back the average positions */
2238 for (i = 0; i < edi->sav.nr; i++)
2240 rvec_inc(xcoll[i], edi->sav.x[i]);
2245 namespace
2247 /*!\brief Write out the projections onto the eigenvectors.
2248 * The order of output corresponds to ed_output_legend().
2249 * \param[in] edi The essential dyanmics parameters
2250 * \param[in] fp The output file
2251 * \param[in] rmsd the rmsd to the reference structure
2253 void write_edo(const t_edpar &edi, FILE *fp, real rmsd)
2255 /* Output how well we fit to the reference structure */
2256 fprintf(fp, EDcol_ffmt, rmsd);
2258 for (int i = 0; i < edi.vecs.mon.neig; i++)
2260 fprintf(fp, EDcol_efmt, edi.vecs.mon.xproj[i]);
2263 for (int i = 0; i < edi.vecs.linfix.neig; i++)
2265 fprintf(fp, EDcol_efmt, edi.vecs.linfix.xproj[i]);
2268 for (int i = 0; i < edi.vecs.linacc.neig; i++)
2270 fprintf(fp, EDcol_efmt, edi.vecs.linacc.xproj[i]);
2273 for (int i = 0; i < edi.vecs.radfix.neig; i++)
2275 fprintf(fp, EDcol_efmt, edi.vecs.radfix.xproj[i]);
2277 if (edi.vecs.radfix.neig)
2279 fprintf(fp, EDcol_ffmt, calc_radius(edi.vecs.radfix)); /* fixed increment radius */
2282 for (int i = 0; i < edi.vecs.radacc.neig; i++)
2284 fprintf(fp, EDcol_efmt, edi.vecs.radacc.xproj[i]);
2286 if (edi.vecs.radacc.neig)
2288 fprintf(fp, EDcol_ffmt, calc_radius(edi.vecs.radacc)); /* acceptance radius */
2291 for (int i = 0; i < edi.vecs.radcon.neig; i++)
2293 fprintf(fp, EDcol_efmt, edi.vecs.radcon.xproj[i]);
2295 if (edi.vecs.radcon.neig)
2297 fprintf(fp, EDcol_ffmt, calc_radius(edi.vecs.radcon)); /* contracting radius */
2300 } // namespace
2303 /* Returns if any constraints are switched on */
2304 static bool ed_constraints(EssentialDynamicsType edtype, const t_edpar &edi)
2306 if (edtype == EssentialDynamicsType::EDSampling || edtype == EssentialDynamicsType::Flooding)
2308 return ((edi.vecs.linfix.neig != 0) || (edi.vecs.linacc.neig != 0) ||
2309 (edi.vecs.radfix.neig != 0) || (edi.vecs.radacc.neig != 0) ||
2310 (edi.vecs.radcon.neig != 0));
2312 return false;
2316 /* Copies reference projection 'refproj' to fixed 'initialReferenceProjection' variable for flooding/
2317 * umbrella sampling simulations. */
2318 static void copyEvecReference(t_eigvec* floodvecs, real * initialReferenceProjection)
2320 int i;
2323 if (nullptr == initialReferenceProjection)
2325 snew(initialReferenceProjection, floodvecs->neig);
2328 for (i = 0; i < floodvecs->neig; i++)
2330 initialReferenceProjection[i] = floodvecs->refproj[i];
2335 /* Call on MASTER only. Check whether the essential dynamics / flooding
2336 * groups of the checkpoint file are consistent with the provided .edi file. */
2337 static void crosscheck_edi_file_vs_checkpoint(const gmx_edsam &ed, edsamhistory_t *EDstate)
2339 if (nullptr == EDstate->nref || nullptr == EDstate->nav)
2341 gmx_fatal(FARGS, "Essential dynamics and flooding can only be switched on (or off) at the\n"
2342 "start of a new simulation. If a simulation runs with/without ED constraints,\n"
2343 "it must also continue with/without ED constraints when checkpointing.\n"
2344 "To switch on (or off) ED constraints, please prepare a new .tpr to start\n"
2345 "from without a checkpoint.\n");
2348 for (size_t edinum = 0; edinum < ed.edpar.size(); ++edinum)
2350 /* Check number of atoms in the reference and average structures */
2351 if (EDstate->nref[edinum] != ed.edpar[edinum].sref.nr)
2353 gmx_fatal(FARGS, "The number of reference structure atoms in ED group %c is\n"
2354 "not the same in .cpt (NREF=%d) and .edi (NREF=%d) files!\n",
2355 get_EDgroupChar(edinum+1, 0), EDstate->nref[edinum], ed.edpar[edinum].sref.nr);
2357 if (EDstate->nav[edinum] != ed.edpar[edinum].sav.nr)
2359 gmx_fatal(FARGS, "The number of average structure atoms in ED group %c is\n"
2360 "not the same in .cpt (NREF=%d) and .edi (NREF=%d) files!\n",
2361 get_EDgroupChar(edinum+1, 0), EDstate->nav[edinum], ed.edpar[edinum].sav.nr);
2365 if (gmx::ssize(ed.edpar) != EDstate->nED)
2367 gmx_fatal(FARGS, "The number of essential dynamics / flooding groups is not consistent.\n"
2368 "There are %d ED groups in the .cpt file, but %zu in the .edi file!\n"
2369 "Are you sure this is the correct .edi file?\n", EDstate->nED, ed.edpar.size());
2374 /* The edsamstate struct stores the information we need to make the ED group
2375 * whole again after restarts from a checkpoint file. Here we do the following:
2376 * a) If we did not start from .cpt, we prepare the struct for proper .cpt writing,
2377 * b) if we did start from .cpt, we copy over the last whole structures from .cpt,
2378 * c) in any case, for subsequent checkpoint writing, we set the pointers in
2379 * edsamstate to the x_old arrays, which contain the correct PBC representation of
2380 * all ED structures at the last time step. */
2381 static void init_edsamstate(const gmx_edsam &ed, edsamhistory_t *EDstate)
2383 snew(EDstate->old_sref_p, EDstate->nED);
2384 snew(EDstate->old_sav_p, EDstate->nED);
2386 /* If we did not read in a .cpt file, these arrays are not yet allocated */
2387 if (!EDstate->bFromCpt)
2389 snew(EDstate->nref, EDstate->nED);
2390 snew(EDstate->nav, EDstate->nED);
2393 /* Loop over all ED/flooding data sets (usually only one, though) */
2394 for (int nr_edi = 0; nr_edi < EDstate->nED; nr_edi++)
2396 const auto &edi = ed.edpar[nr_edi];
2397 /* We always need the last reference and average positions such that
2398 * in the next time step we can make the ED group whole again
2399 * if the atoms do not have the correct PBC representation */
2400 if (EDstate->bFromCpt)
2402 /* Copy the last whole positions of reference and average group from .cpt */
2403 for (int i = 0; i < edi.sref.nr; i++)
2405 copy_rvec(EDstate->old_sref[nr_edi][i], edi.sref.x_old[i]);
2407 for (int i = 0; i < edi.sav.nr; i++)
2409 copy_rvec(EDstate->old_sav [nr_edi][i], edi.sav.x_old [i]);
2412 else
2414 EDstate->nref[nr_edi] = edi.sref.nr;
2415 EDstate->nav [nr_edi] = edi.sav.nr;
2418 /* For subsequent checkpoint writing, set the edsamstate pointers to the edi arrays: */
2419 EDstate->old_sref_p[nr_edi] = edi.sref.x_old;
2420 EDstate->old_sav_p [nr_edi] = edi.sav.x_old;
2425 /* Adds 'buf' to 'str' */
2426 static void add_to_string(char **str, const char *buf)
2428 int len;
2431 len = strlen(*str) + strlen(buf) + 1;
2432 srenew(*str, len);
2433 strcat(*str, buf);
2437 static void add_to_string_aligned(char **str, const char *buf)
2439 char buf_aligned[STRLEN];
2441 sprintf(buf_aligned, EDcol_sfmt, buf);
2442 add_to_string(str, buf_aligned);
2446 static void nice_legend(const char ***setname, int *nsets, char **LegendStr, const char *value, const char *unit, char EDgroupchar)
2448 auto tmp = gmx::formatString("%c %s", EDgroupchar, value);
2449 add_to_string_aligned(LegendStr, tmp.c_str());
2450 tmp += gmx::formatString(" (%s)", unit);
2451 (*setname)[*nsets] = gmx_strdup(tmp.c_str());
2452 (*nsets)++;
2456 static void nice_legend_evec(const char ***setname, int *nsets, char **LegendStr, t_eigvec *evec, char EDgroupChar, const char *EDtype)
2458 int i;
2459 char tmp[STRLEN];
2462 for (i = 0; i < evec->neig; i++)
2464 sprintf(tmp, "EV%dprj%s", evec->ieig[i], EDtype);
2465 nice_legend(setname, nsets, LegendStr, tmp, "nm", EDgroupChar);
2470 /* Makes a legend for the xvg output file. Call on MASTER only! */
2471 static void write_edo_legend(gmx_edsam * ed, int nED, const gmx_output_env_t *oenv)
2473 int i;
2474 int nr_edi, nsets, n_flood, n_edsam;
2475 const char **setname;
2476 char buf[STRLEN];
2477 char *LegendStr = nullptr;
2480 auto edi = ed->edpar.begin();
2482 fprintf(ed->edo, "# Output will be written every %d step%s\n", edi->outfrq, edi->outfrq != 1 ? "s" : "");
2484 for (nr_edi = 1; nr_edi <= nED; nr_edi++)
2486 fprintf(ed->edo, "#\n");
2487 fprintf(ed->edo, "# Summary of applied con/restraints for the ED group %c\n", get_EDgroupChar(nr_edi, nED));
2488 fprintf(ed->edo, "# Atoms in average structure: %d\n", edi->sav.nr);
2489 fprintf(ed->edo, "# monitor : %d vec%s\n", edi->vecs.mon.neig, edi->vecs.mon.neig != 1 ? "s" : "");
2490 fprintf(ed->edo, "# LINFIX : %d vec%s\n", edi->vecs.linfix.neig, edi->vecs.linfix.neig != 1 ? "s" : "");
2491 fprintf(ed->edo, "# LINACC : %d vec%s\n", edi->vecs.linacc.neig, edi->vecs.linacc.neig != 1 ? "s" : "");
2492 fprintf(ed->edo, "# RADFIX : %d vec%s\n", edi->vecs.radfix.neig, edi->vecs.radfix.neig != 1 ? "s" : "");
2493 fprintf(ed->edo, "# RADACC : %d vec%s\n", edi->vecs.radacc.neig, edi->vecs.radacc.neig != 1 ? "s" : "");
2494 fprintf(ed->edo, "# RADCON : %d vec%s\n", edi->vecs.radcon.neig, edi->vecs.radcon.neig != 1 ? "s" : "");
2495 fprintf(ed->edo, "# FLOODING : %d vec%s ", edi->flood.vecs.neig, edi->flood.vecs.neig != 1 ? "s" : "");
2497 if (edi->flood.vecs.neig)
2499 /* If in any of the groups we find a flooding vector, flooding is turned on */
2500 ed->eEDtype = EssentialDynamicsType::Flooding;
2502 /* Print what flavor of flooding we will do */
2503 if (0 == edi->flood.tau) /* constant flooding strength */
2505 fprintf(ed->edo, "Efl_null = %g", edi->flood.constEfl);
2506 if (edi->flood.bHarmonic)
2508 fprintf(ed->edo, ", harmonic");
2511 else /* adaptive flooding */
2513 fprintf(ed->edo, ", adaptive");
2516 fprintf(ed->edo, "\n");
2518 ++edi;
2521 /* Print a nice legend */
2522 snew(LegendStr, 1);
2523 LegendStr[0] = '\0';
2524 sprintf(buf, "# %6s", "time");
2525 add_to_string(&LegendStr, buf);
2527 /* Calculate the maximum number of columns we could end up with */
2528 edi = ed->edpar.begin();
2529 nsets = 0;
2530 for (nr_edi = 1; nr_edi <= nED; nr_edi++)
2532 nsets += 5 +edi->vecs.mon.neig
2533 +edi->vecs.linfix.neig
2534 +edi->vecs.linacc.neig
2535 +edi->vecs.radfix.neig
2536 +edi->vecs.radacc.neig
2537 +edi->vecs.radcon.neig
2538 + 6*edi->flood.vecs.neig;
2539 ++edi;
2541 snew(setname, nsets);
2543 /* In the mdrun time step in a first function call (do_flood()) the flooding
2544 * forces are calculated and in a second function call (do_edsam()) the
2545 * ED constraints. To get a corresponding legend, we need to loop twice
2546 * over the edi groups and output first the flooding, then the ED part */
2548 /* The flooding-related legend entries, if flooding is done */
2549 nsets = 0;
2550 if (EssentialDynamicsType::Flooding == ed->eEDtype)
2552 edi = ed->edpar.begin();
2553 for (nr_edi = 1; nr_edi <= nED; nr_edi++)
2555 /* Always write out the projection on the flooding EVs. Of course, this can also
2556 * be achieved with the monitoring option in do_edsam() (if switched on by the
2557 * user), but in that case the positions need to be communicated in do_edsam(),
2558 * which is not necessary when doing flooding only. */
2559 nice_legend(&setname, &nsets, &LegendStr, "RMSD to ref", "nm", get_EDgroupChar(nr_edi, nED) );
2561 for (i = 0; i < edi->flood.vecs.neig; i++)
2563 sprintf(buf, "EV%dprjFLOOD", edi->flood.vecs.ieig[i]);
2564 nice_legend(&setname, &nsets, &LegendStr, buf, "nm", get_EDgroupChar(nr_edi, nED));
2566 /* Output the current reference projection if it changes with time;
2567 * this can happen when flooding is used as harmonic restraint */
2568 if (edi->flood.bHarmonic && edi->flood.referenceProjectionSlope[i] != 0.0)
2570 sprintf(buf, "EV%d ref.prj.", edi->flood.vecs.ieig[i]);
2571 nice_legend(&setname, &nsets, &LegendStr, buf, "nm", get_EDgroupChar(nr_edi, nED));
2574 /* For flooding we also output Efl, Vfl, deltaF, and the flooding forces */
2575 if (0 != edi->flood.tau) /* only output Efl for adaptive flooding (constant otherwise) */
2577 sprintf(buf, "EV%d-Efl", edi->flood.vecs.ieig[i]);
2578 nice_legend(&setname, &nsets, &LegendStr, buf, "kJ/mol", get_EDgroupChar(nr_edi, nED));
2581 sprintf(buf, "EV%d-Vfl", edi->flood.vecs.ieig[i]);
2582 nice_legend(&setname, &nsets, &LegendStr, buf, "kJ/mol", get_EDgroupChar(nr_edi, nED));
2584 if (0 != edi->flood.tau) /* only output deltaF for adaptive flooding (zero otherwise) */
2586 sprintf(buf, "EV%d-deltaF", edi->flood.vecs.ieig[i]);
2587 nice_legend(&setname, &nsets, &LegendStr, buf, "kJ/mol", get_EDgroupChar(nr_edi, nED));
2590 sprintf(buf, "EV%d-FLforces", edi->flood.vecs.ieig[i]);
2591 nice_legend(&setname, &nsets, &LegendStr, buf, "kJ/mol/nm", get_EDgroupChar(nr_edi, nED));
2594 ++edi;
2595 } /* End of flooding-related legend entries */
2597 n_flood = nsets;
2599 /* Now the ED-related entries, if essential dynamics is done */
2600 edi = ed->edpar.begin();
2601 for (nr_edi = 1; nr_edi <= nED; nr_edi++)
2603 if (bNeedDoEdsam(*edi)) /* Only print ED legend if at least one ED option is on */
2605 nice_legend(&setname, &nsets, &LegendStr, "RMSD to ref", "nm", get_EDgroupChar(nr_edi, nED) );
2607 /* Essential dynamics, projections on eigenvectors */
2608 nice_legend_evec(&setname, &nsets, &LegendStr, &edi->vecs.mon, get_EDgroupChar(nr_edi, nED), "MON" );
2609 nice_legend_evec(&setname, &nsets, &LegendStr, &edi->vecs.linfix, get_EDgroupChar(nr_edi, nED), "LINFIX");
2610 nice_legend_evec(&setname, &nsets, &LegendStr, &edi->vecs.linacc, get_EDgroupChar(nr_edi, nED), "LINACC");
2611 nice_legend_evec(&setname, &nsets, &LegendStr, &edi->vecs.radfix, get_EDgroupChar(nr_edi, nED), "RADFIX");
2612 if (edi->vecs.radfix.neig)
2614 nice_legend(&setname, &nsets, &LegendStr, "RADFIX radius", "nm", get_EDgroupChar(nr_edi, nED));
2616 nice_legend_evec(&setname, &nsets, &LegendStr, &edi->vecs.radacc, get_EDgroupChar(nr_edi, nED), "RADACC");
2617 if (edi->vecs.radacc.neig)
2619 nice_legend(&setname, &nsets, &LegendStr, "RADACC radius", "nm", get_EDgroupChar(nr_edi, nED));
2621 nice_legend_evec(&setname, &nsets, &LegendStr, &edi->vecs.radcon, get_EDgroupChar(nr_edi, nED), "RADCON");
2622 if (edi->vecs.radcon.neig)
2624 nice_legend(&setname, &nsets, &LegendStr, "RADCON radius", "nm", get_EDgroupChar(nr_edi, nED));
2627 ++edi;
2628 } /* end of 'pure' essential dynamics legend entries */
2629 n_edsam = nsets - n_flood;
2631 xvgr_legend(ed->edo, nsets, setname, oenv);
2632 sfree(setname);
2634 fprintf(ed->edo, "#\n"
2635 "# Legend for %d column%s of flooding plus %d column%s of essential dynamics data:\n",
2636 n_flood, 1 == n_flood ? "" : "s",
2637 n_edsam, 1 == n_edsam ? "" : "s");
2638 fprintf(ed->edo, "%s", LegendStr);
2639 sfree(LegendStr);
2641 fflush(ed->edo);
2645 /* Init routine for ED and flooding. Calls init_edi in a loop for every .edi-cycle
2646 * contained in the input file, creates a NULL terminated list of t_edpar structures */
2647 std::unique_ptr<gmx::EssentialDynamics> init_edsam(
2648 const gmx::MDLogger &mdlog,
2649 const char *ediFileName,
2650 const char *edoFileName,
2651 const gmx_mtop_t *mtop,
2652 const t_inputrec *ir,
2653 const t_commrec *cr,
2654 gmx::Constraints *constr,
2655 const t_state *globalState,
2656 ObservablesHistory *oh,
2657 const gmx_output_env_t *oenv,
2658 const gmx::StartingBehavior startingBehavior)
2660 int i, avindex;
2661 rvec *x_pbc = nullptr; /* positions of the whole MD system with pbc removed */
2662 rvec *xfit = nullptr, *xstart = nullptr; /* dummy arrays to determine initial RMSDs */
2663 rvec fit_transvec; /* translation ... */
2664 matrix fit_rotmat; /* ... and rotation from fit to reference structure */
2665 rvec *ref_x_old = nullptr; /* helper pointer */
2668 if (MASTER(cr))
2670 fprintf(stderr, "ED: Initializing essential dynamics constraints.\n");
2672 if (oh->edsamHistory != nullptr && oh->edsamHistory->bFromCpt && !gmx_fexist(ediFileName) )
2674 gmx_fatal(FARGS, "The checkpoint file you provided is from an essential dynamics or flooding\n"
2675 "simulation. Please also set the .edi file on the command line with -ei.\n");
2679 GMX_LOG(mdlog.info).asParagraph().
2680 appendText("Activating essential dynamics via files passed to "
2681 "gmx mdrun -edi will change in future to be files passed to "
2682 "gmx grompp and the related .mdp options may change also.");
2684 /* Open input and output files, allocate space for ED data structure */
2685 auto edHandle = ed_open(mtop->natoms, oh, ediFileName, edoFileName, startingBehavior, oenv, cr);
2686 auto ed = edHandle->getLegacyED();
2687 GMX_RELEASE_ASSERT(constr != nullptr, "Must have valid constraints object");
2688 constr->saveEdsamPointer(ed);
2690 /* Needed for initializing radacc radius in do_edsam */
2691 ed->bFirst = TRUE;
2693 /* The input file is read by the master and the edi structures are
2694 * initialized here. Input is stored in ed->edpar. Then the edi
2695 * structures are transferred to the other nodes */
2696 if (MASTER(cr))
2698 /* Initialization for every ED/flooding group. Flooding uses one edi group per
2699 * flooding vector, Essential dynamics can be applied to more than one structure
2700 * as well, but will be done in the order given in the edi file, so
2701 * expect different results for different order of edi file concatenation! */
2702 for (auto &edi : ed->edpar)
2704 init_edi(mtop, &edi);
2705 init_flood(&edi, ed, ir->delta_t);
2709 /* The master does the work here. The other nodes get the positions
2710 * not before dd_partition_system which is called after init_edsam */
2711 if (MASTER(cr))
2713 edsamhistory_t *EDstate = oh->edsamHistory.get();
2715 if (!EDstate->bFromCpt)
2717 /* Remove PBC, make molecule(s) subject to ED whole. */
2718 snew(x_pbc, mtop->natoms);
2719 copy_rvecn(globalState->x.rvec_array(), x_pbc, 0, mtop->natoms);
2720 do_pbc_first_mtop(nullptr, ir->ePBC, globalState->box, mtop, x_pbc);
2722 /* Reset pointer to first ED data set which contains the actual ED data */
2723 auto edi = ed->edpar.begin();
2724 GMX_ASSERT(!ed->edpar.empty(), "Essential dynamics parameters is undefined");
2726 /* Loop over all ED/flooding data sets (usually only one, though) */
2727 for (int nr_edi = 1; nr_edi <= EDstate->nED; nr_edi++)
2729 /* For multiple ED groups we use the output frequency that was specified
2730 * in the first set */
2731 if (nr_edi > 1)
2733 edi->outfrq = ed->edpar.begin()->outfrq;
2736 /* Extract the initial reference and average positions. When starting
2737 * from .cpt, these have already been read into sref.x_old
2738 * in init_edsamstate() */
2739 if (!EDstate->bFromCpt)
2741 /* If this is the first run (i.e. no checkpoint present) we assume
2742 * that the starting positions give us the correct PBC representation */
2743 for (i = 0; i < edi->sref.nr; i++)
2745 copy_rvec(x_pbc[edi->sref.anrs[i]], edi->sref.x_old[i]);
2748 for (i = 0; i < edi->sav.nr; i++)
2750 copy_rvec(x_pbc[edi->sav.anrs[i]], edi->sav.x_old[i]);
2754 /* Now we have the PBC-correct start positions of the reference and
2755 average structure. We copy that over to dummy arrays on which we
2756 can apply fitting to print out the RMSD. We srenew the memory since
2757 the size of the buffers is likely different for every ED group */
2758 srenew(xfit, edi->sref.nr );
2759 srenew(xstart, edi->sav.nr );
2760 if (edi->bRefEqAv)
2762 /* Reference indices are the same as average indices */
2763 ref_x_old = edi->sav.x_old;
2765 else
2767 ref_x_old = edi->sref.x_old;
2769 copy_rvecn(ref_x_old, xfit, 0, edi->sref.nr);
2770 copy_rvecn(edi->sav.x_old, xstart, 0, edi->sav.nr);
2772 /* Make the fit to the REFERENCE structure, get translation and rotation */
2773 fit_to_reference(xfit, fit_transvec, fit_rotmat, &(*edi));
2775 /* Output how well we fit to the reference at the start */
2776 translate_and_rotate(xfit, edi->sref.nr, fit_transvec, fit_rotmat);
2777 fprintf(stderr, "ED: Initial RMSD from reference after fit = %f nm",
2778 rmsd_from_structure(xfit, &edi->sref));
2779 if (EDstate->nED > 1)
2781 fprintf(stderr, " (ED group %c)", get_EDgroupChar(nr_edi, EDstate->nED));
2783 fprintf(stderr, "\n");
2785 /* Now apply the translation and rotation to the atoms on which ED sampling will be performed */
2786 translate_and_rotate(xstart, edi->sav.nr, fit_transvec, fit_rotmat);
2788 /* calculate initial projections */
2789 project(xstart, &(*edi));
2791 /* For the target and origin structure both a reference (fit) and an
2792 * average structure can be provided in make_edi. If both structures
2793 * are the same, make_edi only stores one of them in the .edi file.
2794 * If they differ, first the fit and then the average structure is stored
2795 * in star (or sor), thus the number of entries in star/sor is
2796 * (n_fit + n_av) with n_fit the size of the fitting group and n_av
2797 * the size of the average group. */
2799 /* process target structure, if required */
2800 if (edi->star.nr > 0)
2802 fprintf(stderr, "ED: Fitting target structure to reference structure\n");
2804 /* get translation & rotation for fit of target structure to reference structure */
2805 fit_to_reference(edi->star.x, fit_transvec, fit_rotmat, &(*edi));
2806 /* do the fit */
2807 translate_and_rotate(edi->star.x, edi->star.nr, fit_transvec, fit_rotmat);
2808 if (edi->star.nr == edi->sav.nr)
2810 avindex = 0;
2812 else /* edi->star.nr = edi->sref.nr + edi->sav.nr */
2814 /* The last sav.nr indices of the target structure correspond to
2815 * the average structure, which must be projected */
2816 avindex = edi->star.nr - edi->sav.nr;
2818 rad_project(*edi, &edi->star.x[avindex], &edi->vecs.radcon);
2820 else
2822 rad_project(*edi, xstart, &edi->vecs.radcon);
2825 /* process structure that will serve as origin of expansion circle */
2826 if ( (EssentialDynamicsType::Flooding == ed->eEDtype) && (!edi->flood.bConstForce) )
2828 fprintf(stderr, "ED: Setting center of flooding potential (0 = average structure)\n");
2831 if (edi->sori.nr > 0)
2833 fprintf(stderr, "ED: Fitting origin structure to reference structure\n");
2835 /* fit this structure to reference structure */
2836 fit_to_reference(edi->sori.x, fit_transvec, fit_rotmat, &(*edi));
2837 /* do the fit */
2838 translate_and_rotate(edi->sori.x, edi->sori.nr, fit_transvec, fit_rotmat);
2839 if (edi->sori.nr == edi->sav.nr)
2841 avindex = 0;
2843 else /* edi->sori.nr = edi->sref.nr + edi->sav.nr */
2845 /* For the projection, we need the last sav.nr indices of sori */
2846 avindex = edi->sori.nr - edi->sav.nr;
2849 rad_project(*edi, &edi->sori.x[avindex], &edi->vecs.radacc);
2850 rad_project(*edi, &edi->sori.x[avindex], &edi->vecs.radfix);
2851 if ( (EssentialDynamicsType::Flooding == ed->eEDtype) && (!edi->flood.bConstForce) )
2853 fprintf(stderr, "ED: The ORIGIN structure will define the flooding potential center.\n");
2854 /* Set center of flooding potential to the ORIGIN structure */
2855 rad_project(*edi, &edi->sori.x[avindex], &edi->flood.vecs);
2856 /* We already know that no (moving) reference position was provided,
2857 * therefore we can overwrite refproj[0]*/
2858 copyEvecReference(&edi->flood.vecs, edi->flood.initialReferenceProjection);
2861 else /* No origin structure given */
2863 rad_project(*edi, xstart, &edi->vecs.radacc);
2864 rad_project(*edi, xstart, &edi->vecs.radfix);
2865 if ( (EssentialDynamicsType::Flooding == ed->eEDtype) && (!edi->flood.bConstForce) )
2867 if (edi->flood.bHarmonic)
2869 fprintf(stderr, "ED: A (possibly changing) ref. projection will define the flooding potential center.\n");
2870 for (i = 0; i < edi->flood.vecs.neig; i++)
2872 edi->flood.vecs.refproj[i] = edi->flood.initialReferenceProjection[i];
2875 else
2877 fprintf(stderr, "ED: The AVERAGE structure will define the flooding potential center.\n");
2878 /* Set center of flooding potential to the center of the covariance matrix,
2879 * i.e. the average structure, i.e. zero in the projected system */
2880 for (i = 0; i < edi->flood.vecs.neig; i++)
2882 edi->flood.vecs.refproj[i] = 0.0;
2887 /* For convenience, output the center of the flooding potential for the eigenvectors */
2888 if ( (EssentialDynamicsType::Flooding == ed->eEDtype) && (!edi->flood.bConstForce) )
2890 for (i = 0; i < edi->flood.vecs.neig; i++)
2892 fprintf(stdout, "ED: EV %d flooding potential center: %11.4e", edi->flood.vecs.ieig[i], edi->flood.vecs.refproj[i]);
2893 if (edi->flood.bHarmonic)
2895 fprintf(stdout, " (adding %11.4e/timestep)", edi->flood.referenceProjectionSlope[i]);
2897 fprintf(stdout, "\n");
2901 /* set starting projections for linsam */
2902 rad_project(*edi, xstart, &edi->vecs.linacc);
2903 rad_project(*edi, xstart, &edi->vecs.linfix);
2905 /* Prepare for the next edi data set: */
2906 ++edi;
2908 /* Cleaning up on the master node: */
2909 if (!EDstate->bFromCpt)
2911 sfree(x_pbc);
2913 sfree(xfit);
2914 sfree(xstart);
2916 } /* end of MASTER only section */
2918 if (PAR(cr))
2920 /* Broadcast the essential dynamics / flooding data to all nodes */
2921 broadcast_ed_data(cr, ed);
2923 else
2925 /* In the single-CPU case, point the local atom numbers pointers to the global
2926 * one, so that we can use the same notation in serial and parallel case: */
2927 /* Loop over all ED data sets (usually only one, though) */
2928 for (auto edi = ed->edpar.begin(); edi != ed->edpar.end(); ++edi)
2930 edi->sref.anrs_loc = edi->sref.anrs;
2931 edi->sav.anrs_loc = edi->sav.anrs;
2932 edi->star.anrs_loc = edi->star.anrs;
2933 edi->sori.anrs_loc = edi->sori.anrs;
2934 /* For the same reason as above, make a dummy c_ind array: */
2935 snew(edi->sav.c_ind, edi->sav.nr);
2936 /* Initialize the array */
2937 for (i = 0; i < edi->sav.nr; i++)
2939 edi->sav.c_ind[i] = i;
2941 /* In the general case we will need a different-sized array for the reference indices: */
2942 if (!edi->bRefEqAv)
2944 snew(edi->sref.c_ind, edi->sref.nr);
2945 for (i = 0; i < edi->sref.nr; i++)
2947 edi->sref.c_ind[i] = i;
2950 /* Point to the very same array in case of other structures: */
2951 edi->star.c_ind = edi->sav.c_ind;
2952 edi->sori.c_ind = edi->sav.c_ind;
2953 /* In the serial case, the local number of atoms is the global one: */
2954 edi->sref.nr_loc = edi->sref.nr;
2955 edi->sav.nr_loc = edi->sav.nr;
2956 edi->star.nr_loc = edi->star.nr;
2957 edi->sori.nr_loc = edi->sori.nr;
2961 /* Allocate space for ED buffer variables */
2962 /* Again, loop over ED data sets */
2963 for (auto edi = ed->edpar.begin(); edi != ed->edpar.end(); ++edi)
2965 /* Allocate space for ED buffer variables */
2966 snew_bc(cr, edi->buf, 1); /* MASTER has already allocated edi->buf in init_edi() */
2967 snew(edi->buf->do_edsam, 1);
2969 /* Space for collective ED buffer variables */
2971 /* Collective positions of atoms with the average indices */
2972 snew(edi->buf->do_edsam->xcoll, edi->sav.nr);
2973 snew(edi->buf->do_edsam->shifts_xcoll, edi->sav.nr); /* buffer for xcoll shifts */
2974 snew(edi->buf->do_edsam->extra_shifts_xcoll, edi->sav.nr);
2975 /* Collective positions of atoms with the reference indices */
2976 if (!edi->bRefEqAv)
2978 snew(edi->buf->do_edsam->xc_ref, edi->sref.nr);
2979 snew(edi->buf->do_edsam->shifts_xc_ref, edi->sref.nr); /* To store the shifts in */
2980 snew(edi->buf->do_edsam->extra_shifts_xc_ref, edi->sref.nr);
2983 /* Get memory for flooding forces */
2984 snew(edi->flood.forces_cartesian, edi->sav.nr);
2987 /* Flush the edo file so that the user can check some things
2988 * when the simulation has started */
2989 if (ed->edo)
2991 fflush(ed->edo);
2994 return edHandle;
2998 void do_edsam(const t_inputrec *ir,
2999 int64_t step,
3000 const t_commrec *cr,
3001 rvec xs[],
3002 rvec v[],
3003 const matrix box,
3004 gmx_edsam *ed)
3006 int i, edinr, iupdate = 500;
3007 matrix rotmat; /* rotation matrix */
3008 rvec transvec; /* translation vector */
3009 rvec dv, dx, x_unsh; /* tmp vectors for velocity, distance, unshifted x coordinate */
3010 real dt_1; /* 1/dt */
3011 struct t_do_edsam *buf;
3012 real rmsdev = -1; /* RMSD from reference structure prior to applying the constraints */
3013 gmx_bool bSuppress = FALSE; /* Write .xvg output file on master? */
3016 /* Check if ED sampling has to be performed */
3017 if (ed->eEDtype == EssentialDynamicsType::None)
3019 return;
3022 dt_1 = 1.0/ir->delta_t;
3024 /* Loop over all ED groups (usually one) */
3025 edinr = 0;
3026 for (auto &edi : ed->edpar)
3028 edinr++;
3029 if (bNeedDoEdsam(edi))
3032 buf = edi.buf->do_edsam;
3034 if (ed->bFirst)
3036 /* initialize radacc radius for slope criterion */
3037 buf->oldrad = calc_radius(edi.vecs.radacc);
3040 /* Copy the positions into buf->xc* arrays and after ED
3041 * feed back corrections to the official positions */
3043 /* Broadcast the ED positions such that every node has all of them
3044 * Every node contributes its local positions xs and stores it in
3045 * the collective buf->xcoll array. Note that for edinr > 1
3046 * xs could already have been modified by an earlier ED */
3048 communicate_group_positions(cr, buf->xcoll, buf->shifts_xcoll, buf->extra_shifts_xcoll, PAR(cr) ? buf->bUpdateShifts : TRUE, xs,
3049 edi.sav.nr, edi.sav.nr_loc, edi.sav.anrs_loc, edi.sav.c_ind, edi.sav.x_old, box);
3051 /* Only assembly reference positions if their indices differ from the average ones */
3052 if (!edi.bRefEqAv)
3054 communicate_group_positions(cr, buf->xc_ref, buf->shifts_xc_ref, buf->extra_shifts_xc_ref, PAR(cr) ? buf->bUpdateShifts : TRUE, xs,
3055 edi.sref.nr, edi.sref.nr_loc, edi.sref.anrs_loc, edi.sref.c_ind, edi.sref.x_old, box);
3058 /* If bUpdateShifts was TRUE then the shifts have just been updated in communicate_group_positions.
3059 * We do not need to update the shifts until the next NS step. Note that dd_make_local_ed_indices
3060 * set bUpdateShifts=TRUE in the parallel case. */
3061 buf->bUpdateShifts = FALSE;
3063 /* Now all nodes have all of the ED positions in edi.sav->xcoll,
3064 * as well as the indices in edi.sav.anrs */
3066 /* Fit the reference indices to the reference structure */
3067 if (edi.bRefEqAv)
3069 fit_to_reference(buf->xcoll, transvec, rotmat, &edi);
3071 else
3073 fit_to_reference(buf->xc_ref, transvec, rotmat, &edi);
3076 /* Now apply the translation and rotation to the ED structure */
3077 translate_and_rotate(buf->xcoll, edi.sav.nr, transvec, rotmat);
3079 /* Find out how well we fit to the reference (just for output steps) */
3080 if (do_per_step(step, edi.outfrq) && MASTER(cr))
3082 if (edi.bRefEqAv)
3084 /* Indices of reference and average structures are identical,
3085 * thus we can calculate the rmsd to SREF using xcoll */
3086 rmsdev = rmsd_from_structure(buf->xcoll, &edi.sref);
3088 else
3090 /* We have to translate & rotate the reference atoms first */
3091 translate_and_rotate(buf->xc_ref, edi.sref.nr, transvec, rotmat);
3092 rmsdev = rmsd_from_structure(buf->xc_ref, &edi.sref);
3096 /* update radsam references, when required */
3097 if (do_per_step(step, edi.maxedsteps) && step >= edi.presteps)
3099 project(buf->xcoll, &edi);
3100 rad_project(edi, buf->xcoll, &edi.vecs.radacc);
3101 rad_project(edi, buf->xcoll, &edi.vecs.radfix);
3102 buf->oldrad = -1.e5;
3105 /* update radacc references, when required */
3106 if (do_per_step(step, iupdate) && step >= edi.presteps)
3108 edi.vecs.radacc.radius = calc_radius(edi.vecs.radacc);
3109 if (edi.vecs.radacc.radius - buf->oldrad < edi.slope)
3111 project(buf->xcoll, &edi);
3112 rad_project(edi, buf->xcoll, &edi.vecs.radacc);
3113 buf->oldrad = 0.0;
3115 else
3117 buf->oldrad = edi.vecs.radacc.radius;
3121 /* apply the constraints */
3122 if (step >= edi.presteps && ed_constraints(ed->eEDtype, edi))
3124 /* ED constraints should be applied already in the first MD step
3125 * (which is step 0), therefore we pass step+1 to the routine */
3126 ed_apply_constraints(buf->xcoll, &edi, step+1 - ir->init_step);
3129 /* write to edo, when required */
3130 if (do_per_step(step, edi.outfrq))
3132 project(buf->xcoll, &edi);
3133 if (MASTER(cr) && !bSuppress)
3135 write_edo(edi, ed->edo, rmsdev);
3139 /* Copy back the positions unless monitoring only */
3140 if (ed_constraints(ed->eEDtype, edi))
3142 /* remove fitting */
3143 rmfit(edi.sav.nr, buf->xcoll, transvec, rotmat);
3145 /* Copy the ED corrected positions into the coordinate array */
3146 /* Each node copies its local part. In the serial case, nat_loc is the
3147 * total number of ED atoms */
3148 for (i = 0; i < edi.sav.nr_loc; i++)
3150 /* Unshift local ED coordinate and store in x_unsh */
3151 ed_unshift_single_coord(box, buf->xcoll[edi.sav.c_ind[i]],
3152 buf->shifts_xcoll[edi.sav.c_ind[i]], x_unsh);
3154 /* dx is the ED correction to the positions: */
3155 rvec_sub(x_unsh, xs[edi.sav.anrs_loc[i]], dx);
3157 if (v != nullptr)
3159 /* dv is the ED correction to the velocity: */
3160 svmul(dt_1, dx, dv);
3161 /* apply the velocity correction: */
3162 rvec_inc(v[edi.sav.anrs_loc[i]], dv);
3164 /* Finally apply the position correction due to ED: */
3165 copy_rvec(x_unsh, xs[edi.sav.anrs_loc[i]]);
3168 } /* END of if ( bNeedDoEdsam(edi) ) */
3170 /* Prepare for the next ED group */
3172 } /* END of loop over ED groups */
3174 ed->bFirst = FALSE;